200 lines
20 KiB
JSON
200 lines
20 KiB
JSON
{
|
|
"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"
|
|
}
|