torusguard 1.3.4 → 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-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__/finding_scorer.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
- package/.torusguard/scripts/apply_runner.py +383 -377
- package/.torusguard/scripts/audit_runner.py +1306 -653
- package/.torusguard/scripts/finding_scorer.py +14 -2
- package/.torusguard/scripts/harden_runner.py +628 -455
- package/.torusguard/scripts/recheck_runner.py +248 -238
- package/.torusguard/scripts/recipes_runner.py +137 -137
- package/.torusguard/scripts/report_sync.py +423 -0
- package/.torusguard/scripts/sarif_exporter.py +116 -116
- package/.torusguard/scripts/term_ui.py +162 -162
- 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 -345
- package/bin/torusguard.js +550 -545
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +73 -72
- 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 -377
- package/skills/torusguard/payload/scripts/audit_runner.py +1306 -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/recheck_runner.py +248 -238
- package/skills/torusguard/payload/scripts/recipes_runner.py +137 -137
- 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 -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 +76 -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 +76 -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
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# TorusGuard Security Audit Findings: run-20260912-215555-audit
|
|
2
|
+
- Target Root: `C:\Users\Admin\Desktop\TorusGuard`
|
|
3
|
+
- Total Scored Findings: `16`
|
|
4
|
+
- Identified Clusters: `7`
|
|
5
|
+
- Generated At: `2026-09-12 21:55:55 IST`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
## Summary of Findings
|
|
9
|
+
|
|
10
|
+
### [Critical] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
11
|
+
- **Finding ID:** `TG-SEC-001-bb5e4b77`
|
|
12
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:9`
|
|
13
|
+
- **Confidence Score:** `80/100` (High Confidence)
|
|
14
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
15
|
+
- **Description:** Hardcoded JWT signing secret
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
// TG-SEC-001: Hardcoded JWT secret
|
|
19
|
+
const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';
|
|
20
|
+
|
|
21
|
+
// TG-PLATFORM-001: Wildcard CORS with credentials
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### [Critical] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
25
|
+
- **Finding ID:** `TG-SEC-001-c393d596`
|
|
26
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:18`
|
|
27
|
+
- **Confidence Score:** `80/100` (High Confidence)
|
|
28
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
29
|
+
- **Description:** Hardcoded credential or API secret string
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
const users = [
|
|
33
|
+
{ id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },
|
|
34
|
+
{ id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },
|
|
35
|
+
];
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### [Critical] TG-DB-002 - Privileged Database Credential in Browser Context
|
|
39
|
+
- **Finding ID:** `TG-DB-002-d9bd69df`
|
|
40
|
+
- **Location:** `demo/playground/vulnerable_nextjs/actions.ts:9`
|
|
41
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
42
|
+
- **Cluster:** `cluster-client-leak`
|
|
43
|
+
- **Description:** Service role key or raw database connection string reference in frontend code
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
// Finding 1: TG-CLIENT-001 - Backend admin key exposed in client-accessible code
|
|
47
|
+
export const SUPABASE_SERVICE_ROLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo_secret_token_1234567890";
|
|
48
|
+
|
|
49
|
+
interface UserRecord {
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### [Critical] TG-SSRF-004 - Unbounded Outbound Request Without Timeout
|
|
53
|
+
- **Finding ID:** `TG-SSRF-004-dcf3f71e`
|
|
54
|
+
- **Location:** `examples/python/fastapi-hardened/main.py:30`
|
|
55
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
56
|
+
- **Cluster:** `cluster-ssrf`
|
|
57
|
+
- **Description:** Python requests call without explicit timeout parameter
|
|
58
|
+
```
|
|
59
|
+
if not is_safe_url(url):
|
|
60
|
+
raise HTTPException(status_code=400, detail="Invalid destination address")
|
|
61
|
+
response = requests.get(url, timeout=5)
|
|
62
|
+
return {"status": response.status_code, "content": response.text}
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### [Critical] TG-SSRF-004 - Unbounded Outbound Request Without Timeout
|
|
67
|
+
- **Finding ID:** `TG-SSRF-004-d8472223`
|
|
68
|
+
- **Location:** `examples/python/fastapi-vuln/main.py:9`
|
|
69
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
70
|
+
- **Cluster:** `cluster-ssrf`
|
|
71
|
+
- **Description:** Python requests call without explicit timeout parameter
|
|
72
|
+
```
|
|
73
|
+
@app.get("/fetch")
|
|
74
|
+
def fetch_url(url: str):
|
|
75
|
+
response = requests.get(url)
|
|
76
|
+
return {"status": response.status_code, "content": response.text}
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### [High] TG-INPUT-003 - Unsafe Dynamic Code or HTML Execution
|
|
81
|
+
- **Finding ID:** `TG-INPUT-003-fea9421e`
|
|
82
|
+
- **Location:** `examples/vulnerable-react-express/client/src/App.jsx:53`
|
|
83
|
+
- **Confidence Score:** `80/100` (High Confidence)
|
|
84
|
+
- **Cluster:** `cluster-injection`
|
|
85
|
+
- **Description:** React dangerouslySetInnerHTML rendering raw unescaped HTML
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
{/* TG-INPUT-003: Unsafe HTML rendering */}
|
|
89
|
+
<div dangerouslySetInnerHTML={{ __html: bio }} />
|
|
90
|
+
|
|
91
|
+
<button onClick={fetchUser}>Fetch user (IDOR demo)</button>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### [High] TG-PLATFORM-001 - Wildcard CORS With Credentials
|
|
95
|
+
- **Finding ID:** `TG-PLATFORM-001-7dd35cb4`
|
|
96
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:12`
|
|
97
|
+
- **Confidence Score:** `80/100` (High Confidence)
|
|
98
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
99
|
+
- **Description:** Wildcard CORS origin configured in Express middleware
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
// TG-PLATFORM-001: Wildcard CORS with credentials
|
|
103
|
+
app.use(cors({ origin: '*', credentials: true }));
|
|
104
|
+
|
|
105
|
+
// TG-PLATFORM-004: No explicit JSON body size limit
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### [High] TG-AUTH-003 - Missing Object-Level Authorization (IDOR)
|
|
109
|
+
- **Finding ID:** `TG-AUTH-003-6a05e509`
|
|
110
|
+
- **Location:** `examples/hardened-react-express/server/index.js:49`
|
|
111
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
112
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
113
|
+
- **Description:** JWT verification missing explicit algorithms restriction parameter
|
|
114
|
+
```
|
|
115
|
+
if (!token) return res.status(401).json({ error: 'Unauthorized' });
|
|
116
|
+
try {
|
|
117
|
+
req.user = jwt.verify(token, process.env.JWT_SECRET);
|
|
118
|
+
next();
|
|
119
|
+
} catch {
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### [High] TG-INPUT-001 - Missing Server-Side Request Validation
|
|
123
|
+
- **Finding ID:** `TG-INPUT-001-c7457f38`
|
|
124
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:27`
|
|
125
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
126
|
+
- **Cluster:** `cluster-injection`
|
|
127
|
+
- **Description:** Destructuring unvalidated req.body without schema validation
|
|
128
|
+
```
|
|
129
|
+
// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
|
|
130
|
+
app.post('/api/login', (req, res) => {
|
|
131
|
+
const { email, password } = req.body;
|
|
132
|
+
console.log('Login attempt:', { email, password }); // TG-SEC-004
|
|
133
|
+
const user = users.find((u) => u.email === email && u.password === password);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### [High] TG-RATE-001 - Unlimited Authentication Endpoint
|
|
137
|
+
- **Finding ID:** `TG-RATE-001-dcd0a3c7`
|
|
138
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:26`
|
|
139
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
140
|
+
- **Cluster:** `cluster-rate-limiting`
|
|
141
|
+
- **Description:** Authentication POST endpoint defined without rate-limiting middleware
|
|
142
|
+
```
|
|
143
|
+
// TG-SEC-004: Logs sensitive data
|
|
144
|
+
// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
|
|
145
|
+
app.post('/api/login', (req, res) => {
|
|
146
|
+
const { email, password } = req.body;
|
|
147
|
+
console.log('Login attempt:', { email, password }); // TG-SEC-004
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### [Medium] TG-PLATFORM-002 - Missing Security Headers
|
|
151
|
+
- **Finding ID:** `TG-PLATFORM-002-1f383dcf`
|
|
152
|
+
- **Location:** `examples/hardened-react-express/server/index.js:17`
|
|
153
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
154
|
+
- **Cluster:** `cluster-platform`
|
|
155
|
+
- **Description:** Express application initialized without helmet security headers middleware
|
|
156
|
+
```
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const app = express();
|
|
160
|
+
const PORT = 3001;
|
|
161
|
+
const isProd = process.env.NODE_ENV === 'production';
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### [Medium] TG-SEC-004 - Sensitive Information in Logs
|
|
165
|
+
- **Finding ID:** `TG-SEC-004-dbbc17f7`
|
|
166
|
+
- **Location:** `examples/vulnerable-react-express/client/src/App.jsx:30`
|
|
167
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
168
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
169
|
+
- **Description:** Plaintext credential or token logged to output sink
|
|
170
|
+
```
|
|
171
|
+
const data = await res.json();
|
|
172
|
+
// TG-CLIENT-002: Sensitive console logging
|
|
173
|
+
console.log('Login token:', data.token, 'config:', clientConfig);
|
|
174
|
+
setMessage(JSON.stringify(data));
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### [Medium] TG-CLIENT-001 - Public Production Source Maps
|
|
179
|
+
- **Finding ID:** `TG-CLIENT-001-1ba4789e`
|
|
180
|
+
- **Location:** `examples/vulnerable-react-express/client/vite.config.js:7`
|
|
181
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
182
|
+
- **Cluster:** `cluster-client-leak`
|
|
183
|
+
- **Description:** Build config emitting unminified source maps in production output
|
|
184
|
+
```
|
|
185
|
+
export default defineConfig({
|
|
186
|
+
plugins: [react()],
|
|
187
|
+
build: { sourcemap: true },
|
|
188
|
+
server: {
|
|
189
|
+
port: 5173,
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### [Medium] TG-SEC-004 - Sensitive Information in Logs
|
|
193
|
+
- **Finding ID:** `TG-SEC-004-08753da5`
|
|
194
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:28`
|
|
195
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
196
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
197
|
+
- **Description:** Plaintext credential or token logged to output sink
|
|
198
|
+
```
|
|
199
|
+
app.post('/api/login', (req, res) => {
|
|
200
|
+
const { email, password } = req.body;
|
|
201
|
+
console.log('Login attempt:', { email, password }); // TG-SEC-004
|
|
202
|
+
const user = users.find((u) => u.email === email && u.password === password);
|
|
203
|
+
if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### [Medium] TG-RATE-002 - Unlimited Public Write Endpoint
|
|
207
|
+
- **Finding ID:** `TG-RATE-002-d67d7c98`
|
|
208
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:54`
|
|
209
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
210
|
+
- **Cluster:** `cluster-rate-limiting`
|
|
211
|
+
- **Description:** Public submission endpoint defined without rate-limiting or captcha defense
|
|
212
|
+
```
|
|
213
|
+
// TG-INPUT-001: No validation
|
|
214
|
+
// TG-RATE-002: Unlimited contact endpoint
|
|
215
|
+
app.post('/api/contact', (req, res) => {
|
|
216
|
+
res.json({ received: req.body });
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### [Medium] TG-PLATFORM-002 - Missing Security Headers
|
|
221
|
+
- **Finding ID:** `TG-PLATFORM-002-eef342ec`
|
|
222
|
+
- **Location:** `examples/vulnerable-react-express/server/index.js:5`
|
|
223
|
+
- **Confidence Score:** `70/100` (High Confidence)
|
|
224
|
+
- **Cluster:** `cluster-platform`
|
|
225
|
+
- **Description:** Express application initialized without helmet security headers middleware
|
|
226
|
+
```
|
|
227
|
+
const jwt = require('jsonwebtoken');
|
|
228
|
+
|
|
229
|
+
const app = express();
|
|
230
|
+
const PORT = 3001;
|
|
231
|
+
|
|
232
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"run_id": "run-20260912-215555-audit",
|
|
3
|
+
"command": "audit",
|
|
4
|
+
"target_name": "TorusGuard",
|
|
5
|
+
"created_at": "2026-09-12 21:55:55 IST",
|
|
6
|
+
"created_at_iso": "2026-09-12T21:55:55.372927+05:30",
|
|
7
|
+
"status": "completed",
|
|
8
|
+
"torusguard_version": "1.3.0",
|
|
9
|
+
"findings_count": 16,
|
|
10
|
+
"confirmed_fixed_count": 0,
|
|
11
|
+
"regressed_count": 0,
|
|
12
|
+
"remediation_bundles_count": 6
|
|
13
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# TorusGuard Governed Remediation Catalog
|
|
2
|
+
**Run ID:** `run-20260912-215555-audit`
|
|
3
|
+
**Generated:** `2026-09-12 21:56:47 IST`
|
|
4
|
+
**Candidate Bundles Formulated:** `6`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
## Formulated Candidate Patches
|
|
8
|
+
|
|
9
|
+
### [TG-SEC-001] Hardcoded Secret or API Key in Tracked Source
|
|
10
|
+
- **Target:** `examples/vulnerable-react-express/server/index.js:9` | **Bundle ID:** `bnd-tg-sec-001-9-e22e50`
|
|
11
|
+
- **Strategy:** Migrated hardcoded JWT secret to environment variable process.env.JWT_SECRET
|
|
12
|
+
- **Ponytail Churn:** `+1 / -1`
|
|
13
|
+
```diff
|
|
14
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
15
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
16
|
+
@@ -7,5 +7,5 @@
|
|
17
|
+
|
|
18
|
+
// TG-SEC-001: Hardcoded JWT secret
|
|
19
|
+
-const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';
|
|
20
|
+
+const JWT_SECRET = process.env.JWT_SECRET || "";
|
|
21
|
+
|
|
22
|
+
// TG-PLATFORM-001: Wildcard CORS with credentials
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### [TG-SSRF-004] Unbounded Outbound Request Without Timeout
|
|
26
|
+
- **Target:** `examples/python/fastapi-vuln/main.py:9` | **Bundle ID:** `bnd-tg-ssrf-004-9-9803ad`
|
|
27
|
+
- **Strategy:** Injected explicit 10-second request timeout to prevent resource exhaustion
|
|
28
|
+
- **Ponytail Churn:** `+1 / -1`
|
|
29
|
+
```diff
|
|
30
|
+
--- a/examples/python/fastapi-vuln/main.py
|
|
31
|
+
+++ b/examples/python/fastapi-vuln/main.py
|
|
32
|
+
@@ -7,5 +7,5 @@
|
|
33
|
+
@app.get("/fetch")
|
|
34
|
+
def fetch_url(url: str):
|
|
35
|
+
- response = requests.get(url)
|
|
36
|
+
+ response = requests.get(url, timeout=10)
|
|
37
|
+
return {"status": response.status_code, "content": response.text}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### [TG-INPUT-003] Unsafe Dynamic Code or HTML Execution
|
|
41
|
+
- **Target:** `examples/vulnerable-react-express/client/src/App.jsx:53` | **Bundle ID:** `bnd-tg-input-003-53-d167b4`
|
|
42
|
+
- **Strategy:** Replaced raw dangerouslySetInnerHTML injection with safe React text interpolation
|
|
43
|
+
- **Ponytail Churn:** `+1 / -1`
|
|
44
|
+
```diff
|
|
45
|
+
--- a/examples/vulnerable-react-express/client/src/App.jsx
|
|
46
|
+
+++ b/examples/vulnerable-react-express/client/src/App.jsx
|
|
47
|
+
@@ -51,5 +51,5 @@
|
|
48
|
+
|
|
49
|
+
{/* TG-INPUT-003: Unsafe HTML rendering */}
|
|
50
|
+
- <div dangerouslySetInnerHTML={{ __html: bio }} />
|
|
51
|
+
+ <div>{bio}</div>
|
|
52
|
+
|
|
53
|
+
<button onClick={fetchUser}>Fetch user (IDOR demo)</button>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### [TG-PLATFORM-001] Wildcard CORS With Credentials
|
|
57
|
+
- **Target:** `examples/vulnerable-react-express/server/index.js:12` | **Bundle ID:** `bnd-tg-platform-001-12-cf8156`
|
|
58
|
+
- **Strategy:** Constrained wildcard CORS origin to process.env.ALLOWED_ORIGIN with secure fallback
|
|
59
|
+
- **Ponytail Churn:** `+1 / -1`
|
|
60
|
+
```diff
|
|
61
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
62
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
63
|
+
@@ -10,5 +10,5 @@
|
|
64
|
+
|
|
65
|
+
// TG-PLATFORM-001: Wildcard CORS with credentials
|
|
66
|
+
-app.use(cors({ origin: '*', credentials: true }));
|
|
67
|
+
+app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));
|
|
68
|
+
|
|
69
|
+
// TG-PLATFORM-004: No explicit JSON body size limit
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### [TG-AUTH-003] Missing Object-Level Authorization (IDOR)
|
|
73
|
+
- **Target:** `examples/hardened-react-express/server/index.js:49` | **Bundle ID:** `bnd-tg-auth-003-49-7c96f3`
|
|
74
|
+
- **Strategy:** Restricted JWT verification to explicit algorithm list ['HS256']
|
|
75
|
+
- **Ponytail Churn:** `+1 / -1`
|
|
76
|
+
```diff
|
|
77
|
+
--- a/examples/hardened-react-express/server/index.js
|
|
78
|
+
+++ b/examples/hardened-react-express/server/index.js
|
|
79
|
+
@@ -47,5 +47,5 @@
|
|
80
|
+
if (!token) return res.status(401).json({ error: 'Unauthorized' });
|
|
81
|
+
try {
|
|
82
|
+
- req.user = jwt.verify(token, process.env.JWT_SECRET);
|
|
83
|
+
+ req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });
|
|
84
|
+
next();
|
|
85
|
+
} catch {
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### [TG-RATE-001] Unlimited Authentication Endpoint
|
|
89
|
+
- **Target:** `examples/vulnerable-react-express/server/index.js:26` | **Bundle ID:** `bnd-tg-rate-001-26-affcfa`
|
|
90
|
+
- **Strategy:** Injected authLimiter rate-limiting middleware to protect authentication endpoint from brute force
|
|
91
|
+
- **Ponytail Churn:** `+1 / -1`
|
|
92
|
+
```diff
|
|
93
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
94
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
95
|
+
@@ -24,5 +24,5 @@
|
|
96
|
+
// TG-SEC-004: Logs sensitive data
|
|
97
|
+
// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
|
|
98
|
+
-app.post('/api/login', (req, res) => {
|
|
99
|
+
+app.post('/api/login', authLimiter, (req, res) => {
|
|
100
|
+
const { email, password } = req.body;
|
|
101
|
+
console.log('Login attempt:', { email, password }); // TG-SEC-004
|
|
102
|
+
```
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# TorusGuard Governed Application Plan: run-20260912-215731-audit
|
|
2
|
+
- **Total Candidate Patches:** 14
|
|
3
|
+
- **Successfully Applied:** 14
|
|
4
|
+
- **Skipped by Human Gate:** 0
|
|
5
|
+
- **Execution Timestamp:** 2026-09-12 22:00:15 IST
|
|
6
|
+
- **Rollback Directory:** `.torusguard/snapshots/run-20260912-215731-audit`
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/metadata.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bundle_id": "bnd-tg-client-001-7-587129",
|
|
3
|
+
"finding_id": "TG-CLIENT-001-1ba4789e",
|
|
4
|
+
"rule_id": "TG-CLIENT-001",
|
|
5
|
+
"title": "Public Production Source Maps",
|
|
6
|
+
"target_file": "examples/vulnerable-react-express/client/vite.config.js",
|
|
7
|
+
"line_number": 7,
|
|
8
|
+
"target_line": " build: { sourcemap: true },",
|
|
9
|
+
"replacement_line": " build: { sourcemap: false },",
|
|
10
|
+
"what_is_wrong": "Build config emitting unminified source maps in production output",
|
|
11
|
+
"why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
|
|
12
|
+
"what_should_change": "Disabled public production source map emission",
|
|
13
|
+
"proposed_diff": "--- a/examples/vulnerable-react-express/client/vite.config.js\n+++ b/examples/vulnerable-react-express/client/vite.config.js\n@@ -5,5 +5,5 @@\n export default defineConfig({\n plugins: [react()],\n- build: { sourcemap: true },\n+ build: { sourcemap: false },\n server: {\n port: 5173,\n",
|
|
14
|
+
"additions": 1,
|
|
15
|
+
"deletions": 1,
|
|
16
|
+
"patched_content": "import { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\n// TG-CLIENT-001: Public production source maps enabled\nexport default defineConfig({\n plugins: [react()],\n build: { sourcemap: false },\n server: {\n port: 5173,\n proxy: { '/api': 'http://localhost:3001' },\n },\n});"
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Remediation Plan: bnd-tg-client-001-7-587129
|
|
2
|
+
- **Rule ID:** `TG-CLIENT-001`
|
|
3
|
+
- **Target File:** `examples/vulnerable-react-express/client/vite.config.js:7`
|
|
4
|
+
- **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
|
|
5
|
+
|
|
6
|
+
## Proposed Change
|
|
7
|
+
Disabled public production source map emission
|
|
8
|
+
|
|
9
|
+
## Unified Diff Preview
|
|
10
|
+
```diff
|
|
11
|
+
--- a/examples/vulnerable-react-express/client/vite.config.js
|
|
12
|
+
+++ b/examples/vulnerable-react-express/client/vite.config.js
|
|
13
|
+
@@ -5,5 +5,5 @@
|
|
14
|
+
export default defineConfig({
|
|
15
|
+
plugins: [react()],
|
|
16
|
+
- build: { sourcemap: true },
|
|
17
|
+
+ build: { sourcemap: false },
|
|
18
|
+
server: {
|
|
19
|
+
port: 5173,
|
|
20
|
+
|
|
21
|
+
```
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/patch.diff
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
--- a/examples/vulnerable-react-express/client/vite.config.js
|
|
2
|
+
+++ b/examples/vulnerable-react-express/client/vite.config.js
|
|
3
|
+
@@ -5,5 +5,5 @@
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [react()],
|
|
6
|
+
- build: { sourcemap: true },
|
|
7
|
+
+ build: { sourcemap: false },
|
|
8
|
+
server: {
|
|
9
|
+
port: 5173,
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/metadata.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bundle_id": "bnd-tg-db-002-9-5f7850",
|
|
3
|
+
"finding_id": "TG-DB-002-d9bd69df",
|
|
4
|
+
"rule_id": "TG-DB-002",
|
|
5
|
+
"title": "Privileged Database Credential in Browser Context",
|
|
6
|
+
"target_file": "demo/playground/vulnerable_nextjs/actions.ts",
|
|
7
|
+
"line_number": 9,
|
|
8
|
+
"target_line": "export const SUPABASE_SERVICE_ROLE_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo_secret_token_1234567890\";",
|
|
9
|
+
"replacement_line": "export const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || \"\";",
|
|
10
|
+
"what_is_wrong": "Service role key or raw database connection string reference in frontend code",
|
|
11
|
+
"why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
|
|
12
|
+
"what_should_change": "Replaced hardcoded privileged database credential with process.env.SUPABASE_SERVICE_ROLE_KEY",
|
|
13
|
+
"proposed_diff": "--- a/demo/playground/vulnerable_nextjs/actions.ts\n+++ b/demo/playground/vulnerable_nextjs/actions.ts\n@@ -7,5 +7,5 @@\n \n // Finding 1: TG-CLIENT-001 - Backend admin key exposed in client-accessible code\n-export const SUPABASE_SERVICE_ROLE_KEY = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo_secret_token_1234567890\";\n+export const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || \"\";\n \n interface UserRecord {\n",
|
|
14
|
+
"additions": 1,
|
|
15
|
+
"deletions": 1,
|
|
16
|
+
"patched_content": "/**\n * TorusGuard Playground: Vulnerable Next.js Server Action Fixture\n * Contains 2 intentional security findings for demonstration purposes:\n * - TG-CLIENT-001 (Leaked Service Role Key)\n * - TG-AUTH-003 (Unauthenticated Server Action Mutation)\n */\n\n// Finding 1: TG-CLIENT-001 - Backend admin key exposed in client-accessible code\nexport const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || \"\";\n\ninterface UserRecord {\n id: string;\n role: string;\n}\n\n// Finding 2: TG-AUTH-003 - Server Action performing state change without session check\nexport async function updateUserRole(userId: string, newRole: string): Promise<{ success: boolean }> {\n \"use server\";\n\n // VULNERABLE: Lacks auth session check e.g. const session = await auth(); if (!session?.user?.isAdmin) throw ...\n console.log(`[VULNERABLE] Updating user ${userId} to role ${newRole} without authentication check`);\n \n return { success: true };\n}"
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Remediation Plan: bnd-tg-db-002-9-5f7850
|
|
2
|
+
- **Rule ID:** `TG-DB-002`
|
|
3
|
+
- **Target File:** `demo/playground/vulnerable_nextjs/actions.ts:9`
|
|
4
|
+
- **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
|
|
5
|
+
|
|
6
|
+
## Proposed Change
|
|
7
|
+
Replaced hardcoded privileged database credential with process.env.SUPABASE_SERVICE_ROLE_KEY
|
|
8
|
+
|
|
9
|
+
## Unified Diff Preview
|
|
10
|
+
```diff
|
|
11
|
+
--- a/demo/playground/vulnerable_nextjs/actions.ts
|
|
12
|
+
+++ b/demo/playground/vulnerable_nextjs/actions.ts
|
|
13
|
+
@@ -7,5 +7,5 @@
|
|
14
|
+
|
|
15
|
+
// Finding 1: TG-CLIENT-001 - Backend admin key exposed in client-accessible code
|
|
16
|
+
-export const SUPABASE_SERVICE_ROLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo_secret_token_1234567890";
|
|
17
|
+
+export const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || "";
|
|
18
|
+
|
|
19
|
+
interface UserRecord {
|
|
20
|
+
|
|
21
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
--- a/demo/playground/vulnerable_nextjs/actions.ts
|
|
2
|
+
+++ b/demo/playground/vulnerable_nextjs/actions.ts
|
|
3
|
+
@@ -7,5 +7,5 @@
|
|
4
|
+
|
|
5
|
+
// Finding 1: TG-CLIENT-001 - Backend admin key exposed in client-accessible code
|
|
6
|
+
-export const SUPABASE_SERVICE_ROLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo_secret_token_1234567890";
|
|
7
|
+
+export const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || "";
|
|
8
|
+
|
|
9
|
+
interface UserRecord {
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/metadata.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bundle_id": "bnd-tg-input-001-27-2486f1",
|
|
3
|
+
"finding_id": "TG-INPUT-001-c7457f38",
|
|
4
|
+
"rule_id": "TG-INPUT-001",
|
|
5
|
+
"title": "Missing Server-Side Request Validation",
|
|
6
|
+
"target_file": "examples/vulnerable-react-express/server/index.js",
|
|
7
|
+
"line_number": 27,
|
|
8
|
+
"target_line": " const { email, password } = req.body;",
|
|
9
|
+
"replacement_line": " if (!req.body || typeof req.body !== \"object\") return res.status(400).json({ error: \"Invalid payload\" });\n const { email, password } = req.body;",
|
|
10
|
+
"what_is_wrong": "Destructuring unvalidated req.body without schema validation",
|
|
11
|
+
"why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
|
|
12
|
+
"what_should_change": "Added defensive request body payload validation before destructuring",
|
|
13
|
+
"proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -25,5 +25,5 @@\n // TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)\n app.post('/api/login', (req, res) => {\n- const { email, password } = req.body;\n+ if (!req.body || typeof req.body !== \"object\") return res.status(400).json({ error: \"Invalid payload\" });\n const { email, password } = req.body;\n console.log('Login attempt:', { email, password }); // TG-SEC-004\n const user = users.find((u) => u.email === email && u.password === password);\n",
|
|
14
|
+
"additions": 1,
|
|
15
|
+
"deletions": 1,
|
|
16
|
+
"patched_content": "const express = require('express');\nconst cors = require('cors');\nconst jwt = require('jsonwebtoken');\n\nconst app = express();\nconst PORT = 3001;\n\n// TG-SEC-001: Hardcoded JWT secret\nconst JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';\n\n// TG-PLATFORM-001: Wildcard CORS with credentials\napp.use(cors({ origin: '*', credentials: true }));\n\n// TG-PLATFORM-004: No explicit JSON body size limit\napp.use(express.json());\n\nconst users = [\n { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },\n { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },\n];\n\n// TG-RATE-001: No rate limit on login\n// TG-AUTH-001: Plaintext password comparison\n// TG-SEC-004: Logs sensitive data\n// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)\napp.post('/api/login', (req, res) => {\n if (!req.body || typeof req.body !== \"object\") return res.status(400).json({ error: \"Invalid payload\" });\n const { email, password } = req.body;\n console.log('Login attempt:', { email, password }); // TG-SEC-004\n const user = users.find((u) => u.email === email && u.password === password);\n if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration\n const token = jwt.sign({ id: user.id }, JWT_SECRET);\n res.cookie('token', token);\n res.json({ message: 'ok', token, user });\n});\n\n// TG-AUTH-003: IDOR \u2014 no ownership check\napp.get('/api/users/:id', (req, res) => {\n const user = users.find((u) => u.id === req.params.id);\n if (!user) return res.status(404).json({ error: 'Not found' });\n res.json(user);\n});\n\n// TG-INPUT-002: SQL concatenation (simulated query string)\n// TG-RATE-003: Unbounded results\napp.get('/api/search', (req, res) => {\n const q = req.query.q || '';\n const fakeSql = `SELECT * FROM users WHERE email LIKE '%${q}%'`;\n const results = users.filter((u) => u.email.includes(q));\n res.json({ query: fakeSql, results });\n});\n\n// TG-INPUT-001: No validation\n// TG-RATE-002: Unlimited contact endpoint\napp.post('/api/contact', (req, res) => {\n res.json({ received: req.body });\n});\n\n// TG-RATE-002: Unlimited AI endpoint\napp.post('/api/ai', (req, res) => {\n res.json({ reply: 'demo', prompt: req.body.prompt });\n});\n\n// TG-INPUT-004: Unrestricted upload (stub)\napp.post('/api/upload', (req, res) => {\n res.json({ saved: req.body.filename });\n});\n\n// TG-AUTH-005: Unsafe password reset\napp.post('/api/reset', (req, res) => {\n const { email } = req.body;\n const user = users.find((u) => u.email === email);\n if (!user) return res.status(404).json({ error: 'Email not registered' }); // enumeration\n const token = `reset-${user.id}-12345`; // predictable\n res.json({ resetToken: token });\n});\n\napp.use((err, req, res, next) => {\n // TG-PLATFORM-003: Stack trace exposed\n res.status(500).json({ error: err.message, stack: err.stack });\n});\n\napp.listen(PORT, () => console.log(`Vulnerable demo server http://localhost:${PORT}`));"
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Remediation Plan: bnd-tg-input-001-27-2486f1
|
|
2
|
+
- **Rule ID:** `TG-INPUT-001`
|
|
3
|
+
- **Target File:** `examples/vulnerable-react-express/server/index.js:27`
|
|
4
|
+
- **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
|
|
5
|
+
|
|
6
|
+
## Proposed Change
|
|
7
|
+
Added defensive request body payload validation before destructuring
|
|
8
|
+
|
|
9
|
+
## Unified Diff Preview
|
|
10
|
+
```diff
|
|
11
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
12
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
13
|
+
@@ -25,5 +25,5 @@
|
|
14
|
+
// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
|
|
15
|
+
app.post('/api/login', (req, res) => {
|
|
16
|
+
- const { email, password } = req.body;
|
|
17
|
+
+ if (!req.body || typeof req.body !== "object") return res.status(400).json({ error: "Invalid payload" });
|
|
18
|
+
const { email, password } = req.body;
|
|
19
|
+
console.log('Login attempt:', { email, password }); // TG-SEC-004
|
|
20
|
+
const user = users.find((u) => u.email === email && u.password === password);
|
|
21
|
+
|
|
22
|
+
```
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/patch.diff
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
2
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
3
|
+
@@ -25,5 +25,5 @@
|
|
4
|
+
// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
|
|
5
|
+
app.post('/api/login', (req, res) => {
|
|
6
|
+
- const { email, password } = req.body;
|
|
7
|
+
+ if (!req.body || typeof req.body !== "object") return res.status(400).json({ error: "Invalid payload" });
|
|
8
|
+
const { email, password } = req.body;
|
|
9
|
+
console.log('Login attempt:', { email, password }); // TG-SEC-004
|
|
10
|
+
const user = users.find((u) => u.email === email && u.password === password);
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bundle_id": "bnd-tg-input-003-53-d167b4",
|
|
3
|
+
"finding_id": "TG-INPUT-003-fea9421e",
|
|
4
|
+
"rule_id": "TG-INPUT-003",
|
|
5
|
+
"title": "Unsafe Dynamic Code or HTML Execution",
|
|
6
|
+
"target_file": "examples/vulnerable-react-express/client/src/App.jsx",
|
|
7
|
+
"line_number": 53,
|
|
8
|
+
"target_line": " <div dangerouslySetInnerHTML={{ __html: bio }} />",
|
|
9
|
+
"replacement_line": " <div>{bio}</div>",
|
|
10
|
+
"what_is_wrong": "React dangerouslySetInnerHTML rendering raw unescaped HTML",
|
|
11
|
+
"why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
|
|
12
|
+
"what_should_change": "Replaced raw dangerouslySetInnerHTML injection with safe React text interpolation",
|
|
13
|
+
"proposed_diff": "--- a/examples/vulnerable-react-express/client/src/App.jsx\n+++ b/examples/vulnerable-react-express/client/src/App.jsx\n@@ -51,5 +51,5 @@\n \n {/* TG-INPUT-003: Unsafe HTML rendering */}\n- <div dangerouslySetInnerHTML={{ __html: bio }} />\n+ <div>{bio}</div>\n \n <button onClick={fetchUser}>Fetch user (IDOR demo)</button>\n",
|
|
14
|
+
"additions": 1,
|
|
15
|
+
"deletions": 1,
|
|
16
|
+
"patched_content": "import { useState } from 'react';\nimport { clientConfig } from './config';\n\n// TG-DB-001: SQL query construction in frontend (never do this)\nfunction buildSearchQuery(email) {\n return `SELECT id, email FROM users WHERE email LIKE '%${email}%'`;\n}\n\n// TG-DB-003: Documented anti-pattern \u2014 Prisma must never run in browser\n// import { PrismaClient } from '@prisma/client'; // FORBIDDEN in client\n\nexport default function App() {\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [bio, setBio] = useState('<img src=x onerror=alert(1)>');\n const [userId, setUserId] = useState('1');\n const [isAdmin] = useState(localStorage.getItem('role') === 'admin'); // TG-AUTH-002\n const [message, setMessage] = useState('');\n\n async function login(e) {\n e.preventDefault();\n const res = await fetch('/api/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n // TG-CLIENT-002: Sensitive console logging\n console.log('Login token:', data.token, 'config:', clientConfig);\n setMessage(JSON.stringify(data));\n }\n\n async function fetchUser() {\n const res = await fetch(`/api/users/${userId}`);\n setMessage(await res.text());\n }\n\n return (\n <div style={{ maxWidth: 560, margin: '2rem auto', fontFamily: 'sans-serif' }}>\n <h1>Vulnerable Demo</h1>\n <p style={{ color: 'crimson' }}>Intentionally insecure \u2014 localhost lab only</p>\n\n <form onSubmit={login}>\n <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder=\"email\" />\n <input value={password} onChange={(e) => setPassword(e.target.value)} placeholder=\"password\" type=\"password\" />\n <button type=\"submit\">Login</button>\n </form>\n\n <p>Frontend SQL preview: {buildSearchQuery(email)}</p>\n\n {/* TG-INPUT-003: Unsafe HTML rendering */}\n <div>{bio}</div>\n\n <button onClick={fetchUser}>Fetch user (IDOR demo)</button>\n\n {/* TG-AUTH-002: Client-only admin gate */}\n {isAdmin && <section><h2>Admin Panel</h2><p>Visible if localStorage role=admin \u2014 not real security</p></section>}\n\n {message && <pre>{message}</pre>}\n </div>\n );\n}"
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Remediation Plan: bnd-tg-input-003-53-d167b4
|
|
2
|
+
- **Rule ID:** `TG-INPUT-003`
|
|
3
|
+
- **Target File:** `examples/vulnerable-react-express/client/src/App.jsx:53`
|
|
4
|
+
- **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
|
|
5
|
+
|
|
6
|
+
## Proposed Change
|
|
7
|
+
Replaced raw dangerouslySetInnerHTML injection with safe React text interpolation
|
|
8
|
+
|
|
9
|
+
## Unified Diff Preview
|
|
10
|
+
```diff
|
|
11
|
+
--- a/examples/vulnerable-react-express/client/src/App.jsx
|
|
12
|
+
+++ b/examples/vulnerable-react-express/client/src/App.jsx
|
|
13
|
+
@@ -51,5 +51,5 @@
|
|
14
|
+
|
|
15
|
+
{/* TG-INPUT-003: Unsafe HTML rendering */}
|
|
16
|
+
- <div dangerouslySetInnerHTML={{ __html: bio }} />
|
|
17
|
+
+ <div>{bio}</div>
|
|
18
|
+
|
|
19
|
+
<button onClick={fetchUser}>Fetch user (IDOR demo)</button>
|
|
20
|
+
|
|
21
|
+
```
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
--- a/examples/vulnerable-react-express/client/src/App.jsx
|
|
2
|
+
+++ b/examples/vulnerable-react-express/client/src/App.jsx
|
|
3
|
+
@@ -51,5 +51,5 @@
|
|
4
|
+
|
|
5
|
+
{/* TG-INPUT-003: Unsafe HTML rendering */}
|
|
6
|
+
- <div dangerouslySetInnerHTML={{ __html: bio }} />
|
|
7
|
+
+ <div>{bio}</div>
|
|
8
|
+
|
|
9
|
+
<button onClick={fetchUser}>Fetch user (IDOR demo)</button>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bundle_id": "bnd-tg-platform-001-12-cf8156",
|
|
3
|
+
"finding_id": "TG-PLATFORM-001-7dd35cb4",
|
|
4
|
+
"rule_id": "TG-PLATFORM-001",
|
|
5
|
+
"title": "Wildcard CORS With Credentials",
|
|
6
|
+
"target_file": "examples/vulnerable-react-express/server/index.js",
|
|
7
|
+
"line_number": 12,
|
|
8
|
+
"target_line": "app.use(cors({ origin: '*', credentials: true }));",
|
|
9
|
+
"replacement_line": "app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));",
|
|
10
|
+
"what_is_wrong": "Wildcard CORS origin configured in Express middleware",
|
|
11
|
+
"why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
|
|
12
|
+
"what_should_change": "Constrained wildcard CORS origin to process.env.ALLOWED_ORIGIN with secure fallback",
|
|
13
|
+
"proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -10,5 +10,5 @@\n \n // TG-PLATFORM-001: Wildcard CORS with credentials\n-app.use(cors({ origin: '*', credentials: true }));\n+app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));\n \n // TG-PLATFORM-004: No explicit JSON body size limit\n",
|
|
14
|
+
"additions": 1,
|
|
15
|
+
"deletions": 1,
|
|
16
|
+
"patched_content": "const express = require('express');\nconst cors = require('cors');\nconst jwt = require('jsonwebtoken');\n\nconst app = express();\nconst PORT = 3001;\n\n// TG-SEC-001: Hardcoded JWT secret\nconst JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';\n\n// TG-PLATFORM-001: Wildcard CORS with credentials\napp.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));\n\n// TG-PLATFORM-004: No explicit JSON body size limit\napp.use(express.json());\n\nconst users = [\n { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },\n { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },\n];\n\n// TG-RATE-001: No rate limit on login\n// TG-AUTH-001: Plaintext password comparison\n// TG-SEC-004: Logs sensitive data\n// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)\napp.post('/api/login', (req, res) => {\n const { email, password } = req.body;\n console.log('Login attempt:', { email, password }); // TG-SEC-004\n const user = users.find((u) => u.email === email && u.password === password);\n if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration\n const token = jwt.sign({ id: user.id }, JWT_SECRET);\n res.cookie('token', token);\n res.json({ message: 'ok', token, user });\n});\n\n// TG-AUTH-003: IDOR \u2014 no ownership check\napp.get('/api/users/:id', (req, res) => {\n const user = users.find((u) => u.id === req.params.id);\n if (!user) return res.status(404).json({ error: 'Not found' });\n res.json(user);\n});\n\n// TG-INPUT-002: SQL concatenation (simulated query string)\n// TG-RATE-003: Unbounded results\napp.get('/api/search', (req, res) => {\n const q = req.query.q || '';\n const fakeSql = `SELECT * FROM users WHERE email LIKE '%${q}%'`;\n const results = users.filter((u) => u.email.includes(q));\n res.json({ query: fakeSql, results });\n});\n\n// TG-INPUT-001: No validation\n// TG-RATE-002: Unlimited contact endpoint\napp.post('/api/contact', (req, res) => {\n res.json({ received: req.body });\n});\n\n// TG-RATE-002: Unlimited AI endpoint\napp.post('/api/ai', (req, res) => {\n res.json({ reply: 'demo', prompt: req.body.prompt });\n});\n\n// TG-INPUT-004: Unrestricted upload (stub)\napp.post('/api/upload', (req, res) => {\n res.json({ saved: req.body.filename });\n});\n\n// TG-AUTH-005: Unsafe password reset\napp.post('/api/reset', (req, res) => {\n const { email } = req.body;\n const user = users.find((u) => u.email === email);\n if (!user) return res.status(404).json({ error: 'Email not registered' }); // enumeration\n const token = `reset-${user.id}-12345`; // predictable\n res.json({ resetToken: token });\n});\n\napp.use((err, req, res, next) => {\n // TG-PLATFORM-003: Stack trace exposed\n res.status(500).json({ error: err.message, stack: err.stack });\n});\n\napp.listen(PORT, () => console.log(`Vulnerable demo server http://localhost:${PORT}`));"
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Remediation Plan: bnd-tg-platform-001-12-cf8156
|
|
2
|
+
- **Rule ID:** `TG-PLATFORM-001`
|
|
3
|
+
- **Target File:** `examples/vulnerable-react-express/server/index.js:12`
|
|
4
|
+
- **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
|
|
5
|
+
|
|
6
|
+
## Proposed Change
|
|
7
|
+
Constrained wildcard CORS origin to process.env.ALLOWED_ORIGIN with secure fallback
|
|
8
|
+
|
|
9
|
+
## Unified Diff Preview
|
|
10
|
+
```diff
|
|
11
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
12
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
13
|
+
@@ -10,5 +10,5 @@
|
|
14
|
+
|
|
15
|
+
// TG-PLATFORM-001: Wildcard CORS with credentials
|
|
16
|
+
-app.use(cors({ origin: '*', credentials: true }));
|
|
17
|
+
+app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));
|
|
18
|
+
|
|
19
|
+
// TG-PLATFORM-004: No explicit JSON body size limit
|
|
20
|
+
|
|
21
|
+
```
|
package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
--- a/examples/vulnerable-react-express/server/index.js
|
|
2
|
+
+++ b/examples/vulnerable-react-express/server/index.js
|
|
3
|
+
@@ -10,5 +10,5 @@
|
|
4
|
+
|
|
5
|
+
// TG-PLATFORM-001: Wildcard CORS with credentials
|
|
6
|
+
-app.use(cors({ origin: '*', credentials: true }));
|
|
7
|
+
+app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));
|
|
8
|
+
|
|
9
|
+
// TG-PLATFORM-004: No explicit JSON body size limit
|