torusguard 1.0.0 โ 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.torusguard/.manifest.json +196 -78
- package/.torusguard/references/csharp-security.md +41 -0
- package/.torusguard/references/go-security.md +41 -0
- package/.torusguard/references/java-security.md +40 -0
- package/.torusguard/references/polyglot-security-matrix.md +25 -0
- package/.torusguard/references/rust-security.md +40 -0
- package/.torusguard/rules/README.md +93 -62
- package/.torusguard/rules/TG-AUTH-001-weak-password-storage.md +103 -0
- package/.torusguard/rules/TG-AUTH-002-client-only-authorization.md +85 -0
- package/.torusguard/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/.torusguard/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/.torusguard/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/.torusguard/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/.torusguard/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/.torusguard/rules/TG-DB-001-frontend-database-query.md +83 -0
- package/.torusguard/rules/TG-DB-002-privileged-database-credential.md +86 -0
- package/.torusguard/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/.torusguard/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/.torusguard/rules/TG-INPUT-001-missing-server-validation.md +98 -0
- package/.torusguard/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/.torusguard/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/.torusguard/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/.torusguard/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/.torusguard/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/.torusguard/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/.torusguard/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/.torusguard/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/.torusguard/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/.torusguard/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/.torusguard/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/.torusguard/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/.torusguard/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/.torusguard/rules/TG-SEC-002-public-environment-secrets.md +83 -0
- package/.torusguard/rules/TG-SEC-003-tracked-env-file.md +79 -0
- package/.torusguard/rules/TG-SEC-004-sensitive-logging.md +83 -0
- package/.torusguard/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
- package/.torusguard/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
- package/.torusguard/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/.torusguard/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/.torusguard/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/.torusguard/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/.torusguard/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/.torusguard/rules/active/TG-DB-001-frontend-database-query.md +83 -0
- package/.torusguard/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
- package/.torusguard/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/.torusguard/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/.torusguard/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
- package/.torusguard/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/.torusguard/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/.torusguard/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/.torusguard/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/.torusguard/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/.torusguard/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/.torusguard/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/.torusguard/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/.torusguard/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/.torusguard/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/.torusguard/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/.torusguard/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/.torusguard/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/.torusguard/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
- package/.torusguard/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
- package/.torusguard/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
- package/.torusguard/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
- package/.torusguard/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
- package/.torusguard/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
- package/.torusguard/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
- package/.torusguard/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
- package/.torusguard/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
- package/.torusguard/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
- package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
- package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
- package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
- package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
- package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
- package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
- package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
- package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
- package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
- package/.torusguard/rules/custom/.gitkeep +1 -0
- package/.torusguard/rules/custom/README.md +30 -0
- package/.torusguard/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
- package/.torusguard/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
- package/.torusguard/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
- package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
- package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
- package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
- package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
- package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
- package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
- package/.torusguard/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
- package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
- package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
- package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
- package/.torusguard/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
- package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
- package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
- package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
- package/.torusguard/runs/report-latest.html +370 -0
- package/.torusguard/runs/run-20260908-112648-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-112648-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-112648-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260908-112648-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-112722-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-112722-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-112722-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260908-112722-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-113004-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-113004-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-113004-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260908-113004-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-113127-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-113127-audit/manifest.json +13 -0
- package/.torusguard/runs/run-20260908-113127-audit/remediation.md +262 -0
- package/.torusguard/runs/run-20260908-113127-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-115240-audit/apply_plan.md +6 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/diff_summary.md +221 -0
- package/.torusguard/runs/run-20260908-115240-audit/findings.json +1553 -0
- package/.torusguard/runs/run-20260908-115240-audit/findings.md +572 -0
- package/.torusguard/runs/run-20260908-115240-audit/manifest.json +14 -0
- package/.torusguard/runs/run-20260908-115240-audit/recheck.md +91 -0
- package/.torusguard/runs/run-20260908-115240-audit/remediation.md +278 -0
- package/.torusguard/runs/run-20260908-115240-audit/summary.md +5 -0
- package/.torusguard/schemas/golden-recipe.schema.json +75 -0
- package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
- package/.torusguard/scripts/apply_runner.py +332 -0
- package/.torusguard/scripts/audit_runner.py +550 -0
- package/.torusguard/scripts/diff_guard.py +183 -8
- package/.torusguard/scripts/finding_scorer.py +91 -5
- package/.torusguard/scripts/harden_runner.py +353 -0
- package/.torusguard/scripts/html_reporter.py +643 -0
- package/.torusguard/scripts/manifest_builder.py +7 -5
- package/.torusguard/scripts/memory_engine.py +525 -99
- package/.torusguard/scripts/monorepo_detector.py +123 -10
- package/.torusguard/scripts/recheck_runner.py +221 -0
- package/.torusguard/scripts/recipes_runner.py +130 -0
- package/.torusguard/scripts/rules_sync.py +321 -0
- package/.torusguard/scripts/run_manager.py +17 -5
- package/.torusguard/scripts/stack_detect.py +458 -26
- package/.torusguard/skills/torusguard/SKILL.md +42 -42
- package/.torusguard/skills/torusguard/references/csharp-security.md +41 -0
- package/.torusguard/skills/torusguard/references/go-security.md +41 -0
- package/.torusguard/skills/torusguard/references/java-security.md +40 -0
- package/.torusguard/skills/torusguard/references/polyglot-security-matrix.md +25 -0
- package/.torusguard/skills/torusguard/references/rust-security.md +40 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/engine/fixture_manager.py.bak +245 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/master_validation.py.bak +698 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/runner.py.bak +551 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_e2e.py.bak +498 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_qa_v0_6_0.py.bak +572 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_1_scale.py.bak +371 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_2_modern_stacks.py.bak +462 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_3_hardening.py.bak +444 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_0_0_memory.py.bak +302 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_1_0_advanced_memory.py.bak +342 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/skills/torusguard/payload/scripts/harden_runner.py.bak +353 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/tests/test_v0_6_0_governed_remediation.py.bak +353 -0
- package/README.md +344 -410
- package/bin/torusguard.js +195 -21
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +42 -42
- package/skills/torusguard/bootstrap.py +149 -70
- package/skills/torusguard/payload/.manifest.json +196 -78
- package/skills/torusguard/payload/references/csharp-security.md +41 -0
- package/skills/torusguard/payload/references/go-security.md +41 -0
- package/skills/torusguard/payload/references/java-security.md +40 -0
- package/skills/torusguard/payload/references/polyglot-security-matrix.md +25 -0
- package/skills/torusguard/payload/references/rust-security.md +40 -0
- package/skills/torusguard/payload/rules/README.md +93 -62
- package/skills/torusguard/payload/rules/TG-AUTH-001-weak-password-storage.md +103 -0
- package/skills/torusguard/payload/rules/TG-AUTH-002-client-only-authorization.md +85 -0
- package/skills/torusguard/payload/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/skills/torusguard/payload/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/skills/torusguard/payload/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/skills/torusguard/payload/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/skills/torusguard/payload/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/skills/torusguard/payload/rules/TG-DB-001-frontend-database-query.md +83 -0
- package/skills/torusguard/payload/rules/TG-DB-002-privileged-database-credential.md +86 -0
- package/skills/torusguard/payload/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/skills/torusguard/payload/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/skills/torusguard/payload/rules/TG-INPUT-001-missing-server-validation.md +98 -0
- package/skills/torusguard/payload/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/skills/torusguard/payload/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/skills/torusguard/payload/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/skills/torusguard/payload/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/skills/torusguard/payload/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/skills/torusguard/payload/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/skills/torusguard/payload/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/skills/torusguard/payload/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/skills/torusguard/payload/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/skills/torusguard/payload/rules/TG-SEC-002-public-environment-secrets.md +83 -0
- package/skills/torusguard/payload/rules/TG-SEC-003-tracked-env-file.md +79 -0
- package/skills/torusguard/payload/rules/TG-SEC-004-sensitive-logging.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/skills/torusguard/payload/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-DB-001-frontend-database-query.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
- package/skills/torusguard/payload/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/skills/torusguard/payload/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/skills/torusguard/payload/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/skills/torusguard/payload/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
- package/skills/torusguard/payload/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
- package/skills/torusguard/payload/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
- package/skills/torusguard/payload/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
- package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
- package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
- package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
- package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
- package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
- package/skills/torusguard/payload/rules/custom/.gitkeep +1 -0
- package/skills/torusguard/payload/rules/custom/README.md +30 -0
- package/skills/torusguard/payload/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
- package/skills/torusguard/payload/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
- package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
- package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
- package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
- package/skills/torusguard/payload/schemas/golden-recipe.schema.json +75 -0
- package/skills/torusguard/payload/scripts/apply_runner.py +332 -0
- package/skills/torusguard/payload/scripts/audit_runner.py +550 -0
- package/skills/torusguard/payload/scripts/diff_guard.py +183 -8
- package/skills/torusguard/payload/scripts/finding_scorer.py +91 -5
- package/skills/torusguard/payload/scripts/harden_runner.py +353 -0
- package/skills/torusguard/payload/scripts/html_reporter.py +643 -0
- package/skills/torusguard/payload/scripts/manifest_builder.py +7 -5
- package/skills/torusguard/payload/scripts/memory_engine.py +525 -99
- package/skills/torusguard/payload/scripts/monorepo_detector.py +123 -10
- package/skills/torusguard/payload/scripts/recheck_runner.py +221 -0
- package/skills/torusguard/payload/scripts/recipes_runner.py +130 -0
- package/skills/torusguard/payload/scripts/rules_sync.py +321 -0
- package/skills/torusguard/payload/scripts/run_manager.py +17 -5
- package/skills/torusguard/payload/scripts/stack_detect.py +458 -26
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +42 -42
- package/skills/torusguard/payload/skills/torusguard/bootstrap.py +149 -70
- package/skills/torusguard/payload/skills/torusguard/references/csharp-security.md +41 -0
- package/skills/torusguard/payload/skills/torusguard/references/go-security.md +41 -0
- package/skills/torusguard/payload/skills/torusguard/references/java-security.md +40 -0
- package/skills/torusguard/payload/skills/torusguard/references/polyglot-security-matrix.md +25 -0
- package/skills/torusguard/payload/skills/torusguard/references/rust-security.md +40 -0
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# TG-CLIENT-001: Public Production Source Maps
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
|
|
5
|
+
Medium
|
|
6
|
+
|
|
7
|
+
## Applies To
|
|
8
|
+
|
|
9
|
+
- Vite production builds (`build.sourcemap`)
|
|
10
|
+
- Next.js production source map settings (`productionBrowserSourceMaps`)
|
|
11
|
+
- Create React App/Webpack production `devtool` configuration
|
|
12
|
+
- Static hosting/CDN configurations that publish `.map` assets publicly
|
|
13
|
+
- Any SPA/SSR frontend bundle served to untrusted clients
|
|
14
|
+
|
|
15
|
+
## Why It Matters
|
|
16
|
+
|
|
17
|
+
Source maps improve debugging, but can expose internal implementation details.
|
|
18
|
+
Public `.map` files make reverse engineering easier at scale.
|
|
19
|
+
Attackers can quickly recover original symbols, comments, and code structure.
|
|
20
|
+
This increases the efficiency of finding hidden routes, feature flags, and weak points.
|
|
21
|
+
It does not create a vulnerability alone, but it lowers attacker effort materially.
|
|
22
|
+
Browser DevTools cannot be blocked, so exposure must be reduced at build and hosting layers.
|
|
23
|
+
|
|
24
|
+
## What TorusGuard Looks For
|
|
25
|
+
|
|
26
|
+
- Build configs enabling source maps for production bundles
|
|
27
|
+
- Presence of emitted `*.js.map` or `*.css.map` in deploy artifacts
|
|
28
|
+
- CDN/static host rules that allow unauthenticated access to map files
|
|
29
|
+
- Missing split behavior (private error telemetry maps vs public maps)
|
|
30
|
+
- Framework defaults overridden to expose maps in production
|
|
31
|
+
- CI pipelines that upload maps to public artifact locations
|
|
32
|
+
|
|
33
|
+
## Unsafe Example
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// vite.config.ts
|
|
37
|
+
import { defineConfig } from "vite";
|
|
38
|
+
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
build: {
|
|
41
|
+
sourcemap: true
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
// next.config.js
|
|
48
|
+
module.exports = {
|
|
49
|
+
productionBrowserSourceMaps: true
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Safe Example
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// vite.config.ts
|
|
57
|
+
import { defineConfig } from "vite";
|
|
58
|
+
|
|
59
|
+
export default defineConfig({
|
|
60
|
+
build: {
|
|
61
|
+
sourcemap: false
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
// next.config.js
|
|
68
|
+
module.exports = {
|
|
69
|
+
productionBrowserSourceMaps: false
|
|
70
|
+
};
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Remediation
|
|
74
|
+
|
|
75
|
+
1. Disable public production source maps by default in Vite/Next/CRA/Webpack.
|
|
76
|
+
2. If stack-trace symbolication is required, upload maps to a private error-monitoring service only.
|
|
77
|
+
3. Block direct `.map` retrieval on CDN and static hosting layers.
|
|
78
|
+
4. Validate build pipelines do not copy maps into public deployment folders.
|
|
79
|
+
5. Remove already published map files from current and prior versions where feasible.
|
|
80
|
+
6. Document an exception process for temporary debugging in production.
|
|
81
|
+
7. Pair with bundle scanning to ensure sensitive literals are not shipped regardless.
|
|
82
|
+
|
|
83
|
+
## Verification
|
|
84
|
+
|
|
85
|
+
- Build production artifacts and confirm no `*.map` files in public output.
|
|
86
|
+
- Request known map paths in deployed environments and verify denial/404 behavior.
|
|
87
|
+
- Check framework configs (`vite.config`, `next.config`, webpack overrides) for safe values.
|
|
88
|
+
- Confirm telemetry symbolication still works via private upload channels where used.
|
|
89
|
+
- Validate rollback artifacts are also map-free in release storage.
|
|
90
|
+
|
|
91
|
+
## False Positives and Exceptions
|
|
92
|
+
|
|
93
|
+
- Private internal tools served only behind corporate SSO and network controls
|
|
94
|
+
- Short-lived troubleshooting releases with approved exception and explicit expiry
|
|
95
|
+
- Source maps uploaded privately to monitoring vendor, not served publicly
|
|
96
|
+
- Bundles where maps exist on disk but are never deployed to public hosts
|
|
97
|
+
|
|
98
|
+
## Related Rules
|
|
99
|
+
|
|
100
|
+
- `TG-CLIENT-002-sensitive-client-bundle-content.md`
|
|
101
|
+
- `TG-PLATFORM-003-production-stack-trace-exposure.md`
|
|
102
|
+
- `TG-SEC-002-public-environment-secrets.md`
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# TG-CLIENT-002: Sensitive Client Bundle Content
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
|
|
5
|
+
High
|
|
6
|
+
|
|
7
|
+
## Applies To
|
|
8
|
+
|
|
9
|
+
- Frontend JavaScript/TypeScript bundles shipped to browsers
|
|
10
|
+
- React, Next.js, Vite, CRA, and other web client builds
|
|
11
|
+
- Client logs (`console.log`, telemetry breadcrumbs, debug overlays)
|
|
12
|
+
- Embedded config constants and generated runtime environment payloads
|
|
13
|
+
- Source files that may be tree-shaken incorrectly but still leak literals
|
|
14
|
+
|
|
15
|
+
## Why It Matters
|
|
16
|
+
|
|
17
|
+
Anything shipped to the browser is attacker-accessible by design.
|
|
18
|
+
Secrets, tokens, admin keys, or internal endpoints in bundles are effectively public.
|
|
19
|
+
Sensitive debug logs can leak credentials into screenshots and support tickets.
|
|
20
|
+
A single hardcoded secret can enable direct backend or third-party API compromise.
|
|
21
|
+
This is a high-impact exposure class and often immediately exploitable.
|
|
22
|
+
Browser DevTools cannot be blocked, so any client-shipped secret should be treated as compromised.
|
|
23
|
+
|
|
24
|
+
## What TorusGuard Looks For
|
|
25
|
+
|
|
26
|
+
- Hardcoded API keys, bearer tokens, private keys, or signing secrets in client code
|
|
27
|
+
- Usage of server-only env vars in frontend modules
|
|
28
|
+
- `console.log`/`console.debug` outputting JWTs, session tokens, or PII
|
|
29
|
+
- Debug utilities that serialize auth headers or full user objects in production
|
|
30
|
+
- References to admin-only endpoints from unauthenticated client paths
|
|
31
|
+
- Bundle artifacts containing known secret patterns or credential-like strings
|
|
32
|
+
|
|
33
|
+
## Unsafe Example
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// src/api/client.ts
|
|
37
|
+
const ADMIN_TOKEN = "sk_live_9f2a...supersecret";
|
|
38
|
+
|
|
39
|
+
export async function createInvoice(payload: unknown) {
|
|
40
|
+
console.log("using token", ADMIN_TOKEN);
|
|
41
|
+
return fetch("https://api.example.com/admin/invoices", {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${ADMIN_TOKEN}`,
|
|
45
|
+
"Content-Type": "application/json"
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify(payload)
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Safe Example
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// src/api/client.ts
|
|
56
|
+
export async function createInvoice(payload: unknown) {
|
|
57
|
+
return fetch("/api/invoices", {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: { "Content-Type": "application/json" },
|
|
60
|
+
body: JSON.stringify(payload)
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// server route uses server-side credentials only
|
|
65
|
+
app.post("/api/invoices", requireAuth, async (req, res) => {
|
|
66
|
+
const result = await billing.createInvoice(req.user.id, req.body);
|
|
67
|
+
res.json(result);
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Remediation
|
|
72
|
+
|
|
73
|
+
1. Remove all secrets and privileged tokens from client code and build-time env payloads.
|
|
74
|
+
2. Move privileged API calls behind server endpoints with proper authz checks.
|
|
75
|
+
3. Restrict frontend env variables to explicitly public-safe values only.
|
|
76
|
+
4. Strip sensitive console statements in production builds.
|
|
77
|
+
5. Add CI secret scanning for source and compiled bundles.
|
|
78
|
+
6. Rotate any leaked credentials immediately and revoke prior tokens.
|
|
79
|
+
7. Add code review gates that block server-only value usage in client modules.
|
|
80
|
+
8. Educate teams that browser code is always inspectable by users and attackers.
|
|
81
|
+
|
|
82
|
+
## Verification
|
|
83
|
+
|
|
84
|
+
- Inspect built bundles and search for token/key patterns and internal secrets.
|
|
85
|
+
- Run app in production mode and confirm no sensitive console output.
|
|
86
|
+
- Verify privileged operations require server-mediated authentication and authorization.
|
|
87
|
+
- Validate rotated credentials are active and leaked values are revoked.
|
|
88
|
+
- Confirm public env allowlist is enforced in CI/build scripts.
|
|
89
|
+
|
|
90
|
+
## False Positives and Exceptions
|
|
91
|
+
|
|
92
|
+
- Public publishable keys intentionally designed for client use (documented by vendor)
|
|
93
|
+
- Fake/sample credentials used only in local demo code outside production builds
|
|
94
|
+
- Debug logs in non-production branches that are stripped before release
|
|
95
|
+
- Internal tools with private distribution, if risk accepted explicitly
|
|
96
|
+
|
|
97
|
+
## Related Rules
|
|
98
|
+
|
|
99
|
+
- `TG-SEC-001-hardcoded-secrets.md`
|
|
100
|
+
- `TG-SEC-002-public-environment-secrets.md`
|
|
101
|
+
- `TG-CLIENT-001-public-production-source-maps.md`
|
|
102
|
+
- `TG-AUTH-002-client-only-authorization.md`
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# TG-DB-001: Frontend Database Query Logic
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
High
|
|
5
|
+
|
|
6
|
+
## Applies To
|
|
7
|
+
- Frontend source paths such as `src/`, `app/`, `pages/`, `components/`, `client/`, `public/`
|
|
8
|
+
- Browser-executed JavaScript and TypeScript bundles
|
|
9
|
+
- SSR-hybrid projects where code placement can blur server/client boundaries
|
|
10
|
+
- Shared utility modules imported by frontend entry points
|
|
11
|
+
|
|
12
|
+
## Why It Matters
|
|
13
|
+
Executing SQL construction or raw database access logic in frontend code exposes internal schema assumptions and trust boundaries.
|
|
14
|
+
Even if direct DB connectivity fails in browsers, query logic can leak sensitive structure, encourage insecure architecture, and lead to credential exposure attempts.
|
|
15
|
+
Database interaction must stay on trusted server infrastructure with controlled authorization.
|
|
16
|
+
|
|
17
|
+
## What TorusGuard Looks For
|
|
18
|
+
- SQL strings (`SELECT`, `INSERT`, `UPDATE`, `DELETE`) in frontend-scoped files
|
|
19
|
+
- Query builders or DB clients imported into client-rendered modules
|
|
20
|
+
- Functions assembling SQL fragments from user input in browser code
|
|
21
|
+
- Mentions of table names, admin joins, or migration SQL in UI components
|
|
22
|
+
- Direct network calls from frontend intended for database endpoints
|
|
23
|
+
|
|
24
|
+
## Unsafe Example
|
|
25
|
+
```ts
|
|
26
|
+
// src/components/UserLookup.tsx
|
|
27
|
+
export function loadUserByEmail(email: string) {
|
|
28
|
+
const sql = `SELECT id, role FROM users WHERE email = '${email}' LIMIT 1`;
|
|
29
|
+
|
|
30
|
+
return fetch("/db/query", {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: { "content-type": "application/json" },
|
|
33
|
+
body: JSON.stringify({ sql }),
|
|
34
|
+
}).then((r) => r.json());
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Safe Example
|
|
39
|
+
```ts
|
|
40
|
+
// src/components/UserLookup.tsx
|
|
41
|
+
export function loadUserByEmail(email: string) {
|
|
42
|
+
return fetch("/api/users/lookup", {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: { "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify({ email }),
|
|
46
|
+
}).then((r) => r.json());
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// server/routes/users.ts
|
|
52
|
+
app.post("/api/users/lookup", async (req, res) => {
|
|
53
|
+
const user = await userRepo.findByEmail(req.body.email);
|
|
54
|
+
res.json({ id: user?.id, role: user?.role ?? "none" });
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Remediation (numbered)
|
|
59
|
+
1. Remove SQL strings and database query logic from frontend-scoped files.
|
|
60
|
+
2. Move all data access into backend APIs, repositories, or service layers.
|
|
61
|
+
3. Validate and authorize request parameters on the server before querying.
|
|
62
|
+
4. Return minimal response shapes needed by the UI.
|
|
63
|
+
5. Review frontend imports to prevent accidental DB client inclusion.
|
|
64
|
+
6. Add static checks that disallow SQL keywords in client-targeted directories.
|
|
65
|
+
7. Document architecture boundaries between browser code and data layers.
|
|
66
|
+
|
|
67
|
+
## Verification
|
|
68
|
+
- Scan frontend paths for SQL keywords and DB client imports.
|
|
69
|
+
- Confirm browser bundles contain no query builders or SQL literals.
|
|
70
|
+
- Validate data retrieval flows through authenticated backend endpoints.
|
|
71
|
+
- Test unauthorized requests to ensure server-side access controls hold.
|
|
72
|
+
- Review code ownership and lint rules enforcing client/server separation.
|
|
73
|
+
|
|
74
|
+
## False Positives and Exceptions
|
|
75
|
+
- Static tutorial snippets in markdown may contain SQL and are non-executable.
|
|
76
|
+
- Demo strings in tests are acceptable if isolated from production bundles.
|
|
77
|
+
- Client files that only reference SQL terms in copy text are low risk.
|
|
78
|
+
- Exceptions should be time-bound and approved by architecture owners.
|
|
79
|
+
|
|
80
|
+
## Related Rules
|
|
81
|
+
- [TG-DB-002](./TG-DB-002-privileged-database-credential.md) - Privileged DB credentials in browser exposure
|
|
82
|
+
- [TG-DB-003](./TG-DB-003-frontend-admin-sdk.md) - Admin/server SDK usage in frontend code
|
|
83
|
+
- [TG-SEC-002](./TG-SEC-002-public-environment-secrets.md) - Public-prefixed secret leakage
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# TG-DB-002: Privileged Database Credential in Browser Context
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
Critical
|
|
5
|
+
|
|
6
|
+
## Applies To
|
|
7
|
+
- Browser-executed code in frontend apps and static assets
|
|
8
|
+
- Public environment variables consumed by client bundles
|
|
9
|
+
- Mobile web, desktop web, and embedded webview clients
|
|
10
|
+
- Shared modules imported into client-side runtime
|
|
11
|
+
|
|
12
|
+
## Why It Matters
|
|
13
|
+
Privileged database credentials in browser-accessible code grant attackers direct or indirect control over sensitive data stores.
|
|
14
|
+
Service-role keys and admin database URLs typically bypass row-level access controls and can expose full datasets.
|
|
15
|
+
Because frontend artifacts are publicly retrievable, embedded privileged credentials should be treated as compromised.
|
|
16
|
+
|
|
17
|
+
## What TorusGuard Looks For
|
|
18
|
+
- Service-role keys and admin tokens referenced in frontend code
|
|
19
|
+
- Database URLs containing usernames/passwords in browser-executed modules
|
|
20
|
+
- Public env variables with names such as:
|
|
21
|
+
- `NEXT_PUBLIC_DATABASE_URL`
|
|
22
|
+
- `VITE_SUPABASE_SERVICE_ROLE_KEY`
|
|
23
|
+
- `REACT_APP_ADMIN_DB_TOKEN`
|
|
24
|
+
- Client initialization using elevated credentials intended for server trust zones
|
|
25
|
+
- Fallback credential constants used when env vars are missing
|
|
26
|
+
|
|
27
|
+
## Unsafe Example
|
|
28
|
+
```ts
|
|
29
|
+
// src/lib/dbClient.ts
|
|
30
|
+
import { createClient } from "@supabase/supabase-js";
|
|
31
|
+
|
|
32
|
+
const url = process.env.NEXT_PUBLIC_DATABASE_URL!;
|
|
33
|
+
const serviceRole = process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!;
|
|
34
|
+
|
|
35
|
+
export const db = createClient(url, serviceRole, {
|
|
36
|
+
auth: { persistSession: false },
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Safe Example
|
|
41
|
+
```ts
|
|
42
|
+
// src/lib/publicClient.ts
|
|
43
|
+
import { createClient } from "@supabase/supabase-js";
|
|
44
|
+
|
|
45
|
+
const url = process.env.NEXT_PUBLIC_SUPABASE_URL!;
|
|
46
|
+
const anonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
|
|
47
|
+
|
|
48
|
+
export const publicDb = createClient(url, anonKey);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// server/lib/adminDb.ts
|
|
53
|
+
import { createClient } from "@supabase/supabase-js";
|
|
54
|
+
|
|
55
|
+
export const adminDb = createClient(
|
|
56
|
+
process.env.SUPABASE_URL!,
|
|
57
|
+
process.env.SUPABASE_SERVICE_ROLE_KEY!,
|
|
58
|
+
);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Remediation (numbered)
|
|
62
|
+
1. Remove privileged DB credentials from all frontend and public env sources.
|
|
63
|
+
2. Rotate exposed service-role keys, passwords, and privileged tokens immediately.
|
|
64
|
+
3. Migrate privileged operations to backend-only services and APIs.
|
|
65
|
+
4. Use least-privilege client credentials (anonymous/public keys) in browser code.
|
|
66
|
+
5. Audit access logs for misuse during exposure window.
|
|
67
|
+
6. Enforce CI policy blocking privileged credential names in public scopes.
|
|
68
|
+
7. Add architecture documentation defining credential trust boundaries.
|
|
69
|
+
|
|
70
|
+
## Verification
|
|
71
|
+
- Inspect client bundles and source maps for privileged credential artifacts.
|
|
72
|
+
- Confirm frontend uses only non-privileged credentials and constrained APIs.
|
|
73
|
+
- Validate server-only secrets are loaded from private runtime environments.
|
|
74
|
+
- Test rotated privileged credentials and verify old keys are rejected.
|
|
75
|
+
- Review monitoring for anomalous database access during and after remediation.
|
|
76
|
+
|
|
77
|
+
## False Positives and Exceptions
|
|
78
|
+
- Public anonymous keys may look secret-like but are intentionally non-privileged.
|
|
79
|
+
- Documentation examples can trigger detections; verify they are non-operational.
|
|
80
|
+
- Local-only sandbox credentials are still risky if bundled into distributed builds.
|
|
81
|
+
- Exceptions require security approval, owner assignment, and expiration date.
|
|
82
|
+
|
|
83
|
+
## Related Rules
|
|
84
|
+
- [TG-SEC-001](./TG-SEC-001-hardcoded-secrets.md) - Hardcoded secrets in tracked source
|
|
85
|
+
- [TG-SEC-002](./TG-SEC-002-public-environment-secrets.md) - Secrets in public env namespaces
|
|
86
|
+
- [TG-DB-003](./TG-DB-003-frontend-admin-sdk.md) - Admin SDK usage in frontend runtime
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# TG-DB-003: Frontend Use of Admin or Server-Only Database SDKs
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
Critical
|
|
5
|
+
|
|
6
|
+
## Applies To
|
|
7
|
+
- Frontend directories such as `src/`, `app/`, `pages/`, `components/`, `client/`, `public/`
|
|
8
|
+
- Browser bundles in React, Next.js client components, Vite, and CRA
|
|
9
|
+
- Shared package imports consumed by client entry points
|
|
10
|
+
- Build systems that can accidentally include server-only dependencies
|
|
11
|
+
|
|
12
|
+
## Why It Matters
|
|
13
|
+
Admin SDKs and server drivers are designed for trusted environments and often assume unrestricted credentials and network access.
|
|
14
|
+
Using packages like Firebase Admin, Prisma, or `pg` in frontend paths risks exposing privileged behavior, credentials, and internal data models.
|
|
15
|
+
Even failed browser execution can leak sensitive implementation details and weaken architectural boundaries.
|
|
16
|
+
|
|
17
|
+
## What TorusGuard Looks For
|
|
18
|
+
- Imports of server-only SDKs in frontend-targeted files:
|
|
19
|
+
- `firebase-admin`
|
|
20
|
+
- `@prisma/client`
|
|
21
|
+
- `pg`
|
|
22
|
+
- Initialization logic for admin clients in UI components or client utilities
|
|
23
|
+
- Conditional imports attempting to bypass bundler checks in browser code
|
|
24
|
+
- Code patterns that create server DB connections in frontend modules
|
|
25
|
+
- Shared files that instantiate privileged clients and are imported by frontend
|
|
26
|
+
|
|
27
|
+
## Unsafe Example
|
|
28
|
+
```ts
|
|
29
|
+
// src/app/dashboard/adminMetrics.tsx
|
|
30
|
+
import { PrismaClient } from "@prisma/client";
|
|
31
|
+
import { Client } from "pg";
|
|
32
|
+
|
|
33
|
+
const prisma = new PrismaClient();
|
|
34
|
+
const pgClient = new Client({
|
|
35
|
+
connectionString: process.env.NEXT_PUBLIC_DATABASE_URL,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export async function loadMetrics() {
|
|
39
|
+
await pgClient.connect();
|
|
40
|
+
const result = await prisma.user.count();
|
|
41
|
+
return { users: result };
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Safe Example
|
|
46
|
+
```ts
|
|
47
|
+
// src/app/dashboard/adminMetrics.tsx
|
|
48
|
+
export async function loadMetrics() {
|
|
49
|
+
const res = await fetch("/api/admin/metrics", { method: "GET" });
|
|
50
|
+
return res.json();
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// server/routes/adminMetrics.ts
|
|
56
|
+
import { PrismaClient } from "@prisma/client";
|
|
57
|
+
|
|
58
|
+
const prisma = new PrismaClient();
|
|
59
|
+
|
|
60
|
+
app.get("/api/admin/metrics", async (_req, res) => {
|
|
61
|
+
const users = await prisma.user.count();
|
|
62
|
+
res.json({ users });
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Remediation (numbered)
|
|
67
|
+
1. Remove server-only SDK imports from frontend and browser-targeted modules.
|
|
68
|
+
2. Relocate privileged data access to backend routes, jobs, or server actions.
|
|
69
|
+
3. Ensure frontend calls authenticated backend endpoints for required data.
|
|
70
|
+
4. Restrict server-only dependencies to backend package boundaries.
|
|
71
|
+
5. Configure bundler/lint rules to block admin SDK imports in frontend paths.
|
|
72
|
+
6. Rotate credentials if admin SDK usage exposed privileged config values.
|
|
73
|
+
7. Add architecture tests validating strict client/server dependency separation.
|
|
74
|
+
|
|
75
|
+
## Verification
|
|
76
|
+
- Scan frontend directories for imports of `firebase-admin`, Prisma, and `pg`.
|
|
77
|
+
- Confirm build output excludes server-only database packages in client chunks.
|
|
78
|
+
- Validate admin operations execute only on server infrastructure.
|
|
79
|
+
- Run access-control tests against backend endpoints exposing admin data.
|
|
80
|
+
- Review dependency graphs to ensure no frontend transitive path to admin SDKs.
|
|
81
|
+
|
|
82
|
+
## False Positives and Exceptions
|
|
83
|
+
- Type-only imports can appear suspicious; verify they are erased at build time.
|
|
84
|
+
- Documentation snippets in markdown are non-runtime and may be acceptable.
|
|
85
|
+
- Server components must be verified carefully to avoid accidental client inclusion.
|
|
86
|
+
- Exceptions require documented risk acceptance and periodic security review.
|
|
87
|
+
|
|
88
|
+
## Related Rules
|
|
89
|
+
- [TG-DB-001](./TG-DB-001-frontend-database-query.md) - Frontend SQL/query logic anti-pattern
|
|
90
|
+
- [TG-DB-002](./TG-DB-002-privileged-database-credential.md) - Privileged credential exposure in browser
|
|
91
|
+
- [TG-SEC-001](./TG-SEC-001-hardcoded-secrets.md) - Hardcoded sensitive literals in source
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: TG-DB-004
|
|
3
|
+
title: Missing Tenant Query Isolation in Multi-Tenant Models
|
|
4
|
+
category: data-access-orm
|
|
5
|
+
severity: Critical
|
|
6
|
+
confidence: Confirmed
|
|
7
|
+
frameworks:
|
|
8
|
+
- django
|
|
9
|
+
- drf
|
|
10
|
+
- fastapi
|
|
11
|
+
- flask
|
|
12
|
+
- sqlalchemy
|
|
13
|
+
cwe: CWE-284
|
|
14
|
+
asvs_v4: V4.1.3
|
|
15
|
+
nist_ssdf: PW.5.1
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# TG-DB-004: Missing Tenant Query Isolation in Multi-Tenant Models
|
|
19
|
+
|
|
20
|
+
## ๐จ Problem Statement
|
|
21
|
+
Applications built on a multi-tenant architecture often fail to scope database lookups (`SELECT`, `UPDATE`, `DELETE`) by the current authenticated tenant. Allowing a direct primary key (ID) lookup without a composite tenant filter allows Insecure Direct Object Reference (IDOR) attacks, enabling users to access or modify data belonging to other tenants.
|
|
22
|
+
|
|
23
|
+
> **Tuning Guardrails (v0.5.6):**
|
|
24
|
+
> - **DO NOT flag** every primary-key lookup.
|
|
25
|
+
> - **ESCALATE** when tenant-owned data can be loaded or modified without a verified tenant scope.
|
|
26
|
+
> - **DETECT** established tenant-scoped managers, repositories, `get_queryset()`, dependency injection, or parent-resource ownership checks.
|
|
27
|
+
> - **MARK** complex multi-layer scope flows as `Needs Review` instead of `Confirmed` when source-only proof is inadequate.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## ๐ฅ Adversarial Threat & Exploitation
|
|
32
|
+
An attacker from Tenant B supplies the record UUID of a confidential document belonging to Tenant A:
|
|
33
|
+
```http
|
|
34
|
+
GET /api/v1/invoices/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d HTTP/1.1
|
|
35
|
+
Host: saas.example.com
|
|
36
|
+
Authorization: Bearer <Tenant_B_JWT>
|
|
37
|
+
```
|
|
38
|
+
If the backend performs `session.get(Invoice, invoice_id)` or `Invoice.objects.get(id=invoice_id)` without scoping to `tenant_id=current_user.tenant_id`, the invoice belonging to Tenant A is returned to the attacker.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## ๐ ๏ธ Framework-Native Remediations
|
|
43
|
+
|
|
44
|
+
### ๐ SQLAlchemy (Scoped Tenant Queries)
|
|
45
|
+
|
|
46
|
+
#### โ Unsafe Pattern
|
|
47
|
+
```python
|
|
48
|
+
# Unsafe: Global primary key lookup without tenant filter
|
|
49
|
+
@app.get("/invoices/{invoice_id}")
|
|
50
|
+
def get_invoice(invoice_id: str, db: Session = Depends(get_db), user: User = Depends(get_current_user)):
|
|
51
|
+
invoice = db.query(Invoice).filter(Invoice.id == invoice_id).first()
|
|
52
|
+
if not invoice:
|
|
53
|
+
raise HTTPException(status_code=404, detail="Invoice not found")
|
|
54
|
+
return invoice
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### โ
Safe Remediation
|
|
58
|
+
```python
|
|
59
|
+
# Safe: Enforce tenant scoping on every query filter
|
|
60
|
+
@app.get("/invoices/{invoice_id}")
|
|
61
|
+
def get_invoice(invoice_id: str, db: Session = Depends(get_db), user: User = Depends(get_current_user)):
|
|
62
|
+
invoice = (
|
|
63
|
+
db.query(Invoice)
|
|
64
|
+
.filter(Invoice.id == invoice_id, Invoice.tenant_id == user.tenant_id)
|
|
65
|
+
.first()
|
|
66
|
+
)
|
|
67
|
+
if not invoice:
|
|
68
|
+
raise HTTPException(status_code=404, detail="Invoice not found")
|
|
69
|
+
return invoice
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### ๐ Django ORM (Scoped Manager / ViewSet Queryset)
|
|
75
|
+
|
|
76
|
+
#### โ Unsafe Pattern
|
|
77
|
+
```python
|
|
78
|
+
# Unsafe: Global queryset in DRF ViewSet
|
|
79
|
+
class InvoiceViewSet(viewsets.ModelViewSet):
|
|
80
|
+
queryset = Invoice.objects.all() # Exposes all tenant records
|
|
81
|
+
serializer_class = InvoiceSerializer
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### โ
Safe Remediation
|
|
85
|
+
```python
|
|
86
|
+
# Safe: Override get_queryset to enforce tenant boundary on every request
|
|
87
|
+
class InvoiceViewSet(viewsets.ModelViewSet):
|
|
88
|
+
serializer_class = InvoiceSerializer
|
|
89
|
+
permission_classes = [permissions.IsAuthenticated]
|
|
90
|
+
|
|
91
|
+
def get_queryset(self):
|
|
92
|
+
# Strictly scope lookups to authenticated user's organization
|
|
93
|
+
return Invoice.objects.filter(tenant=self.request.user.tenant)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## ๐งช Verification & Reproduction
|
|
99
|
+
1. Send request with valid Tenant B token requesting Tenant A resource ID:
|
|
100
|
+
```bash
|
|
101
|
+
curl -H "Authorization: Bearer <Tenant_B_Token>" http://localhost:8000/invoices/<Tenant_A_UUID>
|
|
102
|
+
```
|
|
103
|
+
2. **Assertion:** Request must return `404 Not Found`, denying access to cross-tenant data.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# TG-INPUT-001: Missing Server-Side Validation
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
High
|
|
5
|
+
|
|
6
|
+
## Applies To
|
|
7
|
+
- REST and GraphQL API handlers
|
|
8
|
+
- Form-processing backend endpoints
|
|
9
|
+
- Message queue consumers that accept external payloads
|
|
10
|
+
- Admin/import endpoints that trust UI validation
|
|
11
|
+
|
|
12
|
+
## Why It Matters
|
|
13
|
+
Client-side checks are easy to bypass because attackers can send crafted requests directly to backend endpoints.
|
|
14
|
+
When the server does not validate required fields, data type, length, format, range, and allowed values, malicious input can trigger account takeover paths, integrity failures, and downstream injection vulnerabilities.
|
|
15
|
+
Server-side validation is also required to keep business rules enforceable when multiple clients, scripts, and integrations call the same APIs.
|
|
16
|
+
|
|
17
|
+
## What TorusGuard Looks For
|
|
18
|
+
- Request data read from `req.body`, `req.query`, `req.params`, headers, or raw payloads without schema validation.
|
|
19
|
+
- Validation done only in frontend files while backend endpoint accepts the same fields blindly.
|
|
20
|
+
- Direct persistence of user-provided objects with broad spread operators.
|
|
21
|
+
- Type coercion and fallback logic that silently accepts invalid values.
|
|
22
|
+
- Missing allowlists for enum-like fields such as role, status, country code, or operation type.
|
|
23
|
+
|
|
24
|
+
## Unsafe Example
|
|
25
|
+
```js
|
|
26
|
+
// Express route that trusts client validation
|
|
27
|
+
app.post("/api/profile", async (req, res) => {
|
|
28
|
+
const { displayName, age, newsletter, role } = req.body;
|
|
29
|
+
|
|
30
|
+
// No server-side validation:
|
|
31
|
+
// - displayName could be extremely long or contain control chars
|
|
32
|
+
// - age could be negative or non-numeric
|
|
33
|
+
// - newsletter could be arbitrary string
|
|
34
|
+
// - role could be escalated to "admin"
|
|
35
|
+
const updated = await db.user.update({
|
|
36
|
+
where: { id: req.user.id },
|
|
37
|
+
data: { displayName, age, newsletter, role }
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
res.json({ ok: true, user: updated });
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Safe Example
|
|
45
|
+
```js
|
|
46
|
+
import { z } from "zod";
|
|
47
|
+
|
|
48
|
+
const updateProfileSchema = z.object({
|
|
49
|
+
displayName: z.string().min(2).max(60).regex(/^[a-zA-Z0-9 _.-]+$/),
|
|
50
|
+
age: z.number().int().min(13).max(120),
|
|
51
|
+
newsletter: z.boolean(),
|
|
52
|
+
role: z.enum(["user"]) // client cannot self-assign privileged roles
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
app.post("/api/profile", async (req, res) => {
|
|
56
|
+
const parsed = updateProfileSchema.safeParse(req.body);
|
|
57
|
+
if (!parsed.success) {
|
|
58
|
+
return res.status(400).json({
|
|
59
|
+
ok: false,
|
|
60
|
+
error: "Invalid input",
|
|
61
|
+
details: parsed.error.issues
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { displayName, age, newsletter } = parsed.data;
|
|
66
|
+
const updated = await db.user.update({
|
|
67
|
+
where: { id: req.user.id },
|
|
68
|
+
data: { displayName, age, newsletter }
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
res.json({ ok: true, user: updated });
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Remediation
|
|
76
|
+
1. Define strict server-side schemas for every externally reachable input surface.
|
|
77
|
+
2. Validate before business logic, authorization decisions, and database writes.
|
|
78
|
+
3. Enforce field allowlists; reject unexpected keys rather than silently ignoring them.
|
|
79
|
+
4. Apply normalization after validation (trim, case-fold, canonical forms) where needed.
|
|
80
|
+
5. Centralize reusable validators for shared payloads to prevent drift across endpoints.
|
|
81
|
+
6. Return clear but non-sensitive validation errors, and log rejection metrics for monitoring.
|
|
82
|
+
|
|
83
|
+
## Verification
|
|
84
|
+
- Send malformed payloads directly with `curl` or API clients, bypassing the web UI.
|
|
85
|
+
- Confirm invalid types, out-of-range values, and unknown fields return `400`.
|
|
86
|
+
- Attempt privilege-related field tampering and verify values are rejected or ignored safely.
|
|
87
|
+
- Run integration tests covering boundary values and negative cases.
|
|
88
|
+
- Ensure validation runs for all entry paths, including batch/import and background worker routes.
|
|
89
|
+
|
|
90
|
+
## False Positives and Exceptions
|
|
91
|
+
- Internal service-to-service endpoints may appear unvalidated but can be acceptable if strong contract validation is enforced at the gateway and mutual trust boundaries are documented.
|
|
92
|
+
- Auto-generated API frameworks sometimes perform implicit validation; keep explicit schema definitions for auditability.
|
|
93
|
+
- Legacy endpoints under migration can be temporarily exempted only with compensating controls and a tracked deprecation timeline.
|
|
94
|
+
|
|
95
|
+
## Related Rules
|
|
96
|
+
- [TG-INPUT-002](./TG-INPUT-002-raw-sql-concatenation.md)
|
|
97
|
+
- [TG-INPUT-003](./TG-INPUT-003-unsafe-html-or-code-execution.md)
|
|
98
|
+
- [TG-AUTH-003](./TG-AUTH-003-missing-object-authorization.md)
|