torusguard 1.3.3 → 1.3.5
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 +93 -7
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-256-c8a22e/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-256-c8a22e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-002-256-c8a22e/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-platform-001-183-47fd5e/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-platform-001-183-47fd5e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-platform-001-183-47fd5e/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260910-120238-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
- package/.torusguard/runs/run-20260910-120238-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260910-120238-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260910-120238-audit/manifest.json +13 -0
- package/.torusguard/runs/run-20260910-120238-audit/recheck.md +86 -0
- package/.torusguard/runs/run-20260910-120238-audit/remediation.md +262 -0
- package/.torusguard/runs/run-20260910-120238-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260910-121238-audit/findings.json +794 -0
- package/.torusguard/runs/run-20260910-121238-audit/findings.md +344 -0
- package/.torusguard/runs/run-20260910-121238-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260910-121238-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260910-130454-audit/findings.json +893 -0
- package/.torusguard/runs/run-20260910-130454-audit/findings.md +386 -0
- package/.torusguard/runs/run-20260910-130454-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260910-130454-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260910-130519-audit/findings.json +563 -0
- package/.torusguard/runs/run-20260910-130519-audit/findings.md +246 -0
- package/.torusguard/runs/run-20260910-130519-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260910-130519-audit/summary.md +5 -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/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
- package/.torusguard/scripts/apply_runner.py +383 -339
- package/.torusguard/scripts/audit_runner.py +1306 -550
- package/.torusguard/scripts/finding_scorer.py +14 -2
- package/.torusguard/scripts/harden_runner.py +628 -375
- package/.torusguard/scripts/recheck_runner.py +248 -221
- package/.torusguard/scripts/recipes_runner.py +137 -130
- package/.torusguard/scripts/report_sync.py +423 -0
- package/.torusguard/scripts/sarif_exporter.py +116 -116
- package/.torusguard/scripts/term_ui.py +162 -0
- package/.torusguard/skills/torusguard/SKILL.md +61 -31
- package/.torusguard/skills/torusguard-apply/SKILL.md +80 -46
- package/.torusguard/skills/torusguard-audit/SKILL.md +83 -70
- package/.torusguard/skills/torusguard-authorize/SKILL.md +5 -4
- package/.torusguard/skills/torusguard-exploit-check/SKILL.md +6 -5
- package/.torusguard/skills/torusguard-full/SKILL.md +1 -1
- package/.torusguard/skills/torusguard-harden/SKILL.md +94 -63
- package/.torusguard/skills/torusguard-init/SKILL.md +64 -52
- package/.torusguard/skills/torusguard-recheck/SKILL.md +77 -53
- package/.torusguard/skills/torusguard-report/SKILL.md +72 -54
- package/.torusguard/skills/torusguard-status/SKILL.md +58 -42
- package/.torusguard/skills/torusguard-verify/SKILL.md +8 -7
- package/.torusguard/skills/torusguard-web-validate/SKILL.md +8 -7
- 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 +470 -344
- package/bin/torusguard.js +209 -97
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +73 -42
- 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/apply_runner.py +383 -339
- package/skills/torusguard/payload/scripts/audit_runner.py +1306 -550
- package/skills/torusguard/payload/scripts/finding_scorer.py +14 -2
- package/skills/torusguard/payload/scripts/harden_runner.py +628 -375
- package/skills/torusguard/payload/scripts/recheck_runner.py +248 -221
- package/skills/torusguard/payload/scripts/recipes_runner.py +137 -130
- package/skills/torusguard/payload/scripts/report_sync.py +423 -0
- package/skills/torusguard/payload/scripts/sarif_exporter.py +116 -116
- package/skills/torusguard/payload/scripts/term_ui.py +162 -0
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +75 -42
- package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +63 -25
- package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +62 -45
- package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +11 -5
- package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +12 -6
- package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +7 -2
- package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +71 -36
- package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +45 -29
- package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +59 -31
- package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +52 -30
- package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +40 -20
- package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +14 -8
- package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +14 -8
- 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 +63 -27
- package/skills/torusguard-audit/SKILL.md +62 -50
- 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 +71 -40
- package/skills/torusguard-init/SKILL.md +45 -30
- package/skills/torusguard-recheck/SKILL.md +59 -32
- package/skills/torusguard-report/SKILL.md +52 -31
- package/skills/torusguard-status/SKILL.md +40 -21
- package/skills/torusguard-verify/SKILL.md +7 -2
- package/skills/torusguard-web-validate/SKILL.md +7 -2
|
@@ -1,37 +1,64 @@
|
|
|
1
1
|
# TG-SSRF-002: Missing Internal Network Protection
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Allowing server-side HTTP clients to dispatch requests to internal network interfaces (127.0.0.1, private RFC 1918 subnets, or cloud metadata services like 169.254.169.254) allows external attackers to extract cloud credentials and interact with internal microservices.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Webhook dispatchers, URL preview fetchers, PDF generators, image proxies
|
|
8
|
+
- Node.js (fetch, axios), Python (requests, httpx, urllib), Go (net/http), Java
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
If a server accepts a destination URL from a user (e.g. `/api/fetch-avatar?url=...`) without blocking private network spaces, an attacker can supply `http://169.254.169.254/latest/meta-data/iam/security-credentials/` to steal AWS IAM role tokens, or `http://127.0.0.1:6379` to inject Redis commands.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Server-side request calls dispatching requests to unvalidated URLs that could resolve to loopback (`127.0.0.0/8`), link-local (`169.254.0.0/16`), or private IP ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`).
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
17
|
+
```python
|
|
18
|
+
# UNSAFE: Outbound fetch without private IP filtering
|
|
19
|
+
import requests
|
|
20
|
+
from fastapi import FastAPI
|
|
21
|
+
|
|
22
|
+
app = FastAPI()
|
|
23
|
+
|
|
24
|
+
@app.get("/fetch")
|
|
25
|
+
def fetch_url(url: str):
|
|
26
|
+
return requests.get(url).text # Attacker passes http://169.254.169.254/...
|
|
18
27
|
```
|
|
19
28
|
|
|
20
29
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
```python
|
|
31
|
+
# SAFE: Resolving IP and validating against private subnet ranges before fetching
|
|
32
|
+
import socket
|
|
33
|
+
import ipaddress
|
|
34
|
+
import requests
|
|
35
|
+
from fastapi import FastAPI, HTTPException
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
1. Step one
|
|
27
|
-
2. Step two
|
|
37
|
+
app = FastAPI()
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
def is_safe_url(url: str) -> bool:
|
|
40
|
+
from urllib.parse import urlparse
|
|
41
|
+
hostname = urlparse(url).hostname
|
|
42
|
+
if not hostname: return False
|
|
43
|
+
ip = ipaddress.ip_address(socket.gethostbyname(hostname))
|
|
44
|
+
return not (ip.is_private or ip.is_loopback or ip.is_link_local)
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
@app.get("/fetch")
|
|
47
|
+
def fetch_url(url: str):
|
|
48
|
+
if not is_safe_url(url):
|
|
49
|
+
raise HTTPException(status_code=400, detail="Invalid destination IP")
|
|
50
|
+
return requests.get(url, timeout=5.0).text
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Ponytail Remediation Budget
|
|
54
|
+
- Additions: <= 14 lines
|
|
55
|
+
- Deletions: <= 2 lines
|
|
56
|
+
|
|
57
|
+
## Remediation
|
|
58
|
+
1. Parse the destination hostname and resolve DNS.
|
|
59
|
+
2. Assert that resolved IP addresses are neither loopback (`127.0.0.0/8`), link-local (`169.254.0.0/16`), nor RFC 1918 private subnets.
|
|
60
|
+
3. Pin DNS resolution to prevent time-of-check to time-of-use (TOCTOU) DNS rebinding attacks.
|
|
35
61
|
|
|
36
62
|
## Related Rules
|
|
37
|
-
- TG-
|
|
63
|
+
- `TG-SSRF-001`: User-Controlled Server-Side URL Fetch
|
|
64
|
+
- `TG-SSRF-004`: Unbounded Outbound Request
|
|
@@ -1,37 +1,41 @@
|
|
|
1
1
|
# TG-SSRF-003: Unsafe Redirect Following
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
High by
|
|
4
|
+
High. Configuring server-side HTTP clients to automatically follow redirects allows attackers to bypass initial URL allowlists by supplying a public URL that redirects (301/302) to an internal loopback or cloud metadata service.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- HTTP Clients (Axios, Requests, Fetch, urllib, cURL)
|
|
8
|
+
- Node.js, Python, Go, Java
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
An application might validate that `https://example.com/image.png` is safe. However, if `example.com` returns a redirect header `Location: http://169.254.169.254/latest/meta-data/` and the client follows redirects automatically, the internal metadata service is fetched.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- HTTP client configurations with `maxRedirects > 0`, `follow_redirects=True`, or `allow_redirects=True` on user-controlled fetches.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Axios configured with default automatic redirect following
|
|
19
|
+
const response = await axios.get(userSuppliedUrl, { maxRedirects: 5 });
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
## Safe Example
|
|
21
23
|
```javascript
|
|
22
|
-
//
|
|
24
|
+
// SAFE: Disabling automatic redirect following or revalidating redirect target
|
|
25
|
+
const response = await axios.get(userSuppliedUrl, {
|
|
26
|
+
maxRedirects: 0,
|
|
27
|
+
validateStatus: status => status >= 200 && status < 300
|
|
28
|
+
});
|
|
23
29
|
```
|
|
24
30
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
31
|
+
## Ponytail Remediation Budget
|
|
32
|
+
- Additions: <= 4 lines
|
|
33
|
+
- Deletions: <= 2 lines
|
|
32
34
|
|
|
33
|
-
##
|
|
34
|
-
|
|
35
|
+
## Remediation
|
|
36
|
+
1. Disable automatic HTTP redirect following (`maxRedirects: 0` or `allow_redirects=False`).
|
|
37
|
+
2. If redirects must be supported, intercept `Location` headers and re-run IP safety checks before dispatching secondary requests.
|
|
35
38
|
|
|
36
39
|
## Related Rules
|
|
37
|
-
- TG-
|
|
40
|
+
- `TG-SSRF-001`: User-Controlled Server-Side URL Fetch
|
|
41
|
+
- `TG-SSRF-002`: Missing Internal Network Protection
|
|
@@ -1,37 +1,46 @@
|
|
|
1
|
-
# TG-SSRF-004: Unbounded Outbound Request
|
|
1
|
+
# TG-SSRF-004: Unbounded Outbound Request Without Timeout
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Dispatching server-side HTTP requests without strict socket and read timeouts allows malicious endpoints or slowloris servers to hang server worker threads indefinitely, leading to resource exhaustion and DoS.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Outbound HTTP Clients (Python `requests`, Node `axios`, Go `http.Client`)
|
|
8
|
+
- Python, Node.js, Go, Java
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
In Python `requests`, the default timeout is `None` (it waits forever). If an attacker provides a URL pointing to a server that accepts the connection and trickles 1 byte every 10 minutes, your server worker threads become permanently exhausted.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Outbound HTTP calls (`requests.get`, `requests.post`, `axios.get`, `fetch`) lacking explicit `timeout` parameters.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
17
|
+
```python
|
|
18
|
+
# UNSAFE: Python requests call without timeout hangs indefinitely
|
|
19
|
+
import requests
|
|
20
|
+
|
|
21
|
+
def fetch_avatar(url: str):
|
|
22
|
+
response = requests.get(url) # Can hang indefinitely
|
|
23
|
+
return response.content
|
|
18
24
|
```
|
|
19
25
|
|
|
20
26
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
```python
|
|
28
|
+
# SAFE: Explicit timeout prevents hanging worker threads
|
|
29
|
+
import requests
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
def fetch_avatar(url: str):
|
|
32
|
+
response = requests.get(url, timeout=5.0) # 5-second socket timeout
|
|
33
|
+
return response.content
|
|
34
|
+
```
|
|
28
35
|
|
|
29
|
-
##
|
|
30
|
-
-
|
|
31
|
-
-
|
|
36
|
+
## Ponytail Remediation Budget
|
|
37
|
+
- Additions: <= 2 lines
|
|
38
|
+
- Deletions: <= 1 line
|
|
32
39
|
|
|
33
|
-
##
|
|
34
|
-
|
|
40
|
+
## Remediation
|
|
41
|
+
1. Always specify an explicit `timeout` on all network calls (typically 3.0 to 10.0 seconds).
|
|
42
|
+
2. Configure custom client sessions with default timeouts applied globally.
|
|
35
43
|
|
|
36
44
|
## Related Rules
|
|
37
|
-
- TG-
|
|
45
|
+
- `TG-SSRF-001`: User-Controlled Server-Side URL Fetch
|
|
46
|
+
- `TG-RATE-003`: Unbounded Resource Consumption
|
package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md
CHANGED
|
@@ -1,37 +1,44 @@
|
|
|
1
1
|
# TG-SUPPLY-001: Missing or Ignored Dependency Lockfile
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
High
|
|
4
|
+
High. Omitting or `.gitignore`-ing dependency lockfiles (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `Poetry.lock`, `Cargo.lock`, `go.sum`) allows non-deterministic builds and exposes installations to malicious sub-dependency updates.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- npm, pnpm, yarn, pip, poetry, cargo, go
|
|
8
|
+
- All polyglot projects
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
Without a committed lockfile, running `npm install` or `pip install` resolves the latest compatible semantic version (`^1.0.0`). If a third-party dependency author account is compromised and publishes a malicious patch version, your CI/CD pipeline installs it automatically.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- `.gitignore` files containing `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml`.
|
|
15
|
+
- Repositories with manifest files (`package.json`) lacking corresponding lockfiles.
|
|
14
16
|
|
|
15
17
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
+
```gitignore
|
|
19
|
+
# UNSAFE: Ignoring dependency lockfiles in version control
|
|
20
|
+
node_modules/
|
|
21
|
+
package-lock.json
|
|
22
|
+
yarn.lock
|
|
18
23
|
```
|
|
19
24
|
|
|
20
25
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
26
|
+
```gitignore
|
|
27
|
+
# SAFE: Tracking lockfiles in version control; ignoring only node_modules
|
|
28
|
+
node_modules/
|
|
29
|
+
dist/
|
|
30
|
+
build/
|
|
23
31
|
```
|
|
24
32
|
|
|
25
|
-
## Remediation
|
|
26
|
-
1
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
33
|
+
## Ponytail Remediation Budget
|
|
34
|
+
- Additions: <= 1 line
|
|
35
|
+
- Deletions: <= 2 lines
|
|
32
36
|
|
|
33
|
-
##
|
|
34
|
-
|
|
37
|
+
## Remediation
|
|
38
|
+
1. Remove lockfile references from `.gitignore`.
|
|
39
|
+
2. Run `npm install` to generate `package-lock.json` and commit it to git.
|
|
40
|
+
3. In CI/CD pipelines, use `npm ci` or `pnpm install --frozen-lockfile` instead of `npm install`.
|
|
35
41
|
|
|
36
42
|
## Related Rules
|
|
37
|
-
- TG-
|
|
43
|
+
- `TG-SUPPLY-002`: Vulnerable Dependency Review Missing
|
|
44
|
+
- `TG-SUPPLY-004`: Unpinned CI Action
|
|
@@ -1,37 +1,47 @@
|
|
|
1
|
-
# TG-SUPPLY-003: Unsafe CI/CD Secret Exposure
|
|
1
|
+
# TG-SUPPLY-003: Unsafe CI/CD Secret Exposure in Workflow Logs
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Echoing or printing pipeline secrets in CI/CD step commands (`echo ${{ secrets.API_KEY }}`) or passing secrets directly in command line arguments persists plaintext credentials in build logs.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- GitHub Actions, GitLab CI, CircleCI, Bitbucket Pipelines
|
|
8
|
+
- YAML Workflows
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
CI/CD logs are often accessible to broad team members, external contributors, or public viewers on open-source repositories. Even when CI providers attempt log masking, modified or base64-encoded strings bypass masking and remain permanently visible in build logs.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- CI steps running `echo` or `print` on `${{ secrets.* }}` or `$SECRET_*`.
|
|
15
|
+
- Passing secrets as command-line arguments instead of masked environment variables.
|
|
14
16
|
|
|
15
17
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
+
```yaml
|
|
19
|
+
# UNSAFE: Echoing secrets directly into execution step logs
|
|
20
|
+
- name: Deploy to Cloud
|
|
21
|
+
run: |
|
|
22
|
+
echo "Using token ${{ secrets.DEPLOY_TOKEN }}"
|
|
23
|
+
deploy-tool --token ${{ secrets.DEPLOY_TOKEN }}
|
|
18
24
|
```
|
|
19
25
|
|
|
20
26
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
27
|
+
```yaml
|
|
28
|
+
# SAFE: Injecting secrets strictly via environment variables without logging
|
|
29
|
+
- name: Deploy to Cloud
|
|
30
|
+
env:
|
|
31
|
+
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
|
|
32
|
+
run: |
|
|
33
|
+
deploy-tool
|
|
23
34
|
```
|
|
24
35
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
36
|
+
## Ponytail Remediation Budget
|
|
37
|
+
- Additions: <= 5 lines
|
|
38
|
+
- Deletions: <= 3 lines
|
|
32
39
|
|
|
33
|
-
##
|
|
34
|
-
|
|
40
|
+
## Remediation
|
|
41
|
+
1. Never print or echo secret variables in workflow step commands.
|
|
42
|
+
2. Pass secrets into steps strictly via the `env:` block.
|
|
43
|
+
3. Avoid command-line arguments for secrets; configure tools to read credentials from environment variables or secure files.
|
|
35
44
|
|
|
36
45
|
## Related Rules
|
|
37
|
-
- TG-
|
|
46
|
+
- `TG-SEC-001`: Hardcoded Secret or API Key in Tracked Source
|
|
47
|
+
- `TG-SUPPLY-004`: Unpinned CI Action
|
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
# TG-SUPPLY-004: Unpinned CI Action
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Referencing third-party GitHub Actions using mutable branch or version tags (e.g. `uses: actions/checkout@v4`) allows attackers who compromise the action's repository to push malicious code that runs with your workflow's permissions.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- GitHub Actions Workflows (`.github/workflows/*.yml`)
|
|
8
|
+
- CI/CD Configurations
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
Git tags in third-party repositories are mutable pointers. An attacker who compromises a popular action maintainer's account can force-push a malicious commit to `@v3` or `@v4`, granting them immediate execution inside your CI environment with access to your repository secrets.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- GitHub Actions `uses:` declarations referencing version tags (`@v4`, `@main`) instead of 40-character immutable commit SHA hashes.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
17
|
+
```yaml
|
|
18
|
+
# UNSAFE: Mutable tag vulnerable to tag spoofing
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: some-vendor/setup-tool@v1
|
|
18
22
|
```
|
|
19
23
|
|
|
20
24
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
25
|
+
```yaml
|
|
26
|
+
# SAFE: Immutable commit SHA pinning with version comment
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
29
|
+
- uses: some-vendor/setup-tool@c2e8c2f1f8b172a5a54db5e6b12a818c1b2c3d4e # v1.2.0
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
32
|
+
## Ponytail Remediation Budget
|
|
33
|
+
- Additions: <= 2 lines
|
|
34
|
+
- Deletions: <= 2 lines
|
|
32
35
|
|
|
33
|
-
##
|
|
34
|
-
|
|
36
|
+
## Remediation
|
|
37
|
+
1. Pin all external GitHub Actions to full 40-character commit SHAs.
|
|
38
|
+
2. Use tools like Dependabot or Renovate to automate SHA updates with release verification.
|
|
35
39
|
|
|
36
40
|
## Related Rules
|
|
37
|
-
- TG-
|
|
41
|
+
- `TG-SUPPLY-003`: Unsafe CI/CD Secret Exposure
|
|
42
|
+
- `TG-SUPPLY-005`: Unsafe Dependency Install Script
|
|
@@ -1,37 +1,42 @@
|
|
|
1
1
|
# TG-SUPPLY-005: Unsafe Dependency Install Script
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Piping remote scripts directly from `curl` or `wget` into `bash` or `sh` without checksum verification or cryptographic signature checking creates an immediate Remote Code Execution (RCE) vulnerability.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- CI/CD Workflows, Setup Scripts, Dockerfiles, Provisioning Scripts
|
|
8
|
+
- Shell, Bash, Dockerfile
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
If the remote server is compromised, the DNS hijacked, or a CDN man-in-the-middle occurs, arbitrary malicious code is executed directly in your environment. Furthermore, partial network downloads can cause truncated execution of dangerous shell commands.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Shell patterns piping `curl -s ... | bash` or `wget -O- ... | sh`.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
|
-
```
|
|
17
|
-
|
|
17
|
+
```bash
|
|
18
|
+
# UNSAFE: Piping remote URL directly into shell execution
|
|
19
|
+
curl -sSL https://install.vendor.com/setup.sh | bash
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
## Safe Example
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
+
```bash
|
|
24
|
+
# SAFE: Downloading script, verifying SHA-256 checksum, and executing
|
|
25
|
+
EXPECTED_SHA="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
26
|
+
curl -sSL -o install.sh https://install.vendor.com/setup.sh
|
|
27
|
+
echo "${EXPECTED_SHA} install.sh" | sha256sum --check -
|
|
28
|
+
bash install.sh
|
|
23
29
|
```
|
|
24
30
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
2
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
31
|
+
## Ponytail Remediation Budget
|
|
32
|
+
- Additions: <= 5 lines
|
|
33
|
+
- Deletions: <= 2 lines
|
|
32
34
|
|
|
33
|
-
##
|
|
34
|
-
|
|
35
|
+
## Remediation
|
|
36
|
+
1. Avoid piping remote URLs directly into shell execution.
|
|
37
|
+
2. Download the installation script to a file and verify its SHA-256 checksum before execution.
|
|
38
|
+
3. Package dependencies through verified package managers (npm, pip, cargo, apt) rather than curl scripts.
|
|
35
39
|
|
|
36
40
|
## Related Rules
|
|
37
|
-
- TG-
|
|
41
|
+
- `TG-INPUT-004`: Command Injection via Shell Execution
|
|
42
|
+
- `TG-SUPPLY-004`: Unpinned CI Action
|
|
@@ -1,37 +1,57 @@
|
|
|
1
1
|
# TG-WEBHOOK-001: Missing Webhook Signature Verification
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Webhook ingestion endpoints (Stripe, GitHub, Shopify) that process events without verifying HMAC cryptographic signatures allow external attackers to forge events (e.g. spoofing a `payment_intent.succeeded` event).
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Webhook Listeners (Express, FastAPI, Django, Flask, Next.js)
|
|
8
|
+
- Node.js, Python, Go, Java, C#
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
Webhook endpoints are public HTTP endpoints. Without signature verification, anyone who discovers the webhook URL can send forged JSON payloads mimicking payment success, account activation, or repository merges.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Public webhook routes (`/api/webhooks/stripe`, `/api/github-webhook`) that parse payloads without calling provider signature verification methods (`stripe.webhooks.constructEvent`, `crypto.createHmac`).
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Trusting incoming webhook payload without verifying signature
|
|
19
|
+
app.post('/api/webhook/stripe', express.json(), async (req, res) => {
|
|
20
|
+
const event = req.body;
|
|
21
|
+
if (event.type === 'payment_intent.succeeded') {
|
|
22
|
+
await fulfillOrder(event.data.object.metadata.orderId);
|
|
23
|
+
}
|
|
24
|
+
res.json({ received: true });
|
|
25
|
+
});
|
|
18
26
|
```
|
|
19
27
|
|
|
20
28
|
## Safe Example
|
|
21
29
|
```javascript
|
|
22
|
-
//
|
|
30
|
+
// SAFE: Verifying Stripe HMAC signature using raw request body
|
|
31
|
+
app.post('/api/webhook/stripe', express.raw({ type: 'application/json' }), (req, res) => {
|
|
32
|
+
const sig = req.headers['stripe-signature'];
|
|
33
|
+
let event;
|
|
34
|
+
try {
|
|
35
|
+
event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
return res.status(400).send(`Webhook Error: ${err.message}`);
|
|
38
|
+
}
|
|
39
|
+
if (event.type === 'payment_intent.succeeded') {
|
|
40
|
+
fulfillOrder(event.data.object.metadata.orderId);
|
|
41
|
+
}
|
|
42
|
+
res.json({ received: true });
|
|
43
|
+
});
|
|
23
44
|
```
|
|
24
45
|
|
|
25
|
-
## Remediation
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
## Verification
|
|
30
|
-
- Test case 1
|
|
31
|
-
- Test case 2
|
|
46
|
+
## Ponytail Remediation Budget
|
|
47
|
+
- Additions: <= 12 lines
|
|
48
|
+
- Deletions: <= 4 lines
|
|
32
49
|
|
|
33
|
-
##
|
|
34
|
-
|
|
50
|
+
## Remediation
|
|
51
|
+
1. Use raw request body buffer for signature computation.
|
|
52
|
+
2. Verify signatures using provider SDKs or timing-safe HMAC comparison (`crypto.timingSafeEqual`).
|
|
53
|
+
3. Store webhook signing secrets in environment variables (`STRIPE_WEBHOOK_SECRET`).
|
|
35
54
|
|
|
36
55
|
## Related Rules
|
|
37
|
-
- TG-
|
|
56
|
+
- `TG-WEBHOOK-002`: Replayable Webhook Without Timestamp Validation
|
|
57
|
+
- `TG-WEBHOOK-003`: Missing Webhook Idempotency
|
|
@@ -1,37 +1,46 @@
|
|
|
1
|
-
# TG-WEBHOOK-002: Replayable Webhook
|
|
1
|
+
# TG-WEBHOOK-002: Replayable Webhook Without Timestamp Validation
|
|
2
2
|
|
|
3
3
|
## Severity
|
|
4
|
-
|
|
4
|
+
Critical. Processing webhook events without verifying timestamp freshness allows an attacker with access to network logs to replay old captured webhook payloads to duplicate orders or events.
|
|
5
5
|
|
|
6
6
|
## Applies To
|
|
7
|
-
-
|
|
7
|
+
- Webhook Handlers (Stripe, Slack, Custom Webhooks)
|
|
8
|
+
- Node.js, Python, Go, Java
|
|
8
9
|
|
|
9
10
|
## Why It Matters
|
|
10
|
-
|
|
11
|
+
Even if an attacker cannot forge a cryptographic signature, they may be able to capture a valid signed request and replay it days later. Enforcing timestamp freshness (e.g. rejecting requests older than 5 minutes) neutralizes replay attacks.
|
|
11
12
|
|
|
12
13
|
## What TorusGuard Looks For
|
|
13
|
-
-
|
|
14
|
+
- Custom signature validation routines that verify hashes but do not check timestamp tolerances.
|
|
14
15
|
|
|
15
16
|
## Unsafe Example
|
|
16
17
|
```javascript
|
|
17
|
-
//
|
|
18
|
+
// UNSAFE: Checking signature without timestamp tolerance check
|
|
19
|
+
function verifySignature(payload, signature, secret) {
|
|
20
|
+
const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
|
|
21
|
+
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
|
|
22
|
+
}
|
|
18
23
|
```
|
|
19
24
|
|
|
20
25
|
## Safe Example
|
|
21
26
|
```javascript
|
|
22
|
-
//
|
|
27
|
+
// SAFE: Asserting timestamp freshness within a 5-minute tolerance window
|
|
28
|
+
function verifySignature(payload, signature, timestamp, secret) {
|
|
29
|
+
const now = Math.floor(Date.now() / 1000);
|
|
30
|
+
if (Math.abs(now - Number(timestamp)) > 300) return false; // 5-minute tolerance
|
|
31
|
+
const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${payload}`).digest('hex');
|
|
32
|
+
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
|
|
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: <= 6 lines
|
|
38
|
+
- Deletions: <= 2 lines
|
|
32
39
|
|
|
33
|
-
##
|
|
34
|
-
|
|
40
|
+
## Remediation
|
|
41
|
+
1. Include timestamp in signature computation payload (`${timestamp}.${payload}`).
|
|
42
|
+
2. Verify that timestamp is within a 300-second window of current server time.
|
|
35
43
|
|
|
36
44
|
## Related Rules
|
|
37
|
-
- TG-
|
|
45
|
+
- `TG-WEBHOOK-001`: Missing Webhook Signature Verification
|
|
46
|
+
- `TG-WEBHOOK-003`: Missing Webhook Idempotency
|