torusguard 1.3.4 → 1.3.6
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 +66 -63
- package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
- package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
- package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
- package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
- package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
- package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
- package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
- package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
- package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
- package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
- package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
- package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
- package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
- package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
- package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
- package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
- package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
- package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
- package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
- package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
- package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
- package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
- package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
- package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
- package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
- package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
- package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
- package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
- package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
- package/.torusguard/rules_catalog.json +520 -0
- package/.torusguard/runs/report-latest.html +2700 -232
- package/.torusguard/runs/results-latest.sarif +20 -0
- package/.torusguard/runs/run-20260912-214110-audit/findings.json +1256 -0
- package/.torusguard/runs/run-20260912-214110-audit/findings.md +534 -0
- package/.torusguard/runs/run-20260912-214110-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260912-214110-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260912-214813-audit/findings.json +992 -0
- package/.torusguard/runs/run-20260912-214813-audit/findings.md +422 -0
- package/.torusguard/runs/run-20260912-214813-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260912-214813-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215555-audit/findings.json +530 -0
- package/.torusguard/runs/run-20260912-215555-audit/findings.md +232 -0
- package/.torusguard/runs/run-20260912-215555-audit/manifest.json +13 -0
- package/.torusguard/runs/run-20260912-215555-audit/remediation.md +102 -0
- package/.torusguard/runs/run-20260912-215555-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260912-215731-audit/apply_plan.md +6 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/minimal_patch_plan.md +22 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/patch.diff +10 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/minimal_patch_plan.md +23 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/patch.diff +11 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/minimal_patch_plan.md +23 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/patch.diff +11 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
- package/.torusguard/runs/run-20260912-215731-audit/diff_summary.md +186 -0
- package/.torusguard/runs/run-20260912-215731-audit/findings.json +497 -0
- package/.torusguard/runs/run-20260912-215731-audit/findings.md +218 -0
- package/.torusguard/runs/run-20260912-215731-audit/manifest.json +14 -0
- package/.torusguard/runs/run-20260912-215731-audit/recheck.md +76 -0
- package/.torusguard/runs/run-20260912-215731-audit/remediation.md +234 -0
- package/.torusguard/runs/run-20260912-215731-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260912-220134-audit/findings.json +68 -0
- package/.torusguard/runs/run-20260912-220134-audit/findings.md +36 -0
- package/.torusguard/runs/run-20260912-220134-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260912-220134-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260912-220200-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260912-220200-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260912-220200-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260912-220200-audit/recheck.md +6 -0
- package/.torusguard/runs/run-20260912-220200-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260912-220227-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260912-220227-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260912-220227-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260912-220227-audit/recheck.md +6 -0
- package/.torusguard/runs/run-20260912-220227-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-104221-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260918-104221-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260918-104221-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-104221-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-104236-audit/findings.json +2314 -0
- package/.torusguard/runs/run-20260918-104236-audit/findings.md +960 -0
- package/.torusguard/runs/run-20260918-104236-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-104236-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-105723-audit/findings.json +2382 -0
- package/.torusguard/runs/run-20260918-105723-audit/findings.md +960 -0
- package/.torusguard/runs/run-20260918-105723-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-105723-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-105731-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260918-105731-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260918-105731-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-105731-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-105940-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260918-105940-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260918-105940-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-105940-audit/summary.md +5 -0
- package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
- package/.torusguard/scripts/apply_runner.py +389 -377
- package/.torusguard/scripts/audit_runner.py +1513 -653
- package/.torusguard/scripts/finding_scorer.py +14 -2
- package/.torusguard/scripts/harden_runner.py +628 -455
- package/.torusguard/scripts/html_reporter.py +2668 -648
- package/.torusguard/scripts/recheck_runner.py +248 -238
- package/.torusguard/scripts/recipes_runner.py +137 -137
- package/.torusguard/scripts/report_sync.py +719 -0
- package/.torusguard/scripts/sarif_exporter.py +156 -116
- package/.torusguard/scripts/stack_detect.py +44 -2
- package/.torusguard/scripts/term_ui.py +162 -162
- package/.torusguard/skills/torusguard/SKILL.md +75 -72
- package/.torusguard/skills/torusguard-apply/SKILL.md +84 -80
- package/.torusguard/skills/torusguard-audit/SKILL.md +87 -83
- package/.torusguard/skills/torusguard-authorize/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-exploit-check/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-full/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-harden/SKILL.md +98 -94
- package/.torusguard/skills/torusguard-init/SKILL.md +68 -64
- package/.torusguard/skills/torusguard-recheck/SKILL.md +81 -77
- package/.torusguard/skills/torusguard-report/SKILL.md +93 -72
- package/.torusguard/skills/torusguard-status/SKILL.md +62 -58
- package/.torusguard/skills/torusguard-verify/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-web-validate/SKILL.md +7 -2
- package/.torusguard/snapshots/run-20260912-215731-audit/demo/playground/vulnerable_nextjs/actions.ts.bak +24 -0
- package/.torusguard/snapshots/run-20260912-215731-audit/examples/hardened-react-express/server/index.js.bak +121 -0
- package/.torusguard/snapshots/run-20260912-215731-audit/examples/python/fastapi-vuln/main.py.bak +20 -0
- package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
- package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/vite.config.js.bak +12 -0
- package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
- package/.torusguard/workflows/apply.md +11 -4
- package/.torusguard/workflows/audit.md +7 -1
- package/.torusguard/workflows/authorize.md +2 -1
- package/.torusguard/workflows/exploit-check.md +2 -1
- package/.torusguard/workflows/harden.md +7 -1
- package/.torusguard/workflows/init.md +6 -1
- package/.torusguard/workflows/memory.md +2 -1
- package/.torusguard/workflows/recheck.md +7 -1
- package/.torusguard/workflows/report.md +7 -1
- package/.torusguard/workflows/status.md +6 -1
- package/.torusguard/workflows/verify.md +6 -1
- package/.torusguard/workflows/web-validate.md +2 -1
- package/README.md +476 -345
- package/bin/torusguard.js +586 -545
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +73 -72
- package/skills/torusguard/bootstrap.py +7 -2
- package/skills/torusguard/payload/.manifest.json +66 -63
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
- package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
- package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
- package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
- package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
- package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
- package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
- package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
- package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
- package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
- package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
- package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
- package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
- package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
- package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
- package/skills/torusguard/payload/rules_catalog.json +520 -0
- package/skills/torusguard/payload/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/apply_runner.py +389 -377
- package/skills/torusguard/payload/scripts/audit_runner.py +1513 -653
- package/skills/torusguard/payload/scripts/finding_scorer.py +14 -2
- package/skills/torusguard/payload/scripts/harden_runner.py +628 -455
- package/skills/torusguard/payload/scripts/html_reporter.py +2668 -648
- package/skills/torusguard/payload/scripts/recheck_runner.py +248 -238
- package/skills/torusguard/payload/scripts/recipes_runner.py +137 -137
- package/skills/torusguard/payload/scripts/report_sync.py +719 -0
- package/skills/torusguard/payload/scripts/sarif_exporter.py +156 -116
- package/skills/torusguard/payload/scripts/stack_detect.py +44 -2
- package/skills/torusguard/payload/scripts/term_ui.py +162 -162
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +75 -72
- package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +84 -80
- package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +87 -83
- package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +7 -2
- package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +7 -2
- package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +7 -2
- package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +98 -94
- package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +68 -64
- package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +81 -77
- package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +93 -72
- package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +62 -58
- package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +7 -2
- package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +7 -2
- package/skills/torusguard/payload/workflows/apply.md +11 -4
- package/skills/torusguard/payload/workflows/audit.md +7 -1
- package/skills/torusguard/payload/workflows/authorize.md +2 -1
- package/skills/torusguard/payload/workflows/exploit-check.md +2 -1
- package/skills/torusguard/payload/workflows/harden.md +7 -1
- package/skills/torusguard/payload/workflows/init.md +6 -1
- package/skills/torusguard/payload/workflows/memory.md +2 -1
- package/skills/torusguard/payload/workflows/recheck.md +7 -1
- package/skills/torusguard/payload/workflows/report.md +7 -1
- package/skills/torusguard/payload/workflows/status.md +6 -1
- package/skills/torusguard/payload/workflows/verify.md +6 -1
- package/skills/torusguard/payload/workflows/web-validate.md +2 -1
- package/skills/torusguard-apply/SKILL.md +84 -80
- package/skills/torusguard-audit/SKILL.md +87 -83
- package/skills/torusguard-authorize/SKILL.md +7 -2
- package/skills/torusguard-exploit-check/SKILL.md +7 -2
- package/skills/torusguard-full/SKILL.md +7 -2
- package/skills/torusguard-harden/SKILL.md +98 -94
- package/skills/torusguard-init/SKILL.md +68 -64
- package/skills/torusguard-recheck/SKILL.md +81 -77
- package/skills/torusguard-report/SKILL.md +93 -72
- package/skills/torusguard-status/SKILL.md +62 -58
- package/skills/torusguard-verify/SKILL.md +7 -2
- package/skills/torusguard-web-validate/SKILL.md +7 -2
|
@@ -1,37 +1,47 @@
|
|
|
1
1
|
# TG-BIZ-004: Unrestricted Sensitive Business Flow
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
High
|
|
4
|
+
High. Critical administrative or high-impact actions lacking step-up authentication, secondary confirmation, or multi-person governance allow compromised sessions to inflict irreversible damage.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Tenant Deletion, Role Escalation, API Key Rotation, Wire Transfers
|
|
8
|
+
- Node.js, Python, Go, Java, C#
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
Session hijacking, CSRF, or brief workstation abandonment can allow attackers to execute destructive operations (such as purging an entire organization's database or transferring company funds) if the flow executes immediately on a single unconfirmed click.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Destructive administrative endpoints (`/delete-organization`, `/transfer-ownership`) executing without recent password re-authentication, MFA step-up verification, or explicit confirmation tokens.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Destructive deletion executing without password re-verification
|
|
19
|
+
app.delete('/api/orgs/:id', authMiddleware, async (req, res) => {
|
|
20
|
+
await db.org.delete({ where: { id: req.params.id } });
|
|
21
|
+
res.json({ success: true });
|
|
22
|
+
});
|
|
18
23
|
```
|
|
19
24
|
|
|
20
25
|
## Safe Example
|
|
21
26
|
```javascript
|
|
22
|
-
//
|
|
27
|
+
// SAFE: Requiring password re-authentication before executing destructive action
|
|
28
|
+
app.delete('/api/orgs/:id', authMiddleware, async (req, res) => {
|
|
29
|
+
const { confirmPassword } = req.body;
|
|
30
|
+
const isValid = await verifyPassword(req.user.id, confirmPassword);
|
|
31
|
+
if (!isValid) return res.status(403).json({ error: 'Invalid password confirmation' });
|
|
32
|
+
await db.org.delete({ where: { id: req.params.id } });
|
|
33
|
+
res.json({ success: true });
|
|
34
|
+
});
|
|
23
35
|
```
|
|
24
36
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
37
|
+
## Ponytail Remediation Budget
|
|
38
|
+
- Additions: <= 12 lines
|
|
39
|
+
- Deletions: <= 2 lines
|
|
32
40
|
|
|
33
|
-
##
|
|
34
|
-
|
|
41
|
+
## Remediation
|
|
42
|
+
1. Enforce step-up authentication (password re-prompt or TOTP code) on high-risk endpoints.
|
|
43
|
+
2. Implement two-stage confirmation (`DELETE` requires prior confirmation token).
|
|
35
44
|
|
|
36
45
|
## Related Rules
|
|
37
|
-
- TG-
|
|
46
|
+
- `TG-AUTH-002`: Client-Only Authorization
|
|
47
|
+
- `TG-RATE-003`: Unbounded Resource Consumption
|
package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md
CHANGED
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
# TG-CACHE-001: Sensitive Response Publicly Cacheable
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
High
|
|
4
|
+
High. Serving authenticated personal data, financial records, or credentials without private `Cache-Control` headers allows shared intermediary proxy servers and CDNs to cache and leak sensitive records to other users.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Authenticated Endpoints, User Profiles, Billing Dashboards
|
|
8
|
+
- Express, Next.js, FastAPI, Django, Flask, Rails, Spring
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
When endpoints returning PII omit cache control directives, shared corporate proxies or public edge CDNs may cache the response. Subsequent requests from other users on the same proxy can receive the cached personal data of the initial requester.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Routes returning user profiles, tokens, or private data with `Cache-Control: public` or missing `Cache-Control` entirely.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Missing cache control or explicitly public caching on private data
|
|
19
|
+
app.get('/api/user/profile', authMiddleware, (req, res) => {
|
|
20
|
+
res.set('Cache-Control', 'public, max-age=3600');
|
|
21
|
+
res.json(req.user);
|
|
22
|
+
});
|
|
18
23
|
```
|
|
19
24
|
|
|
20
25
|
## Safe Example
|
|
21
26
|
```javascript
|
|
22
|
-
//
|
|
27
|
+
// SAFE: Explicit private no-store cache control on sensitive responses
|
|
28
|
+
app.get('/api/user/profile', authMiddleware, (req, res) => {
|
|
29
|
+
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
|
|
30
|
+
res.set('Pragma', 'no-cache');
|
|
31
|
+
res.json(req.user);
|
|
32
|
+
});
|
|
23
33
|
```
|
|
24
34
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
35
|
+
## Ponytail Remediation Budget
|
|
36
|
+
- Additions: <= 4 lines
|
|
37
|
+
- Deletions: <= 2 lines
|
|
32
38
|
|
|
33
|
-
##
|
|
34
|
-
|
|
39
|
+
## Remediation
|
|
40
|
+
1. Inject global middleware setting `Cache-Control: no-store, private` on all authenticated API responses.
|
|
41
|
+
2. Verify reverse proxies and CDNs do not cache responses containing `Authorization` or `Cookie` headers.
|
|
35
42
|
|
|
36
43
|
## Related Rules
|
|
37
|
-
- TG-
|
|
44
|
+
- `TG-CACHE-002`: Missing User Cache Isolation
|
|
45
|
+
- `TG-PLATFORM-002`: Missing Security Headers
|
|
@@ -1,37 +1,51 @@
|
|
|
1
1
|
# TG-CACHE-002: Missing User Cache Isolation
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
High
|
|
4
|
+
High. Storing per-user computed assets or database query results in shared application memory caches (Redis, Memcached) without tenant or user ID scoping leads to cross-user data leakage.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Application Caching Layers (Redis, Memcached, LRU Caches)
|
|
8
|
+
- Node.js, Python, Go, Java
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
If cache keys are formed using generic keys (e.g., `cache:dashboard_summary`) rather than tenant-qualified keys (`cache:tenant_{tid}:user_{uid}:dashboard_summary`), the first user to query the dashboard caches their data, and all subsequent users receive that cached data.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Cache get/set calls where the cache key lacks user or tenant identifier variables.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
17
|
+
```python
|
|
18
|
+
# UNSAFE: Generic cache key shared across all users
|
|
19
|
+
@app.get("/api/dashboard")
|
|
20
|
+
def get_dashboard(user: User = Depends(get_current_user)):
|
|
21
|
+
data = cache.get("dashboard_data")
|
|
22
|
+
if not data:
|
|
23
|
+
data = generate_dashboard(user.id)
|
|
24
|
+
cache.set("dashboard_data", data, expire=300)
|
|
25
|
+
return data
|
|
18
26
|
```
|
|
19
27
|
|
|
20
28
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
29
|
+
```python
|
|
30
|
+
# SAFE: Fully isolated cache key scoped by tenant and user
|
|
31
|
+
@app.get("/api/dashboard")
|
|
32
|
+
def get_dashboard(user: User = Depends(get_current_user)):
|
|
33
|
+
cache_key = f"dashboard:tenant_{user.tenant_id}:user_{user.id}"
|
|
34
|
+
data = cache.get(cache_key)
|
|
35
|
+
if not data:
|
|
36
|
+
data = generate_dashboard(user.id)
|
|
37
|
+
cache.set(cache_key, data, expire=300)
|
|
38
|
+
return data
|
|
23
39
|
```
|
|
24
40
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
41
|
+
## Ponytail Remediation Budget
|
|
42
|
+
- Additions: <= 6 lines
|
|
43
|
+
- Deletions: <= 3 lines
|
|
32
44
|
|
|
33
|
-
##
|
|
34
|
-
|
|
45
|
+
## Remediation
|
|
46
|
+
1. Always prefix cache keys with organizational and user identifiers.
|
|
47
|
+
2. Clear tenant cache keys immediately upon logout or permissions change.
|
|
35
48
|
|
|
36
49
|
## Related Rules
|
|
37
|
-
- TG-
|
|
50
|
+
- `TG-DB-004`: Missing Multi-Tenant Query Isolation
|
|
51
|
+
- `TG-CACHE-001`: Sensitive Response Publicly Cacheable
|
|
@@ -1,37 +1,44 @@
|
|
|
1
|
-
# TG-CACHE-003: Sensitive Data in URL
|
|
1
|
+
# TG-CACHE-003: Sensitive Data in URL Query Parameters
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Medium. Passing API keys, session tokens, passwords, or PII in URL query parameters causes secrets to be persisted in browser histories, web server access logs, and HTTP `Referer` headers.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Authentication Flows, Invitation Links, Reset Handlers
|
|
8
|
+
- Frontend JS, Express, Django, FastAPI, Go, PHP
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
URLs are routinely logged in plaintext by reverse proxies, load balancers, CDN providers, and browser histories. If tokens are in query strings (`/login?token=xyz`), any external asset loaded on the page receives the token in the `Referer` header.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Query parameter patterns matching `api_key=`, `token=`, `secret=`, or `password=` in GET routes.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Accepting credentials or tokens in URL query string
|
|
19
|
+
app.get('/api/auth/callback', (req, res) => {
|
|
20
|
+
const { apiKey, password } = req.query;
|
|
21
|
+
authenticate(apiKey, password);
|
|
22
|
+
});
|
|
18
23
|
```
|
|
19
24
|
|
|
20
25
|
## Safe Example
|
|
21
26
|
```javascript
|
|
22
|
-
//
|
|
27
|
+
// SAFE: Passing credentials in Authorization header or POST request body
|
|
28
|
+
app.post('/api/auth/token', (req, res) => {
|
|
29
|
+
const { apiKey, password } = req.body;
|
|
30
|
+
authenticate(apiKey, password);
|
|
31
|
+
});
|
|
23
32
|
```
|
|
24
33
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
34
|
+
## Ponytail Remediation Budget
|
|
35
|
+
- Additions: <= 6 lines
|
|
36
|
+
- Deletions: <= 3 lines
|
|
32
37
|
|
|
33
|
-
##
|
|
34
|
-
|
|
38
|
+
## Remediation
|
|
39
|
+
1. Migrate authentication parameters to `Authorization: Bearer` headers or JSON request bodies via POST.
|
|
40
|
+
2. Strip sensitive query parameters from URLs using history replace state before page render.
|
|
35
41
|
|
|
36
42
|
## Related Rules
|
|
37
|
-
- TG-
|
|
43
|
+
- `TG-SEC-001`: Hardcoded Secret or API Key in Tracked Source
|
|
44
|
+
- `TG-SEC-004`: Sensitive Information in Logs
|
|
@@ -1,37 +1,50 @@
|
|
|
1
1
|
# TG-CSRF-001: Missing CSRF Protection
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. State-changing endpoints (POST, PUT, DELETE, PATCH) that rely on ambient credentials (cookies, basic auth) without CSRF tokens or SameSite cookie protection allow malicious third-party websites to execute actions on behalf of authenticated users.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Traditional Form Submissions, Cookie-Authenticated REST APIs
|
|
8
|
+
- Express (csurf), Django, Flask (Flask-WTF), Rails, Spring Security, ASP.NET Core
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
If a banking or SaaS application authenticates requests solely via browser cookies, a user visiting a malicious site can be tricked into submitting unauthorized form requests that the browser will automatically authenticate with the user's cookies.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- State-changing route handlers lacking CSRF middleware, CSRF tokens in headers, or explicit SameSite cookie configurations.
|
|
15
|
+
- Explicit disabling of CSRF protection (e.g. `@csrf_exempt`, `csrf().disable()`).
|
|
14
16
|
|
|
15
17
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
+
```python
|
|
19
|
+
# UNSAFE: Disabling CSRF protection on state-changing endpoint
|
|
20
|
+
from django.views.decorators.csrf import csrf_exempt
|
|
21
|
+
|
|
22
|
+
@csrf_exempt
|
|
23
|
+
def update_email(request):
|
|
24
|
+
request.user.email = request.POST.get("email")
|
|
25
|
+
request.user.save()
|
|
18
26
|
```
|
|
19
27
|
|
|
20
28
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
29
|
+
```python
|
|
30
|
+
# SAFE: Enforcing CSRF token verification
|
|
31
|
+
from django.views.decorators.csrf import csrf_protect
|
|
32
|
+
|
|
33
|
+
@csrf_protect
|
|
34
|
+
def update_email(request):
|
|
35
|
+
request.user.email = request.POST.get("email")
|
|
36
|
+
request.user.save()
|
|
23
37
|
```
|
|
24
38
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
39
|
+
## Ponytail Remediation Budget
|
|
40
|
+
- Additions: <= 4 lines
|
|
41
|
+
- Deletions: <= 2 lines
|
|
32
42
|
|
|
33
|
-
##
|
|
34
|
-
|
|
43
|
+
## Remediation
|
|
44
|
+
1. Never disable framework CSRF protection with `@csrf_exempt` or `csrf().disable()`.
|
|
45
|
+
2. Configure session cookies with `SameSite: 'Lax'` or `'Strict'`.
|
|
46
|
+
3. For single-page applications, validate custom headers (e.g. `X-Requested-With`, `X-CSRF-Token`).
|
|
35
47
|
|
|
36
48
|
## Related Rules
|
|
37
|
-
- TG-
|
|
49
|
+
- `TG-AUTH-004`: Insecure Session Cookie Configuration
|
|
50
|
+
- `TG-PLATFORM-001`: Wildcard CORS With Credentials
|
package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md
CHANGED
|
@@ -1,37 +1,48 @@
|
|
|
1
|
-
# TG-CSRF-002: Unsafe Credentialed Cross-Origin
|
|
1
|
+
# TG-CSRF-002: Unsafe Credentialed Cross-Origin Requests
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Enabling credentialed cross-origin access (`credentials: true` / `Access-Control-Allow-Credentials: true`) combined with dynamic reflection of incoming `Origin` headers allows any untrusted domain to read authenticated responses.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- CORS Middleware Configurations
|
|
8
|
+
- Express (cors), FastAPI, Flask-CORS, Django-cors-headers, Spring Security
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
When a server blindly reflects the `Origin` header while allowing credentials, any malicious site visited by an authenticated user can make cross-origin requests and read private user data, completely circumventing the Same-Origin Policy.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- CORS configurations reflecting `req.headers.origin` directly when `credentials: true` is enabled.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Blindly reflecting any origin with credentials enabled
|
|
19
|
+
app.use(cors({
|
|
20
|
+
origin: (origin, callback) => callback(null, true),
|
|
21
|
+
credentials: true
|
|
22
|
+
}));
|
|
18
23
|
```
|
|
19
24
|
|
|
20
25
|
## Safe Example
|
|
21
26
|
```javascript
|
|
22
|
-
//
|
|
27
|
+
// SAFE: Strictly validating origin against an explicit environment allowlist
|
|
28
|
+
const allowedOrigins = (process.env.ALLOWED_ORIGINS || 'https://app.example.com').split(',');
|
|
29
|
+
app.use(cors({
|
|
30
|
+
origin: (origin, callback) => {
|
|
31
|
+
if (!origin || allowedOrigins.includes(origin)) return callback(null, true);
|
|
32
|
+
callback(new Error('Blocked by CORS'));
|
|
33
|
+
},
|
|
34
|
+
credentials: true
|
|
35
|
+
}));
|
|
23
36
|
```
|
|
24
37
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
38
|
+
## Ponytail Remediation Budget
|
|
39
|
+
- Additions: <= 8 lines
|
|
40
|
+
- Deletions: <= 4 lines
|
|
32
41
|
|
|
33
|
-
##
|
|
34
|
-
|
|
42
|
+
## Remediation
|
|
43
|
+
1. Restrict CORS origins to a static, verified allowlist stored in environment variables.
|
|
44
|
+
2. Never reflect untrusted `req.headers.origin` when credentials are permitted.
|
|
35
45
|
|
|
36
46
|
## Related Rules
|
|
37
|
-
- TG-
|
|
47
|
+
- `TG-PLATFORM-001`: Wildcard CORS With Credentials
|
|
48
|
+
- `TG-CSRF-001`: Missing CSRF Protection
|
package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md
CHANGED
|
@@ -1,37 +1,53 @@
|
|
|
1
|
-
# TG-GQL-002: Resolver Missing Authorization
|
|
1
|
+
# TG-GQL-002: GraphQL Resolver Missing Authorization
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
High
|
|
4
|
+
High. Exposing GraphQL mutation or query resolvers without granular user ownership or role authorization checks allows authenticated users to query or mutate records belonging to other tenants.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- GraphQL Servers (Apollo Server, Yoga, Pothos, Graphene)
|
|
8
|
+
- Node.js, Python, Go, Java
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
In GraphQL, nested queries allow clients to traverse relationships (e.g. `user { organization { members { invoices } } }`). If individual field resolvers fail to assert ownership, users can traverse schema graphs to access unauthorized tenant resources.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- GraphQL resolver functions querying database entities directly by `args.id` without checking `context.user` or filtering by `context.tenantId`.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Querying invoice directly by ID without checking user or tenant
|
|
19
|
+
const resolvers = {
|
|
20
|
+
Query: {
|
|
21
|
+
invoice: async (_, { id }) => {
|
|
22
|
+
return await db.invoice.findUnique({ where: { id } });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
18
26
|
```
|
|
19
27
|
|
|
20
28
|
## Safe Example
|
|
21
29
|
```javascript
|
|
22
|
-
//
|
|
30
|
+
// SAFE: Scoping query by tenant and authenticated user context
|
|
31
|
+
const resolvers = {
|
|
32
|
+
Query: {
|
|
33
|
+
invoice: async (_, { id }, context) => {
|
|
34
|
+
if (!context.user) throw new Error('Unauthorized');
|
|
35
|
+
return await db.invoice.findFirst({
|
|
36
|
+
where: { id, tenantId: context.user.tenantId }
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
23
41
|
```
|
|
24
42
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
43
|
+
## Ponytail Remediation Budget
|
|
44
|
+
- Additions: <= 8 lines
|
|
45
|
+
- Deletions: <= 2 lines
|
|
32
46
|
|
|
33
|
-
##
|
|
34
|
-
|
|
47
|
+
## Remediation
|
|
48
|
+
1. Enforce shield/guard middleware or resolver-level ownership checks on all query and mutation fields.
|
|
49
|
+
2. Pass authenticated `context` to all database queries and enforce `tenantId` constraints.
|
|
35
50
|
|
|
36
51
|
## Related Rules
|
|
37
|
-
- TG-
|
|
52
|
+
- `TG-DB-004`: Missing Multi-Tenant Query Isolation
|
|
53
|
+
- `TG-AUTH-003`: Missing Object-Level Authorization (IDOR)
|
|
@@ -1,37 +1,52 @@
|
|
|
1
1
|
# TG-GQL-003: Unbounded GraphQL Pagination or Batching
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Medium. Permitting unbounded `first`, `limit`, or batching queries in GraphQL enables resource exhaustion and Denial of Service (DoS).
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Apollo Server, GraphQL Yoga, Graphene
|
|
8
|
+
- Node.js, Python, Go
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
Clients can request `users(first: 1000000)` or send a batched array of 500 queries in a single HTTP request, forcing the server to exhaust memory and database connection pools.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Resolvers accepting integer `first` / `limit` arguments without enforcing a maximum cap (e.g. `Math.min(limit, 100)`).
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Directly passing client-controlled limit to database
|
|
19
|
+
const resolvers = {
|
|
20
|
+
Query: {
|
|
21
|
+
users: async (_, { limit = 50 }) => {
|
|
22
|
+
return await db.user.findMany({ take: limit }); // Attacker passes limit: 500000
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
18
26
|
```
|
|
19
27
|
|
|
20
28
|
## Safe Example
|
|
21
29
|
```javascript
|
|
22
|
-
//
|
|
30
|
+
// SAFE: Enforcing strict maximum upper bound on pagination
|
|
31
|
+
const MAX_LIMIT = 100;
|
|
32
|
+
const resolvers = {
|
|
33
|
+
Query: {
|
|
34
|
+
users: async (_, { limit = 20 }) => {
|
|
35
|
+
const safeLimit = Math.min(Math.max(1, limit), MAX_LIMIT);
|
|
36
|
+
return await db.user.findMany({ take: safeLimit });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
23
40
|
```
|
|
24
41
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
42
|
+
## Ponytail Remediation Budget
|
|
43
|
+
- Additions: <= 5 lines
|
|
44
|
+
- Deletions: <= 2 lines
|
|
32
45
|
|
|
33
|
-
##
|
|
34
|
-
|
|
46
|
+
## Remediation
|
|
47
|
+
1. Enforce maximum limit boundaries on all pagination arguments.
|
|
48
|
+
2. Disable batched HTTP query execution unless explicitly required.
|
|
35
49
|
|
|
36
50
|
## Related Rules
|
|
37
|
-
- TG-
|
|
51
|
+
- `TG-RATE-003`: Unbounded Resource Consumption
|
|
52
|
+
- `TG-GQL-001`: Missing Query Depth Limits
|
package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md
CHANGED
|
@@ -1,37 +1,46 @@
|
|
|
1
1
|
# TG-GQL-004: Unnecessary Production Introspection
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Medium. Enabling GraphQL schema introspection in production environments reveals full schema types, queries, mutations, and deprecated fields to external attackers.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- GraphQL Servers (Apollo, Yoga, Mercurius, Helix)
|
|
8
|
+
- Production Node.js, Python, Go deployments
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
While introspection powers developer tools like Apollo Studio and GraphiQL, in production it provides attackers with an automated blueprint of the internal API surface, administrative fields, and hidden parameters.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- GraphQL server initialization setting `introspection: true` or failing to disable introspection when `NODE_ENV === 'production'`.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Introspection unconditionally enabled
|
|
19
|
+
const server = new ApolloServer({
|
|
20
|
+
typeDefs,
|
|
21
|
+
resolvers,
|
|
22
|
+
introspection: true
|
|
23
|
+
});
|
|
18
24
|
```
|
|
19
25
|
|
|
20
26
|
## Safe Example
|
|
21
27
|
```javascript
|
|
22
|
-
//
|
|
28
|
+
// SAFE: Introspection restricted to non-production environments
|
|
29
|
+
const server = new ApolloServer({
|
|
30
|
+
typeDefs,
|
|
31
|
+
resolvers,
|
|
32
|
+
introspection: process.env.NODE_ENV !== 'production'
|
|
33
|
+
});
|
|
23
34
|
```
|
|
24
35
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
36
|
+
## Ponytail Remediation Budget
|
|
37
|
+
- Additions: <= 2 lines
|
|
38
|
+
- Deletions: <= 2 lines
|
|
32
39
|
|
|
33
|
-
##
|
|
34
|
-
|
|
40
|
+
## Remediation
|
|
41
|
+
1. Bind `introspection` to environment checks (`process.env.NODE_ENV !== 'production'`).
|
|
42
|
+
2. Disable GraphQL Playground and Apollo Sandbox in production.
|
|
35
43
|
|
|
36
44
|
## Related Rules
|
|
37
|
-
- TG-
|
|
45
|
+
- `TG-PLATFORM-003`: Production Stack Trace Exposure
|
|
46
|
+
- `TG-CLIENT-001`: Public Production Source Maps
|