# Risk map — strapi/strapi

> Canonical page: https://codevetter.com/unpack/strapi/risk-map

# Risk map — strapi/strapi

Scanned commit 93476f908c08d6d3d5215c06483829e3c6da1b32 (2026-10-02). Generated by codevetter codevetter 1.15.0 on 2026-10-02.

Source inspection; upstream code and tests were not executed.

These are source observations and explicitly labeled hypotheses, not confirmed vulnerabilities. Startup and publication are persistence hotspots because they synchronize schemas or replace related rows. Authentication and MCP rely on different enforcement paths, and upload provider operations cross a storage boundary outside database transactions. Configuration compatibility, global state, and CI conditions require focused review when changing these areas.
- Startup has a broad database blast radius: bootstrap runs schema.sync, conditional orphan-morph repairs, and a one-time join-table repair. The registered discard-drafts migration clones/remaps persisted data, and its down implementation throws 'not implemented'. — [packages/core/core/src/Strapi.ts#L475-503](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/Strapi.ts#L475-L503) [packages/core/core/src/providers/registries.ts#L33-38](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/providers/registries.ts#L33-L38) [packages/core/core/src/migrations/database/5.0.0-discard-drafts.ts#L3526-3568](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/migrations/database/5.0.0-discard-drafts.ts#L3526-L3568) [packages/core/core/src/migrations/database/5.0.0-discard-drafts.ts#L3653-3659](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/migrations/database/5.0.0-discard-drafts.ts#L3653-L3659)
- Publishing deletes old published rows before recreating variants and synchronizing multiple relation classes. Correctness depends on retaining repository transaction wrapping; Database.transaction reuses an existing transaction for nested calls and rolls back rejected callbacks. — [packages/core/core/src/services/document-service/repository.ts#L629-660](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/document-service/repository.ts#L629-L660) [packages/core/core/src/services/document-service/repository.ts#L785-787](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/document-service/repository.ts#L785-L787) [packages/core/core/src/services/document-service/common.ts#L8-9](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/document-service/common.ts#L8-L9) [packages/core/database/src/index.ts#L177-215](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/database/src/index.ts#L177-L215)
- auth:false bypasses ordinary authenticate and verify. MCP deliberately uses this route configuration but performs admin-token authentication inside handlePost; edits must preserve that independent boundary and its ability/user propagation. — [packages/core/core/src/services/auth/index.ts#L61-69](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/auth/index.ts#L61-L69) [packages/core/core/src/services/auth/index.ts#L123-133](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/auth/index.ts#L123-L133) [packages/core/core/src/services/mcp/routes.ts#L30-37](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/mcp/routes.ts#L30-L37) [packages/core/core/src/services/mcp/handlers/handlePost.ts#L32-53](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/mcp/handlers/handlePost.ts#L32-L53)
- Hypothesis: a metadata-write failure after successful provider upload could leave stored bytes without a corresponding media row. The inspected uploadFileAndPersist/add sequence writes provider bytes before database metadata, while upload's finally cleans temporary work rather than showing provider compensation. (inferred) — [packages/core/upload/server/src/services/upload.ts#L424-441](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/upload/server/src/services/upload.ts#L424-L441) [packages/core/upload/server/src/services/upload.ts#L575-590](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/upload/server/src/services/upload.ts#L575-L590) [packages/core/upload/server/src/services/upload.ts#L280-288](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/upload/server/src/services/upload.ts#L280-L288)
- Hypothesis: callers passing absolute paths to StrapiFS could escape the intended application root. normalizePath strips leading relative traversal and then calls path.resolve(app.root, normalizedPath), without an explicit containment check in that function; exploitability and caller reachability were not established. (inferred) — [packages/core/core/src/services/fs.ts#L17-33](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/fs.ts#L17-L33) [packages/core/core/src/services/fs.ts#L50-60](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/fs.ts#L50-L60)
- Global instance coupling remains despite guidance preferring injection: createStrapi assigns global.strapi, Document Service repository/common use ambient strapi, and destroy deletes the global and removes all process listeners. This is a source-observed isolation hotspot for multi-instance or lifecycle changes. — [AGENTS.md#L53-57](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/AGENTS.md#L53-L57) [packages/core/core/src/index.ts#L24-25](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/index.ts#L24-L25) [packages/core/core/src/services/document-service/repository.ts#L35-36](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/document-service/repository.ts#L35-L36) [packages/core/core/src/services/document-service/common.ts#L8-9](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/services/document-service/common.ts#L8-L9) [packages/core/core/src/Strapi.ts#L569-578](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/core/core/src/Strapi.ts#L569-L578)
- GraphQL warns when depthLimit/maxLimit are unbounded or invalid, but preserves depthLimit as configured rather than imposing a finite fallback. Landing-page configuration can explicitly enable the local playground in production; custom Apollo configuration is merged into defaults. — [packages/plugins/graphql/server/src/bootstrap.ts#L33-55](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/plugins/graphql/server/src/bootstrap.ts#L33-L55) [packages/plugins/graphql/server/src/bootstrap.ts#L114-125](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/plugins/graphql/server/src/bootstrap.ts#L114-L125) [packages/plugins/graphql/server/src/bootstrap.ts#L203-229](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/packages/plugins/graphql/server/src/bootstrap.ts#L203-L229)
- The TypeScript CI condition checks global or backend twice and omits frontend, although the frontend filter independently matches admin source changes. This is a source-observed job-selection mismatch; actual skipped runs or downstream defects were not verified. — [.github/workflows/tests.yml#L148-173](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/.github/workflows/tests.yml#L148-L173) [.github/filters.yaml#L10-16](https://github.com/strapi/strapi/blob/93476f908c08d6d3d5215c06483829e3c6da1b32/.github/filters.yaml#L10-L16)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
