torusguard 1.0.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.torusguard/.manifest.json +196 -78
- package/.torusguard/references/csharp-security.md +41 -0
- package/.torusguard/references/go-security.md +41 -0
- package/.torusguard/references/java-security.md +40 -0
- package/.torusguard/references/polyglot-security-matrix.md +25 -0
- package/.torusguard/references/rust-security.md +40 -0
- package/.torusguard/rules/README.md +93 -62
- package/.torusguard/rules/TG-AUTH-001-weak-password-storage.md +103 -0
- package/.torusguard/rules/TG-AUTH-002-client-only-authorization.md +85 -0
- package/.torusguard/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/.torusguard/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/.torusguard/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/.torusguard/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/.torusguard/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/.torusguard/rules/TG-DB-001-frontend-database-query.md +83 -0
- package/.torusguard/rules/TG-DB-002-privileged-database-credential.md +86 -0
- package/.torusguard/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/.torusguard/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/.torusguard/rules/TG-INPUT-001-missing-server-validation.md +98 -0
- package/.torusguard/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/.torusguard/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/.torusguard/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/.torusguard/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/.torusguard/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/.torusguard/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/.torusguard/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/.torusguard/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/.torusguard/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/.torusguard/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/.torusguard/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/.torusguard/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/.torusguard/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/.torusguard/rules/TG-SEC-002-public-environment-secrets.md +83 -0
- package/.torusguard/rules/TG-SEC-003-tracked-env-file.md +79 -0
- package/.torusguard/rules/TG-SEC-004-sensitive-logging.md +83 -0
- package/.torusguard/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
- package/.torusguard/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
- package/.torusguard/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/.torusguard/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/.torusguard/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/.torusguard/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/.torusguard/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/.torusguard/rules/active/TG-DB-001-frontend-database-query.md +83 -0
- package/.torusguard/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
- package/.torusguard/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/.torusguard/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/.torusguard/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
- package/.torusguard/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/.torusguard/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/.torusguard/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/.torusguard/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/.torusguard/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/.torusguard/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/.torusguard/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/.torusguard/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/.torusguard/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/.torusguard/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/.torusguard/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/.torusguard/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/.torusguard/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/.torusguard/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
- package/.torusguard/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
- package/.torusguard/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
- package/.torusguard/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
- package/.torusguard/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
- package/.torusguard/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
- package/.torusguard/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
- package/.torusguard/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
- package/.torusguard/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
- package/.torusguard/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
- package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
- package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
- package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
- package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
- package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
- package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
- package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
- package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
- package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
- package/.torusguard/rules/custom/.gitkeep +1 -0
- package/.torusguard/rules/custom/README.md +30 -0
- package/.torusguard/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
- package/.torusguard/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
- package/.torusguard/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
- package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
- package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
- package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
- package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
- package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
- package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
- package/.torusguard/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
- package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
- package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
- package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
- package/.torusguard/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
- package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
- package/.torusguard/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
- package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
- package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
- package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
- package/.torusguard/runs/report-latest.html +370 -0
- package/.torusguard/runs/run-20260908-112648-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-112648-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-112648-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260908-112648-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-112722-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-112722-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-112722-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260908-112722-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-113004-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-113004-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-113004-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260908-113004-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-113127-audit/findings.json +1520 -0
- package/.torusguard/runs/run-20260908-113127-audit/findings.md +560 -0
- package/.torusguard/runs/run-20260908-113127-audit/manifest.json +13 -0
- package/.torusguard/runs/run-20260908-113127-audit/remediation.md +262 -0
- package/.torusguard/runs/run-20260908-113127-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260908-115240-audit/apply_plan.md +6 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
- package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
- package/.torusguard/runs/run-20260908-115240-audit/diff_summary.md +221 -0
- package/.torusguard/runs/run-20260908-115240-audit/findings.json +1553 -0
- package/.torusguard/runs/run-20260908-115240-audit/findings.md +572 -0
- package/.torusguard/runs/run-20260908-115240-audit/manifest.json +14 -0
- package/.torusguard/runs/run-20260908-115240-audit/recheck.md +91 -0
- package/.torusguard/runs/run-20260908-115240-audit/remediation.md +278 -0
- package/.torusguard/runs/run-20260908-115240-audit/summary.md +5 -0
- package/.torusguard/schemas/golden-recipe.schema.json +75 -0
- package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
- package/.torusguard/scripts/apply_runner.py +332 -0
- package/.torusguard/scripts/audit_runner.py +550 -0
- package/.torusguard/scripts/diff_guard.py +183 -8
- package/.torusguard/scripts/finding_scorer.py +91 -5
- package/.torusguard/scripts/harden_runner.py +353 -0
- package/.torusguard/scripts/html_reporter.py +643 -0
- package/.torusguard/scripts/manifest_builder.py +7 -5
- package/.torusguard/scripts/memory_engine.py +525 -99
- package/.torusguard/scripts/monorepo_detector.py +123 -10
- package/.torusguard/scripts/recheck_runner.py +221 -0
- package/.torusguard/scripts/recipes_runner.py +130 -0
- package/.torusguard/scripts/rules_sync.py +321 -0
- package/.torusguard/scripts/run_manager.py +17 -5
- package/.torusguard/scripts/stack_detect.py +458 -26
- package/.torusguard/skills/torusguard/SKILL.md +42 -42
- package/.torusguard/skills/torusguard/references/csharp-security.md +41 -0
- package/.torusguard/skills/torusguard/references/go-security.md +41 -0
- package/.torusguard/skills/torusguard/references/java-security.md +40 -0
- package/.torusguard/skills/torusguard/references/polyglot-security-matrix.md +25 -0
- package/.torusguard/skills/torusguard/references/rust-security.md +40 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/engine/fixture_manager.py.bak +245 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/master_validation.py.bak +698 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/runner.py.bak +551 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_e2e.py.bak +498 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_qa_v0_6_0.py.bak +572 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_1_scale.py.bak +371 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_2_modern_stacks.py.bak +462 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_3_hardening.py.bak +444 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_0_0_memory.py.bak +302 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_1_0_advanced_memory.py.bak +342 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/skills/torusguard/payload/scripts/harden_runner.py.bak +353 -0
- package/.torusguard/snapshots/run-20260908-115240-audit/tests/test_v0_6_0_governed_remediation.py.bak +353 -0
- package/README.md +344 -410
- package/bin/torusguard.js +195 -21
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +42 -42
- package/skills/torusguard/bootstrap.py +149 -70
- package/skills/torusguard/payload/.manifest.json +196 -78
- package/skills/torusguard/payload/references/csharp-security.md +41 -0
- package/skills/torusguard/payload/references/go-security.md +41 -0
- package/skills/torusguard/payload/references/java-security.md +40 -0
- package/skills/torusguard/payload/references/polyglot-security-matrix.md +25 -0
- package/skills/torusguard/payload/references/rust-security.md +40 -0
- package/skills/torusguard/payload/rules/README.md +93 -62
- package/skills/torusguard/payload/rules/TG-AUTH-001-weak-password-storage.md +103 -0
- package/skills/torusguard/payload/rules/TG-AUTH-002-client-only-authorization.md +85 -0
- package/skills/torusguard/payload/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/skills/torusguard/payload/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/skills/torusguard/payload/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/skills/torusguard/payload/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/skills/torusguard/payload/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/skills/torusguard/payload/rules/TG-DB-001-frontend-database-query.md +83 -0
- package/skills/torusguard/payload/rules/TG-DB-002-privileged-database-credential.md +86 -0
- package/skills/torusguard/payload/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/skills/torusguard/payload/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/skills/torusguard/payload/rules/TG-INPUT-001-missing-server-validation.md +98 -0
- package/skills/torusguard/payload/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/skills/torusguard/payload/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/skills/torusguard/payload/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/skills/torusguard/payload/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/skills/torusguard/payload/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/skills/torusguard/payload/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/skills/torusguard/payload/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/skills/torusguard/payload/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/skills/torusguard/payload/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/skills/torusguard/payload/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/skills/torusguard/payload/rules/TG-SEC-002-public-environment-secrets.md +83 -0
- package/skills/torusguard/payload/rules/TG-SEC-003-tracked-env-file.md +79 -0
- package/skills/torusguard/payload/rules/TG-SEC-004-sensitive-logging.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
- package/skills/torusguard/payload/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
- package/skills/torusguard/payload/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-DB-001-frontend-database-query.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
- package/skills/torusguard/payload/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
- package/skills/torusguard/payload/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
- package/skills/torusguard/payload/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
- package/skills/torusguard/payload/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
- package/skills/torusguard/payload/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
- package/skills/torusguard/payload/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
- package/skills/torusguard/payload/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
- package/skills/torusguard/payload/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
- package/skills/torusguard/payload/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
- package/skills/torusguard/payload/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
- package/skills/torusguard/payload/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
- package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
- package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
- package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
- package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
- package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
- package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
- package/skills/torusguard/payload/rules/custom/.gitkeep +1 -0
- package/skills/torusguard/payload/rules/custom/README.md +30 -0
- package/skills/torusguard/payload/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
- package/skills/torusguard/payload/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
- package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
- package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
- package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
- package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
- package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
- package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
- package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
- package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
- package/skills/torusguard/payload/schemas/golden-recipe.schema.json +75 -0
- package/skills/torusguard/payload/scripts/apply_runner.py +332 -0
- package/skills/torusguard/payload/scripts/audit_runner.py +550 -0
- package/skills/torusguard/payload/scripts/diff_guard.py +183 -8
- package/skills/torusguard/payload/scripts/finding_scorer.py +91 -5
- package/skills/torusguard/payload/scripts/harden_runner.py +353 -0
- package/skills/torusguard/payload/scripts/html_reporter.py +643 -0
- package/skills/torusguard/payload/scripts/manifest_builder.py +7 -5
- package/skills/torusguard/payload/scripts/memory_engine.py +525 -99
- package/skills/torusguard/payload/scripts/monorepo_detector.py +123 -10
- package/skills/torusguard/payload/scripts/recheck_runner.py +221 -0
- package/skills/torusguard/payload/scripts/recipes_runner.py +130 -0
- package/skills/torusguard/payload/scripts/rules_sync.py +321 -0
- package/skills/torusguard/payload/scripts/run_manager.py +17 -5
- package/skills/torusguard/payload/scripts/stack_detect.py +458 -26
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +42 -42
- package/skills/torusguard/payload/skills/torusguard/bootstrap.py +149 -70
- package/skills/torusguard/payload/skills/torusguard/references/csharp-security.md +41 -0
- package/skills/torusguard/payload/skills/torusguard/references/go-security.md +41 -0
- package/skills/torusguard/payload/skills/torusguard/references/java-security.md +40 -0
- package/skills/torusguard/payload/skills/torusguard/references/polyglot-security-matrix.md +25 -0
- package/skills/torusguard/payload/skills/torusguard/references/rust-security.md +40 -0
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
|
@@ -26,7 +26,7 @@ def detect_package_info(abs_pkg_dir: Path, root: Path) -> Dict[str, Any]:
|
|
|
26
26
|
# Check typescript / javascript
|
|
27
27
|
package_json = pkg_dir / "package.json"
|
|
28
28
|
if package_json.is_file() or list(pkg_dir.glob("*.ts")) or list(pkg_dir.glob("*.js")):
|
|
29
|
-
language = "
|
|
29
|
+
language = "TypeScript" if (list(pkg_dir.glob("*.ts")) or list(pkg_dir.glob("**/*.ts"))) else "JavaScript"
|
|
30
30
|
if package_json.is_file():
|
|
31
31
|
try:
|
|
32
32
|
with open(package_json, "r", encoding="utf-8") as f:
|
|
@@ -35,6 +35,8 @@ def detect_package_info(abs_pkg_dir: Path, root: Path) -> Dict[str, Any]:
|
|
|
35
35
|
deps = {**pj.get("dependencies", {}), **pj.get("devDependencies", {})}
|
|
36
36
|
if "next" in deps:
|
|
37
37
|
framework = "nextjs"
|
|
38
|
+
elif "@nestjs/core" in deps:
|
|
39
|
+
framework = "nestjs"
|
|
38
40
|
elif "express" in deps:
|
|
39
41
|
framework = "express"
|
|
40
42
|
elif "react" in deps:
|
|
@@ -51,7 +53,7 @@ def detect_package_info(abs_pkg_dir: Path, root: Path) -> Dict[str, Any]:
|
|
|
51
53
|
reqs = pkg_dir / "requirements.txt"
|
|
52
54
|
if pyproject.is_file() or reqs.is_file() or list(pkg_dir.glob("*.py")):
|
|
53
55
|
if language == "unknown":
|
|
54
|
-
language = "
|
|
56
|
+
language = "Python"
|
|
55
57
|
content = ""
|
|
56
58
|
if pyproject.is_file():
|
|
57
59
|
content += pyproject.read_text(encoding="utf-8", errors="replace").lower()
|
|
@@ -61,17 +63,116 @@ def detect_package_info(abs_pkg_dir: Path, root: Path) -> Dict[str, Any]:
|
|
|
61
63
|
content += pyf.read_text(encoding="utf-8", errors="replace").lower()
|
|
62
64
|
|
|
63
65
|
if "fastapi" in content or "fastapi" in pkg_dir.name:
|
|
64
|
-
framework = "
|
|
66
|
+
framework = "FastAPI"
|
|
65
67
|
elif "django" in content or "django" in pkg_dir.name:
|
|
66
|
-
framework = "
|
|
68
|
+
framework = "Django"
|
|
67
69
|
elif "flask" in content or "flask" in pkg_dir.name:
|
|
68
|
-
framework = "
|
|
70
|
+
framework = "Flask"
|
|
71
|
+
|
|
72
|
+
# Check Go
|
|
73
|
+
go_mod = pkg_dir / "go.mod"
|
|
74
|
+
if go_mod.is_file() or list(pkg_dir.glob("*.go")):
|
|
75
|
+
if language == "unknown":
|
|
76
|
+
language = "Go"
|
|
77
|
+
if go_mod.is_file():
|
|
78
|
+
try:
|
|
79
|
+
gc = go_mod.read_text(encoding="utf-8", errors="replace")
|
|
80
|
+
if "gin-gonic/gin" in gc:
|
|
81
|
+
framework = "Gin"
|
|
82
|
+
elif "gofiber/fiber" in gc:
|
|
83
|
+
framework = "Fiber"
|
|
84
|
+
elif "go-chi/chi" in gc:
|
|
85
|
+
framework = "Chi"
|
|
86
|
+
except Exception:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
# Check Rust
|
|
90
|
+
cargo_toml = pkg_dir / "Cargo.toml"
|
|
91
|
+
if cargo_toml.is_file() or list(pkg_dir.glob("*.rs")):
|
|
92
|
+
if language == "unknown":
|
|
93
|
+
language = "Rust"
|
|
94
|
+
if cargo_toml.is_file():
|
|
95
|
+
try:
|
|
96
|
+
cc = cargo_toml.read_text(encoding="utf-8", errors="replace")
|
|
97
|
+
if "actix-web" in cc:
|
|
98
|
+
framework = "Actix-web"
|
|
99
|
+
elif "axum" in cc:
|
|
100
|
+
framework = "Axum"
|
|
101
|
+
elif "rocket" in cc:
|
|
102
|
+
framework = "Rocket"
|
|
103
|
+
except Exception:
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
# Check Java / Kotlin
|
|
107
|
+
pom_xml = pkg_dir / "pom.xml"
|
|
108
|
+
b_gradle = pkg_dir / "build.gradle"
|
|
109
|
+
b_gradle_kts = pkg_dir / "build.gradle.kts"
|
|
110
|
+
if pom_xml.is_file() or b_gradle.is_file() or b_gradle_kts.is_file() or list(pkg_dir.glob("**/*.java")) or list(pkg_dir.glob("**/*.kt")):
|
|
111
|
+
if language == "unknown":
|
|
112
|
+
language = "Kotlin" if (b_gradle_kts.is_file() or list(pkg_dir.glob("**/*.kt"))) else "Java"
|
|
113
|
+
jc = ""
|
|
114
|
+
for jf in [pom_xml, b_gradle, b_gradle_kts]:
|
|
115
|
+
if jf.is_file():
|
|
116
|
+
try:
|
|
117
|
+
jc += jf.read_text(encoding="utf-8", errors="replace") + "\n"
|
|
118
|
+
except Exception:
|
|
119
|
+
pass
|
|
120
|
+
if "spring-boot" in jc or "springframework" in jc:
|
|
121
|
+
framework = "Spring Boot"
|
|
122
|
+
elif "quarkus" in jc:
|
|
123
|
+
framework = "Quarkus"
|
|
124
|
+
elif "ktor" in jc:
|
|
125
|
+
framework = "Ktor"
|
|
126
|
+
|
|
127
|
+
# Check C#
|
|
128
|
+
csprojs = list(pkg_dir.glob("*.csproj")) + list(pkg_dir.glob("**/*.csproj"))
|
|
129
|
+
if csprojs or list(pkg_dir.glob("*.sln")) or list(pkg_dir.glob("*.cs")):
|
|
130
|
+
if language == "unknown":
|
|
131
|
+
language = "C#"
|
|
132
|
+
csc = ""
|
|
133
|
+
for cf in csprojs[:5]:
|
|
134
|
+
try:
|
|
135
|
+
csc += cf.read_text(encoding="utf-8", errors="replace") + "\n"
|
|
136
|
+
except Exception:
|
|
137
|
+
pass
|
|
138
|
+
if "Microsoft.NET.Sdk.Web" in csc or "Microsoft.AspNetCore" in csc or "Swashbuckle" in csc:
|
|
139
|
+
framework = "ASP.NET Core"
|
|
140
|
+
|
|
141
|
+
# Check PHP
|
|
142
|
+
composer_json = pkg_dir / "composer.json"
|
|
143
|
+
if composer_json.is_file() or list(pkg_dir.glob("*.php")):
|
|
144
|
+
if language == "unknown":
|
|
145
|
+
language = "PHP"
|
|
146
|
+
if composer_json.is_file():
|
|
147
|
+
try:
|
|
148
|
+
with open(composer_json, "r", encoding="utf-8") as f:
|
|
149
|
+
c_data = json.load(f)
|
|
150
|
+
reqs = {**c_data.get("require", {}), **c_data.get("require-dev", {})}
|
|
151
|
+
if "laravel/framework" in reqs:
|
|
152
|
+
framework = "Laravel"
|
|
153
|
+
elif any("symfony" in k for k in reqs):
|
|
154
|
+
framework = "Symfony"
|
|
155
|
+
except Exception:
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
# Check Ruby
|
|
159
|
+
gemfile = pkg_dir / "Gemfile"
|
|
160
|
+
if gemfile.is_file() or list(pkg_dir.glob("*.rb")):
|
|
161
|
+
if language == "unknown":
|
|
162
|
+
language = "Ruby"
|
|
163
|
+
if gemfile.is_file():
|
|
164
|
+
try:
|
|
165
|
+
gc = gemfile.read_text(encoding="utf-8", errors="replace")
|
|
166
|
+
if "rails" in gc:
|
|
167
|
+
framework = "Ruby on Rails"
|
|
168
|
+
except Exception:
|
|
169
|
+
pass
|
|
69
170
|
|
|
70
171
|
return {
|
|
71
172
|
"name": name,
|
|
72
173
|
"path": rel_path,
|
|
73
|
-
"language": language,
|
|
74
|
-
"framework": framework
|
|
174
|
+
"language": language.lower(),
|
|
175
|
+
"framework": framework.lower()
|
|
75
176
|
}
|
|
76
177
|
|
|
77
178
|
|
|
@@ -102,21 +203,33 @@ def scan_workspace(root_dir: str = ".") -> Dict[str, Any]:
|
|
|
102
203
|
pass
|
|
103
204
|
|
|
104
205
|
# Scan common monorepo container directories and direct project subfolders
|
|
105
|
-
candidate_folders = ["apps", "packages", "services", "libs", "modules"]
|
|
206
|
+
candidate_folders = ["apps", "packages", "services", "src", "libs", "modules"]
|
|
207
|
+
manifest_names = [
|
|
208
|
+
"package.json", "pyproject.toml", "requirements.txt", "setup.py", "Cargo.toml",
|
|
209
|
+
"go.mod", "pom.xml", "build.gradle", "build.gradle.kts", "composer.json",
|
|
210
|
+
"Gemfile", "mix.exs", "pubspec.yaml", "CMakeLists.txt", "main.py", "main.go", "actions.ts"
|
|
211
|
+
]
|
|
106
212
|
found_dirs = []
|
|
107
213
|
|
|
214
|
+
def has_manifest(d: Path) -> bool:
|
|
215
|
+
if any((d / m).exists() for m in manifest_names):
|
|
216
|
+
return True
|
|
217
|
+
if list(d.glob("*.csproj")) or list(d.glob("*/*.csproj")):
|
|
218
|
+
return True
|
|
219
|
+
return False
|
|
220
|
+
|
|
108
221
|
for cf in candidate_folders:
|
|
109
222
|
container = root / cf
|
|
110
223
|
if container.is_dir():
|
|
111
224
|
for child in container.iterdir():
|
|
112
225
|
if child.is_dir() and not child.name.startswith(('.', '_')):
|
|
113
|
-
if
|
|
226
|
+
if has_manifest(child):
|
|
114
227
|
found_dirs.append(child)
|
|
115
228
|
|
|
116
229
|
# Also scan direct subdirectories if not already captured
|
|
117
230
|
for child in root.iterdir():
|
|
118
231
|
if child.is_dir() and not child.name.startswith(('.', '_')) and child.name not in candidate_folders:
|
|
119
|
-
if
|
|
232
|
+
if has_manifest(child):
|
|
120
233
|
if child not in found_dirs:
|
|
121
234
|
found_dirs.append(child)
|
|
122
235
|
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TorusGuard Targeted Differential Recheck Engine (v1.3.0)
|
|
4
|
+
Executes scoped differential re-audits verifying only impacted files and adjacent boundaries.
|
|
5
|
+
Evaluates formal status transitions (Confirmed Fixed vs Regressed), updates run manifest,
|
|
6
|
+
and records verification telemetry in the persistent security memory subsystem.
|
|
7
|
+
|
|
8
|
+
Pure Python 3.10+ standard library (zero external dependencies).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import json
|
|
15
|
+
import argparse
|
|
16
|
+
import datetime
|
|
17
|
+
import unicodedata
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Dict, List, Any, Optional, Tuple
|
|
20
|
+
|
|
21
|
+
# Windows console UTF-8 support
|
|
22
|
+
if sys.stdout and hasattr(sys.stdout, "reconfigure"):
|
|
23
|
+
try:
|
|
24
|
+
getattr(sys.stdout, "reconfigure")(encoding="utf-8", errors="replace")
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
# ─── Timezone Configuration: Indian Standard Time (IST, UTC+05:30) ───────────
|
|
29
|
+
IST = datetime.timezone(datetime.timedelta(hours=5, minutes=30), name="IST")
|
|
30
|
+
|
|
31
|
+
def get_ist_now() -> datetime.datetime:
|
|
32
|
+
return datetime.datetime.now(IST)
|
|
33
|
+
|
|
34
|
+
# ─── ANSI Colors & Formatter ───────────────────────────────────────────────────
|
|
35
|
+
BOLD = "\033[1m"
|
|
36
|
+
DIM = "\033[2m"
|
|
37
|
+
RESET = "\033[0m"
|
|
38
|
+
CYAN = "\033[36m"
|
|
39
|
+
GREEN = "\033[32m"
|
|
40
|
+
YELLOW = "\033[33m"
|
|
41
|
+
WHITE = "\033[97m"
|
|
42
|
+
GRAY = "\033[90m"
|
|
43
|
+
RED = "\033[31m"
|
|
44
|
+
|
|
45
|
+
ANSI_REGEX = re.compile(r'\033\[[0-9;]*m')
|
|
46
|
+
|
|
47
|
+
def get_visual_width(text: str) -> int:
|
|
48
|
+
clean = ANSI_REGEX.sub('', text)
|
|
49
|
+
width = 0
|
|
50
|
+
for ch in clean:
|
|
51
|
+
ea = unicodedata.east_asian_width(ch)
|
|
52
|
+
if ea in ('W', 'F'):
|
|
53
|
+
width += 2
|
|
54
|
+
elif ord(ch) >= 0x1F300:
|
|
55
|
+
width += 2
|
|
56
|
+
else:
|
|
57
|
+
width += 1
|
|
58
|
+
return width
|
|
59
|
+
|
|
60
|
+
def format_box_line(content: str, width: int = 71, border: str = "│", border_color: str = CYAN) -> str:
|
|
61
|
+
vis = get_visual_width(content)
|
|
62
|
+
pad = " " * max(0, width - vis)
|
|
63
|
+
return f" {border_color}{border}{RESET} {content}{pad}{border_color}{border}{RESET}"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def find_latest_audit_run(runs_dir: Path) -> Optional[Path]:
|
|
67
|
+
if not runs_dir.is_dir():
|
|
68
|
+
return None
|
|
69
|
+
runs = sorted(runs_dir.glob("run-*-audit"), key=lambda p: p.stat().st_mtime, reverse=True)
|
|
70
|
+
return runs[0] if runs else None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def execute_recheck(target_root: Path, run_id_arg: Optional[str] = None) -> Dict[str, Any]:
|
|
74
|
+
runs_dir = target_root / ".torusguard" / "runs"
|
|
75
|
+
if run_id_arg:
|
|
76
|
+
run_folder = runs_dir / run_id_arg
|
|
77
|
+
else:
|
|
78
|
+
run_folder = find_latest_audit_run(runs_dir)
|
|
79
|
+
|
|
80
|
+
if not run_folder or not run_folder.is_dir():
|
|
81
|
+
print(f"\n {RED}✖ No audit run found to recheck.{RESET}\n")
|
|
82
|
+
sys.exit(1)
|
|
83
|
+
|
|
84
|
+
# Import audit scanner and memory engine
|
|
85
|
+
scripts_dir = Path(__file__).resolve().parent
|
|
86
|
+
if str(scripts_dir) not in sys.path:
|
|
87
|
+
sys.path.insert(0, str(scripts_dir))
|
|
88
|
+
import audit_runner
|
|
89
|
+
import memory_engine
|
|
90
|
+
|
|
91
|
+
bundles_dir = run_folder / "bundles"
|
|
92
|
+
bundle_meta_files = list(bundles_dir.glob("*/metadata.json")) if bundles_dir.is_dir() else []
|
|
93
|
+
|
|
94
|
+
# Header Card
|
|
95
|
+
print(f"\n {CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}")
|
|
96
|
+
print(f" {CYAN}│ │{RESET}")
|
|
97
|
+
print(format_box_line(f"{BOLD}🛡️ TORUSGUARD DIFFERENTIAL RECHECK ENGINE v1.3.0{RESET}", border_color=CYAN))
|
|
98
|
+
print(format_box_line(f"{DIM}Targeted Differential AST Scan & Regression Verification{RESET}", border_color=CYAN))
|
|
99
|
+
print(f" {CYAN}│ │{RESET}")
|
|
100
|
+
print(f" {CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}\n")
|
|
101
|
+
|
|
102
|
+
print(f" {CYAN}┌─ Recheck Verification Scope ────────────────────────────────────────────┐{RESET}")
|
|
103
|
+
print(format_box_line(f"Active Run: {WHITE}{run_folder.name}{RESET}"))
|
|
104
|
+
print(format_box_line(f"Target Root: {WHITE}{target_root}{RESET}"))
|
|
105
|
+
print(f" {CYAN}└─────────────────────────────────────────────────────────────────────────┘{RESET}\n")
|
|
106
|
+
|
|
107
|
+
recheck_results = []
|
|
108
|
+
confirmed_count = 0
|
|
109
|
+
regressed_count = 0
|
|
110
|
+
unresolved_count = 0
|
|
111
|
+
|
|
112
|
+
recheck_md_lines = [
|
|
113
|
+
f"# TorusGuard Differential Recheck Report",
|
|
114
|
+
f"**Run ID:** `{run_folder.name}` ",
|
|
115
|
+
f"**Timestamp:** `{get_ist_now().strftime('%Y-%m-%d %H:%M:%S IST')}` \n",
|
|
116
|
+
"---",
|
|
117
|
+
"## Recheck Transition Catalog\n"
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
for mf in bundle_meta_files:
|
|
121
|
+
try:
|
|
122
|
+
bdata = json.loads(mf.read_text(encoding="utf-8"))
|
|
123
|
+
except Exception:
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
rule_id = bdata.get("rule_id", "")
|
|
127
|
+
rel_path = bdata.get("target_file", "")
|
|
128
|
+
target_path = target_root / rel_path
|
|
129
|
+
|
|
130
|
+
if not target_path.is_file():
|
|
131
|
+
continue
|
|
132
|
+
|
|
133
|
+
# Differential scan on this single modified file
|
|
134
|
+
file_findings = audit_runner.scan_file(target_path, target_root)
|
|
135
|
+
matching_rule_findings = [f for f in file_findings if f.get("rule_id") == rule_id]
|
|
136
|
+
|
|
137
|
+
if not matching_rule_findings:
|
|
138
|
+
outcome = "Confirmed Fixed"
|
|
139
|
+
confirmed_count += 1
|
|
140
|
+
status_color = GREEN
|
|
141
|
+
# Record in memory
|
|
142
|
+
try:
|
|
143
|
+
memory_engine.record_event("fix_verified", {
|
|
144
|
+
"rule_id": rule_id,
|
|
145
|
+
"file_path": rel_path,
|
|
146
|
+
"verification_result": "fixed"
|
|
147
|
+
}, root_dir=target_root)
|
|
148
|
+
except Exception:
|
|
149
|
+
pass
|
|
150
|
+
else:
|
|
151
|
+
outcome = "Unresolved"
|
|
152
|
+
unresolved_count += 1
|
|
153
|
+
status_color = YELLOW
|
|
154
|
+
|
|
155
|
+
recheck_results.append({
|
|
156
|
+
"rule_id": rule_id,
|
|
157
|
+
"target_file": rel_path,
|
|
158
|
+
"outcome": outcome,
|
|
159
|
+
"title": bdata.get("title", rule_id)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
recheck_md_lines.append(f"### [{rule_id}] {bdata.get('title')}")
|
|
163
|
+
recheck_md_lines.append(f"- **File:** `{rel_path}`")
|
|
164
|
+
recheck_md_lines.append(f"- **Outcome:** `{outcome}`")
|
|
165
|
+
recheck_md_lines.append(f"- **Verification Timestamp:** {get_ist_now().strftime('%Y-%m-%d %H:%M:%S IST')}\n")
|
|
166
|
+
|
|
167
|
+
print(f" {status_color}✔ [{outcome}]{RESET} {WHITE}{rule_id}{RESET} on {rel_path}")
|
|
168
|
+
|
|
169
|
+
# Write recheck.md
|
|
170
|
+
(run_folder / "recheck.md").write_text("\n".join(recheck_md_lines), encoding="utf-8")
|
|
171
|
+
|
|
172
|
+
# Update manifest
|
|
173
|
+
manifest_file = run_folder / "manifest.json"
|
|
174
|
+
if manifest_file.is_file():
|
|
175
|
+
try:
|
|
176
|
+
mdata = json.loads(manifest_file.read_text(encoding="utf-8"))
|
|
177
|
+
mdata["status"] = "verified_fixed" if regressed_count == 0 and unresolved_count == 0 else "recheck_completed"
|
|
178
|
+
mdata["confirmed_fixed_count"] = confirmed_count
|
|
179
|
+
mdata["regressed_count"] = regressed_count
|
|
180
|
+
manifest_file.write_text(json.dumps(mdata, indent=2), encoding="utf-8")
|
|
181
|
+
except Exception:
|
|
182
|
+
pass
|
|
183
|
+
|
|
184
|
+
print()
|
|
185
|
+
print(f" {CYAN}┌─ Recheck Summary ───────────────────────────────────────────────────────┐{RESET}")
|
|
186
|
+
print(format_box_line(f"Confirmed Fixed:{GREEN}{confirmed_count} vulnerabilities verified closed{RESET}"))
|
|
187
|
+
print(format_box_line(f"Regressed: {RED if regressed_count > 0 else GREEN}{regressed_count} regressions detected{RESET}"))
|
|
188
|
+
print(format_box_line(f"Unresolved: {YELLOW if unresolved_count > 0 else GREEN}{unresolved_count} unresolved{RESET}"))
|
|
189
|
+
print(format_box_line(f"Memory Sync: {GREEN}Verification events synced to persistent memory engine{RESET}"))
|
|
190
|
+
print(f" {CYAN}└─────────────────────────────────────────────────────────────────────────┘{RESET}\n")
|
|
191
|
+
|
|
192
|
+
print(f" {GREEN}╔═ Next Governed Action ═════════════════════════════════════════════════════╗{RESET}")
|
|
193
|
+
print(format_box_line(f"Visual Dashboard: {BOLD}{WHITE}npx torusguard report --html{RESET} (Updated posture score)", border="║", border_color=GREEN))
|
|
194
|
+
print(format_box_line(f"View Recipes: {CYAN}npx torusguard recipes{RESET} (Active golden fix recipes)", border="║", border_color=GREEN))
|
|
195
|
+
print(f" {GREEN}╚═════════════════════════════════════════════════════════════════════════════╝{RESET}\n")
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
"run_folder": str(run_folder),
|
|
199
|
+
"confirmed_fixed_count": confirmed_count,
|
|
200
|
+
"regressed_count": regressed_count,
|
|
201
|
+
"unresolved_count": unresolved_count,
|
|
202
|
+
"results": recheck_results
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def main():
|
|
207
|
+
parser = argparse.ArgumentParser(description="TorusGuard Differential Recheck Engine")
|
|
208
|
+
parser.add_argument("path", nargs="?", default=".", help="Target project root directory")
|
|
209
|
+
parser.add_argument("--run", "-r", help="Explicit run ID to recheck")
|
|
210
|
+
parser.add_argument("--json", action="store_true", help="Output raw JSON")
|
|
211
|
+
args = parser.parse_args()
|
|
212
|
+
|
|
213
|
+
target = Path(args.path).resolve()
|
|
214
|
+
result = execute_recheck(target, run_id_arg=args.run)
|
|
215
|
+
|
|
216
|
+
if args.json:
|
|
217
|
+
print(json.dumps(result, indent=2))
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
main()
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TorusGuard Golden Fix Recipe Explorer (v1.3.0)
|
|
4
|
+
Inspect, list, and export reusable, verified AST remediation code snippets
|
|
5
|
+
distilled from passing security patches and persistent memory patterns.
|
|
6
|
+
|
|
7
|
+
Pure Python 3.10+ standard library (zero external dependencies).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
import json
|
|
12
|
+
import argparse
|
|
13
|
+
import unicodedata
|
|
14
|
+
import re
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Dict, List, Any, Optional
|
|
17
|
+
|
|
18
|
+
# Windows console UTF-8 support
|
|
19
|
+
if sys.stdout and hasattr(sys.stdout, "reconfigure"):
|
|
20
|
+
try:
|
|
21
|
+
getattr(sys.stdout, "reconfigure")(encoding="utf-8", errors="replace")
|
|
22
|
+
except Exception:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
# ─── ANSI Colors & Formatter ───────────────────────────────────────────────────
|
|
26
|
+
BOLD = "\033[1m"
|
|
27
|
+
DIM = "\033[2m"
|
|
28
|
+
RESET = "\033[0m"
|
|
29
|
+
CYAN = "\033[36m"
|
|
30
|
+
GREEN = "\033[32m"
|
|
31
|
+
YELLOW = "\033[33m"
|
|
32
|
+
WHITE = "\033[97m"
|
|
33
|
+
GRAY = "\033[90m"
|
|
34
|
+
RED = "\033[31m"
|
|
35
|
+
|
|
36
|
+
ANSI_REGEX = re.compile(r'\033\[[0-9;]*m')
|
|
37
|
+
|
|
38
|
+
def get_visual_width(text: str) -> int:
|
|
39
|
+
clean = ANSI_REGEX.sub('', text)
|
|
40
|
+
width = 0
|
|
41
|
+
for ch in clean:
|
|
42
|
+
ea = unicodedata.east_asian_width(ch)
|
|
43
|
+
if ea in ('W', 'F'):
|
|
44
|
+
width += 2
|
|
45
|
+
elif ord(ch) >= 0x1F300:
|
|
46
|
+
width += 2
|
|
47
|
+
else:
|
|
48
|
+
width += 1
|
|
49
|
+
return width
|
|
50
|
+
|
|
51
|
+
def format_box_line(content: str, width: int = 71, border: str = "│", border_color: str = CYAN) -> str:
|
|
52
|
+
vis = get_visual_width(content)
|
|
53
|
+
pad = " " * max(0, width - vis)
|
|
54
|
+
return f" {border_color}{border}{RESET} {content}{pad}{border_color}{border}{RESET}"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def list_recipes(target_root: Path, detail_id: Optional[str] = None, json_output: bool = False) -> None:
|
|
58
|
+
patterns_file = target_root / ".torusguard" / "memory" / "patterns.json"
|
|
59
|
+
recipes: List[Dict[str, Any]] = []
|
|
60
|
+
|
|
61
|
+
if patterns_file.is_file():
|
|
62
|
+
try:
|
|
63
|
+
patterns = json.loads(patterns_file.read_text(encoding="utf-8"))
|
|
64
|
+
recipes = [p for p in patterns if p.get("pattern_type") == "golden_fix_recipe"]
|
|
65
|
+
except Exception:
|
|
66
|
+
recipes = []
|
|
67
|
+
|
|
68
|
+
if json_output:
|
|
69
|
+
print(json.dumps(recipes, indent=2))
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
# Header Card
|
|
73
|
+
print(f"\n {CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}")
|
|
74
|
+
print(f" {CYAN}│ │{RESET}")
|
|
75
|
+
print(format_box_line(f"{BOLD}🛡️ TORUSGUARD GOLDEN FIX RECIPES v1.3.0{RESET}", border_color=CYAN))
|
|
76
|
+
print(format_box_line(f"{DIM}Distilled Ponytail Fixes (<= 35 add, <= 25 del) in Persistent Memory{RESET}", border_color=CYAN))
|
|
77
|
+
print(f" {CYAN}│ │{RESET}")
|
|
78
|
+
print(f" {CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}\n")
|
|
79
|
+
|
|
80
|
+
if not recipes:
|
|
81
|
+
print(f" {YELLOW}ℹ No golden fix recipes captured yet.{RESET}")
|
|
82
|
+
print(f" Run {CYAN}npx torusguard harden{RESET} followed by {CYAN}npx torusguard apply{RESET} to distill verified recipes.\n")
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
print(f" {CYAN}┌─ Active Distilled Recipes ({len(recipes)}) ─────────────────────────────────────┐{RESET}")
|
|
86
|
+
for idx, r in enumerate(recipes, 1):
|
|
87
|
+
rule_id = r.get("rule_id", "TG-SEC")
|
|
88
|
+
rec_id = r.get("recipe_id", f"recipe-{idx}")
|
|
89
|
+
desc = r.get("description", "Verified fix")
|
|
90
|
+
rdata = r.get("recipe_data", {})
|
|
91
|
+
metrics = rdata.get("ponytail_metrics", {})
|
|
92
|
+
verified = rdata.get("verified_count", 1)
|
|
93
|
+
adds = metrics.get("additions", 0)
|
|
94
|
+
dels = metrics.get("deletions", 0)
|
|
95
|
+
|
|
96
|
+
print(format_box_line(f"{GREEN}[{rule_id}]{RESET} {WHITE}{rec_id}{RESET} (Verified {verified}x · +{adds}/-{dels} Ponytail)"))
|
|
97
|
+
print(format_box_line(f" └─ {DIM}{desc}{RESET}"))
|
|
98
|
+
print(f" {CYAN}└─────────────────────────────────────────────────────────────────────────┘{RESET}\n")
|
|
99
|
+
|
|
100
|
+
if detail_id:
|
|
101
|
+
target_rec = next((r for r in recipes if r.get("recipe_id") == detail_id), None)
|
|
102
|
+
if target_rec:
|
|
103
|
+
rdata = target_rec.get("recipe_data", {})
|
|
104
|
+
print(f" {BOLD}Recipe Details: {detail_id}{RESET}")
|
|
105
|
+
print(f" {DIM}Rule ID:{RESET} {target_rec.get('rule_id')}")
|
|
106
|
+
print(f" {DIM}Diff Snippet:{RESET}")
|
|
107
|
+
print(" ```diff")
|
|
108
|
+
for line in rdata.get("diff_snippet", "").splitlines():
|
|
109
|
+
if line.startswith("+"):
|
|
110
|
+
print(f" {GREEN}{line}{RESET}")
|
|
111
|
+
elif line.startswith("-"):
|
|
112
|
+
print(f" {RED}{line}{RESET}")
|
|
113
|
+
else:
|
|
114
|
+
print(f" {DIM}{line}{RESET}")
|
|
115
|
+
print(" ```\n")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def main():
|
|
119
|
+
parser = argparse.ArgumentParser(description="TorusGuard Golden Fix Recipe Explorer")
|
|
120
|
+
parser.add_argument("path", nargs="?", default=".", help="Target project root directory")
|
|
121
|
+
parser.add_argument("--detail", "-d", help="Inspect specific recipe ID")
|
|
122
|
+
parser.add_argument("--json", action="store_true", help="Output raw JSON")
|
|
123
|
+
args = parser.parse_args()
|
|
124
|
+
|
|
125
|
+
target = Path(args.path).resolve()
|
|
126
|
+
list_recipes(target, detail_id=args.detail, json_output=args.json)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if __name__ == "__main__":
|
|
130
|
+
main()
|