{ "documentType": "codex-security.scan-manifest", "scan": { "artifacts": [ { "mediaType": "application/json", "path": "findings.json", "sha256": "3884e597638c69a493af2c8869cf772ceecdad651eb46e062da9a63ffa6b9314" }, { "mediaType": "application/json", "path": "coverage.json", "sha256": "6a40f0a888d78716b31180cbad762167372a9f7c143d2233a206e5e09d3fc368" } ], "completedAt": "2026-09-08T12:52:54.338810Z", "coverageRef": "coverage.json", "findingsRef": "findings.json", "id": "4c194468-0b5f-4f24-9005-5be211dc0e47", "preservedSources": { "checkpoints/2554140402e8e806d0fc9066ab498f121c3adda4c2fa8a0cc4d9219f906cfb62.json": "9f224890355cb4ad64f6242d008cd5fd0c7fd6b31be7fcdea64be115b40b5f99", "checkpoints/a0a575a67430a289893d5c590e52fae92e5c3e02dced613366160327d22204c0.json": "6b807e93783851cd3c101fc30c19a678461e5641b094b769b43577bf92286f4b", "checkpoints/a465c6ca7aaac4bec30e86579d857186ed255cd095818d961fdd5afa54583c89.json": "54c03e1544bfc060476d9898825855d75766b95f5a06e2e8bb4d99f749d46d92", "checkpoints/a5174fc1c150ed228f8d64feda7151de15b334da83d207370aca233f5758cdc9.json": "a5174fc1c150ed228f8d64feda7151de15b334da83d207370aca233f5758cdc9", "checkpoints/c2b024a503781cf1fe58a44701b8346e1e33b4ebc93c157dd63b9128884149c3.json": "8933660b6786bc90effde1b588bbfa7e2950bc42ddf84bc93bf339bd19f070ab", "checkpoints/c8dd318728ac16e8c75fd8bf79844283c7877274bc241603a3dddd767a39e476.json": "d3926dbe629975bd1fa807abec36f0a422f87f53b4f756af3ed213d689705c82", "checkpoints/e87e912ce792fff133063edb5e07f8efc27f233f100e856cf46aa948380a16fe.json": "ca71c7837bd2465bb08cfc79a0bbf381273eee526a889e3b0dc8586f884dea66" }, "producer": { "name": "codex-security-plugin", "version": "0.1.23" }, "scope": { "artifactsReviewed": [ "apps/backend/src/app.module.ts", "apps/backend/src/application/api-keys/api-keys.service.ts", "apps/backend/src/application/auth/auth.service.ts", "apps/backend/src/application/auth/jwt.strategy.ts", "apps/backend/src/application/controllers/audit.controller.ts", "apps/backend/src/application/controllers/auth.controller.ts", "apps/backend/src/application/controllers/bookings.controller.ts", "apps/backend/src/application/controllers/csv-booking-actions.controller.ts", "apps/backend/src/application/controllers/gdpr.controller.ts", "apps/backend/src/application/controllers/invitations.controller.ts", "apps/backend/src/application/controllers/notifications.controller.ts", "apps/backend/src/application/controllers/organizations.controller.ts", "apps/backend/src/application/controllers/subscriptions.controller.ts", "apps/backend/src/application/controllers/users.controller.ts", "apps/backend/src/application/controllers/webhooks.controller.ts", "apps/backend/src/application/csv-bookings/csv-bookings.module.ts", "apps/backend/src/application/dashboard/dashboard.controller.ts", "apps/backend/src/application/dto/organization.dto.ts", "apps/backend/src/application/dto/subscription.dto.ts", "apps/backend/src/application/dto/user.dto.ts", "apps/backend/src/application/gateways/notifications.gateway.ts", "apps/backend/src/application/guards/api-key-or-jwt.guard.ts", "apps/backend/src/application/guards/feature-flag.guard.ts", "apps/backend/src/application/guards/jwt-auth.guard.ts", "apps/backend/src/application/guards/roles.guard.ts", "apps/backend/src/application/guards/throttle.guard.ts", "apps/backend/src/application/logs/logs.controller.ts", "apps/backend/src/application/mcp/capabilities/account.capabilities.ts", "apps/backend/src/application/mcp/capabilities/admin.capabilities.ts", "apps/backend/src/application/mcp/capabilities/bookings.capabilities.ts", "apps/backend/src/application/mcp/capabilities/knowledge.capabilities.ts", "apps/backend/src/application/mcp/capabilities/rates.capabilities.ts", "apps/backend/src/application/mcp/capability.registry.ts", "apps/backend/src/application/mcp/capability.ts", "apps/backend/src/application/mcp/mcp.controller.ts", "apps/backend/src/application/notifications/notifications.module.ts", "apps/backend/src/application/services/analytics.service.ts", "apps/backend/src/application/services/fuzzy-search.service.ts", "apps/backend/src/application/services/gdpr.service.ts", "apps/backend/src/application/services/invitation.service.ts", "apps/backend/src/application/services/notification.service.ts", "apps/backend/src/application/services/subscription.service.ts", "apps/backend/src/application/services/webhook.service.ts", "apps/backend/src/application/trade-assistant/trade-assistant.controller.ts", "apps/backend/src/application/trade-assistant/trade-assistant.service.ts", "apps/backend/src/domain/entities/subscription.entity.ts", "apps/backend/src/domain/entities/user.entity.ts", "apps/backend/src/domain/services/booking.service.ts", "apps/backend/src/domain/services/capability-access.ts", "apps/backend/src/domain/value-objects/subscription-plan.vo.ts", "apps/backend/src/domain/value-objects/subscription-status.vo.ts", "apps/backend/src/infrastructure/ai/openai-trade.adapter.ts", "apps/backend/src/infrastructure/pdf/pdf.adapter.ts", "apps/backend/src/infrastructure/persistence/typeorm/entities/notification.orm-entity.ts", "apps/backend/src/infrastructure/persistence/typeorm/entities/subscription.orm-entity.ts", "apps/backend/src/infrastructure/persistence/typeorm/mappers/csv-booking.mapper.ts", "apps/backend/src/infrastructure/persistence/typeorm/repositories/csv-booking.repository.ts", "apps/backend/src/infrastructure/persistence/typeorm/repositories/typeorm-notification.repository.ts", "apps/backend/src/infrastructure/persistence/typeorm/repositories/typeorm-subscription.repository.ts", "apps/backend/src/infrastructure/persistence/typeorm/repositories/typeorm-trade-conversation.repository.ts", "apps/backend/src/infrastructure/persistence/typeorm/repositories/typeorm-trade-quota.repository.ts", "apps/backend/src/infrastructure/security/security.config.ts", "apps/backend/src/infrastructure/storage/s3-storage.adapter.ts", "apps/backend/src/infrastructure/stripe/stripe.adapter.ts", "apps/backend/src/main.ts", "apps/frontend/Dockerfile", "apps/frontend/app/[locale]/layout.tsx", "apps/frontend/app/[locale]/login/page.tsx", "apps/frontend/app/api/health/route.ts", "apps/frontend/i18n/navigation.ts", "apps/frontend/i18n/request.ts", "apps/frontend/i18n/routing.ts", "apps/frontend/lib/api/client.ts", "apps/frontend/middleware.ts", "apps/frontend/next.config.js", "apps/frontend/package.json", "apps/frontend/src/components/ExportButton.tsx", "apps/frontend/src/components/assistant/answer-text.tsx", "apps/frontend/src/components/assistant/message-list.tsx", "apps/frontend/src/components/notifications/notification-row.tsx", "apps/frontend/src/components/providers.tsx", "apps/frontend/src/hooks/use-url-state.ts", "apps/frontend/src/lib/api/client.ts", "apps/frontend/src/lib/context/auth-context.tsx", "apps/frontend/src/utils/export.ts", "apps/frontend/tsconfig.json", "apps/log-exporter/Dockerfile", "apps/log-exporter/package.json", "apps/log-exporter/src/index.js", "docker/docker-compose.full.yml", "infra/logging/loki/loki-config.yml", "infra/prod/k8s/base/06-log-exporter.yaml", "infra/prod/k8s/base/08-traefik-middlewares.yaml", "infra/prod/k8s/base/09-ingress.yaml", "infra/prod/k8s/base/10-network-policies.yaml" ], "context": "Mod\u00e8le de menace g\u00e9n\u00e9r\u00e9 depuis le code et revu ind\u00e9pendamment ; aucun mod\u00e8le utilisateur.", "excludePaths": [], "includePaths": [ "." ], "limitations": [ "Couverture source partielle ; aucune attestation d\u2019absence de vuln\u00e9rabilit\u00e9s.", "Fichiers .env/.env.* interdits, non lus.", "Pas d\u2019audit CVE en ligne, de d\u00e9ploiement r\u00e9el, des secrets actifs, permissions cloud ou historique Git." ], "runtimeStatus": "Aucun test de p\u00e9n\u00e9tration ni ex\u00e9cution du produit ; v\u00e9rification des biblioth\u00e8ques install\u00e9es par lecture.", "summary": "Audit statique transversal sur check_secu, r\u00e9vision 8446f879b676b303fdb2891388f88ff7e43f5fea.", "validationMode": "Static source trace" }, "sealedAt": "2026-09-08T12:52:54.338810Z", "startedAt": "2026-09-07T21:29:14.337312Z", "status": "completed", "target": { "displayName": "xpeditis2.0 copy", "kind": "git_revision", "revision": "8446f879b676b303fdb2891388f88ff7e43f5fea", "targetId": "target_sha256_ddfe0183466d4153b86e8f190318b958432df21c7d3bcaec8c57c2564c3f1208" }, "threatModel": { "assets": [ "User sessions, API-key authority, organization booking data and subscription entitlements; API-key/JWT authentication paths are distinct (apps/backend/src/application/guards/api-key-or-jwt.guard.ts:34).", "Booking documents, freight rate integrity, published blog assets, AI conversation history and tool access." ], "assumptions": [ "User origin: requested complete security audit on new check_secu branch from current branch; this independent review performs architecture mapping only. No supplied threat model or knowledge base.", "No first-party SECURITY.md found by resolver inventory; only vendored node_modules policies exist. No .env files read.", "ConfigMap DATABASE_SSL=true and hostssl comments do not mean runtime clients consume TLS: app.module options and startup script omit ssl; CLI data-source consumes true but disables certificate validation (apps/backend/src/app.module.ts:165; apps/backend/scripts/setup/startup.js:13; apps/backend/src/infrastructure/persistence/typeorm/data-source.ts:26; infra/prod/k8s/base/02-configmap-backend.yaml:47).", "ConfigMap AWS_S3_BUCKET=xpeditis-prod-documents affects CSV object loading; separate booking documents/PDF/blog consumers hardcode other buckets. Object-store policies and provisioned bucket existence remain external prerequisites (infra/prod/k8s/base/02-configmap-backend.yaml:71; apps/backend/src/application/services/csv-booking.service.ts:1269; apps/backend/src/application/services/booking-automation.service.ts:100; apps/backend/src/application/controllers/blog.controller.ts:23).", "Current code uses httpOnly auth cookies; repository overview claiming localStorage token architecture is not sufficient evidence of current implementation (apps/backend/src/application/controllers/auth.controller.ts:108; apps/backend/src/application/auth/jwt.strategy.ts:40).", "Coverage is architectural, not a completed vulnerability audit. External IAM, deployed networking, CI secrets, tenant enforcement of every handler, refresh lifecycle and carrier-token entropy/expiry are not fully established by this pass.", "Nest TypeORM / production ConfigMap: DATABASE_HOST/PORT/NAME from ConfigService; DATABASE_SSL declared but absent from TypeORM options => 10.10.1.20:5432/xpeditis_prod; no explicit TLS option. Contr\u00f4le: synchronize:false; server pg_hba controls admission. Runtime factory does not consume DATABASE_SSL; deployment success and ambient driver options remain unknown Sources: apps/backend/src/app.module.ts:165, infra/prod/k8s/base/02-configmap-backend.yaml:44", "TypeORM migration CLI / production migration Job: Job calls compiled data-source; DATABASE_SSL=true from ConfigMap => 10.10.1.20:5432/xpeditis_prod with ssl.rejectUnauthorized=false. Contr\u00f4le: TLS encryption without certificate validation in data-source. Sources: infra/prod/k8s/base/07-migration-job.yaml:52, apps/backend/src/infrastructure/persistence/typeorm/data-source.ts:26", "Startup pg client and migration DataSource / image startup script: DATABASE_* directly consumed; no ssl option => configured PostgreSQL target, including prod target when prod ConfigMap injected. Contr\u00f4le: database credential and server admission. Different TLS behavior from migration Job; Job explicitly documents this at 07-migration-job.yaml:52 Sources: apps/backend/scripts/setup/startup.js:13, apps/backend/scripts/setup/startup.js:40", "CSV object loader / production/object-storage configured: company config metadata.minioObjectKey; AWS_S3_BUCKET from ConfigMap; storage adapter AWS_S3_ENDPOINT => https://fsn1.your-objectstorage.com/xpeditis-prod-documents/{metadata.minioObjectKey}. Contr\u00f4le: S3 credential permissions; fallback to local file on error. Sources: apps/backend/src/infrastructure/carriers/csv-loader/csv-rate-loader.adapter.ts:149, apps/backend/src/infrastructure/storage/s3-storage.adapter.ts:244, infra/prod/k8s/base/02-configmap-backend.yaml:70", "CSV local loader / local and object-store fallback: absolute filePath unchanged; otherwise process.cwd()/src/infrastructure/storage/csv-storage/rates joined with filePath => {cwd}/src/infrastructure/storage/csv-storage/rates/{relative filePath}, or absolute filePath. Contr\u00f4le: host filesystem permissions and administrative configuration authority. Sources: apps/backend/src/infrastructure/carriers/csv-loader/csv-rate-loader.adapter.ts:125, apps/backend/src/infrastructure/carriers/csv-loader/csv-rate-loader.adapter.ts:164, apps/backend/src/infrastructure/carriers/csv-loader/csv-rate-loader.adapter.ts:287", "Booking document upload/download / all S3 deployments including prod: hardcoded bucket; document key constructed in service; endpoint from adapter => xpeditis-documents/csv-bookings/{bookingId}/{documentId}-{originalFilename}; prod endpoint https://fsn1.your-objectstorage.com. Contr\u00f4le: carrier token, ACCEPTED status, password hash when present, document belongs to token booking. AWS_S3_BUCKET=xpeditis-prod-documents does not select this bucket Sources: apps/backend/src/application/services/csv-booking.service.ts:1269, apps/backend/src/application/services/csv-booking.service.ts:848, apps/backend/src/application/services/csv-booking.service.ts:866", "Booking PDF automation / all S3 deployments: hardcoded bucket and booking-derived key => xpeditis-bookings/bookings/{booking.id}/{booking.bookingNumber.value}.pdf. Contr\u00f4le: backend automation and S3 credentials. AWS_S3_BUCKET does not select this bucket Sources: apps/backend/src/application/services/booking-automation.service.ts:98", "Blog image API / all S3 deployments: hardcoded bucket; public route constructs blog-images filename key => xpeditis-blog/blog-images/{filename}. Contr\u00f4le: public publication workflow and S3 credentials. AWS_S3_BUCKET does not select this bucket Sources: apps/backend/src/application/controllers/blog.controller.ts:23, apps/backend/src/application/controllers/blog.controller.ts:27, apps/backend/src/application/controllers/blog.controller.ts:76", "Trade assistant AI / configured OPENAI_API_KEY: fixed Responses endpoint; OPENAI_MODEL defaults gpt-4.1-mini => https://api.openai.com/v1/responses; question/history/passages and invoked tool outcomes. Contr\u00f4le: actor-bound registry invocation; 4 tool rounds, 800 output tokens, store:false, 30 second timeout. Sources: apps/backend/src/infrastructure/ai/openai-trade.adapter.ts:51, apps/backend/src/infrastructure/ai/openai-trade.adapter.ts:115, apps/backend/src/application/trade-assistant/trade-assistant.service.ts:162, apps/backend/src/application/trade-assistant/trade-assistant.service.ts:216" ], "attackerCapabilities": [ "Unauthenticated caller can request public endpoints and supply arbitrary ordinary request input, but is not assumed to possess carrier token, password, Stripe signing secret, administrative API key or deployment control.", "Authenticated organization user controls their requests and AI questions; crossing into another tenant, administrative capability or higher-plan entitlement would be a new authority gain. MCP visibility alone is not permission evidence; registry invocation enforces policy (apps/backend/src/application/mcp/capability.registry.ts:85).", "Privileged CSV configuration/import and release operators are separate conditional workflows; ordinary remote callers are not assumed to control local files, deployment variables, or migration scripts." ], "securityObjectives": [ "Preserve organization and document ownership across API, MCP and AI handlers; evaluate handler-level scoping separately from global authentication.", "Keep public token capabilities scoped to intended booking and action; enforce additional document password/state controls at every document consumer (apps/backend/src/application/services/csv-booking.service.ts:848).", "Bind financial state changes to verified Stripe events; protect credentials and sensitive object contents with actual consumed storage/database configuration.", "Retain effective resource distinctions: CSV configured bucket, document/PDF/blog hardcoded buckets, and distinct database startup versus migration TLS behavior." ], "summary": "Xpeditis freight platform uses Nest API with relational storage, CSV shipping rates, booking documents, subscription payments, MCP and AI assistant. Global ApiKeyOrJwtGuard and throttling protect normal API routes; public carrier links and Stripe webhook have separate authority checks (apps/backend/src/app.module.ts:210; apps/backend/src/application/controllers/csv-booking-actions.controller.ts:28; apps/backend/src/application/controllers/subscriptions.controller.ts:262). Production manifests describe Kubernetes plus private PostgreSQL and external object storage; actual deployment state is not supplied.", "trustBoundaries": [ "Browser to API: JWT extraction accepts httpOnly accessToken cookie; auth endpoints set cookies and security config defaults SameSite=lax with production Secure (apps/backend/src/application/auth/jwt.strategy.ts:40; apps/backend/src/application/controllers/auth.controller.ts:108; apps/backend/src/infrastructure/security/security.config.ts:195). Helmet/CORS/validation are applied at startup (apps/backend/src/main.ts:33; apps/backend/src/main.ts:42; apps/backend/src/main.ts:54).", "External API key caller to application: key validation supplies user context; absent key falls back to JWT (apps/backend/src/application/guards/api-key-or-jwt.guard.ts:34).", "MCP tools/list visibility is separate from invocation enforcement: registry checks role and plan again and parses schema before handler execution, recording audit (apps/backend/src/application/mcp/capability.registry.ts:85; apps/backend/src/application/mcp/capability.registry.ts:100).", "AI invocation is bound to authenticated actor and uses the same capability registry; capability scope is not inherently read-only. Quota reserved before model request (apps/backend/src/application/trade-assistant/trade-assistant.service.ts:146; apps/backend/src/application/trade-assistant/trade-assistant.service.ts:216).", "Carrier email token permits public accept/reject actions; document delivery independently requires accepted booking and password when hash exists (apps/backend/src/application/controllers/csv-booking-actions.controller.ts:28; apps/backend/src/application/services/csv-booking.service.ts:729; apps/backend/src/application/services/csv-booking.service.ts:848).", "Stripe webhook is public and passes raw request body/signature to service, with adapter constructEvent verification using configured webhook secret (apps/backend/src/application/controllers/subscriptions.controller.ts:262; apps/backend/src/infrastructure/stripe/stripe.adapter.ts:251)." ] } }, "schemaVersion": "1.0" }