vibecheck-ai 2.0.1 → 5.0.0
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/bin/.generated +25 -0
- package/bin/_deprecations.js +463 -0
- package/bin/_router.js +46 -0
- package/bin/cli-hygiene.js +241 -0
- package/bin/dev/run-v2-torture.js +30 -0
- package/bin/registry.js +656 -0
- package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
- package/bin/runners/REPORT_AUDIT.md +64 -0
- package/bin/runners/cli-utils.js +1070 -0
- package/bin/runners/context/ai-task-decomposer.js +337 -0
- package/bin/runners/context/analyzer.js +513 -0
- package/bin/runners/context/api-contracts.js +427 -0
- package/bin/runners/context/context-diff.js +342 -0
- package/bin/runners/context/context-pruner.js +291 -0
- package/bin/runners/context/dependency-graph.js +414 -0
- package/bin/runners/context/generators/claude.js +107 -0
- package/bin/runners/context/generators/codex.js +108 -0
- package/bin/runners/context/generators/copilot.js +119 -0
- package/bin/runners/context/generators/cursor-enhanced.js +2525 -0
- package/bin/runners/context/generators/cursor.js +514 -0
- package/bin/runners/context/generators/mcp.js +169 -0
- package/bin/runners/context/generators/windsurf.js +180 -0
- package/bin/runners/context/git-context.js +304 -0
- package/bin/runners/context/index.js +1110 -0
- package/bin/runners/context/insights.js +173 -0
- package/bin/runners/context/mcp-server/generate-rules.js +337 -0
- package/bin/runners/context/mcp-server/index.js +1176 -0
- package/bin/runners/context/mcp-server/package.json +24 -0
- package/bin/runners/context/memory.js +200 -0
- package/bin/runners/context/monorepo.js +215 -0
- package/bin/runners/context/multi-repo-federation.js +404 -0
- package/bin/runners/context/patterns.js +253 -0
- package/bin/runners/context/proof-context.js +1264 -0
- package/bin/runners/context/security-scanner.js +541 -0
- package/bin/runners/context/semantic-search.js +350 -0
- package/bin/runners/context/shared.js +264 -0
- package/bin/runners/context/team-conventions.js +336 -0
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
- package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
- package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
- package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
- package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
- package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
- package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
- package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
- package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
- package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
- package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
- package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
- package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
- package/bin/runners/lib/agent-firewall/index.js +200 -0
- package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
- package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
- package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
- package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
- package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
- package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
- package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
- package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
- package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
- package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -0
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
- package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
- package/bin/runners/lib/agent-firewall/logger.js +141 -0
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
- package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +79 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -0
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
- package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
- package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
- package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
- package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
- package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
- package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
- package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
- package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
- package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
- package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
- package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
- package/bin/runners/lib/agent-firewall/session/index.js +26 -0
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
- package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
- package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
- package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
- package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/ai-bridge.js +416 -0
- package/bin/runners/lib/analysis-core.js +309 -0
- package/bin/runners/lib/analyzers.js +2500 -0
- package/bin/runners/lib/api-client.js +269 -0
- package/bin/runners/lib/approve-output.js +235 -0
- package/bin/runners/lib/artifact-envelope.js +540 -0
- package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
- package/bin/runners/lib/audit-bridge.js +391 -0
- package/bin/runners/lib/auth-shared.js +977 -0
- package/bin/runners/lib/auth-truth.js +193 -0
- package/bin/runners/lib/auth.js +215 -0
- package/bin/runners/lib/authority-badge.js +425 -0
- package/bin/runners/lib/backup.js +62 -0
- package/bin/runners/lib/billing.js +107 -0
- package/bin/runners/lib/checkpoint.js +941 -0
- package/bin/runners/lib/claims.js +118 -0
- package/bin/runners/lib/classify-output.js +204 -0
- package/bin/runners/lib/cleanup/engine.js +571 -0
- package/bin/runners/lib/cleanup/index.js +53 -0
- package/bin/runners/lib/cleanup/output.js +375 -0
- package/bin/runners/lib/cleanup/rules.js +1060 -0
- package/bin/runners/lib/cli-output.js +400 -0
- package/bin/runners/lib/cli-ui.js +540 -0
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +165 -0
- package/bin/runners/lib/contracts/auth-contract.js +202 -0
- package/bin/runners/lib/contracts/env-contract.js +181 -0
- package/bin/runners/lib/contracts/external-contract.js +206 -0
- package/bin/runners/lib/contracts/guard.js +168 -0
- package/bin/runners/lib/contracts/index.js +89 -0
- package/bin/runners/lib/contracts/plan-validator.js +311 -0
- package/bin/runners/lib/contracts/route-contract.js +199 -0
- package/bin/runners/lib/contracts.js +804 -0
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/detect.js +89 -0
- package/bin/runners/lib/detectors-v2.js +622 -0
- package/bin/runners/lib/doctor/autofix.js +254 -0
- package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
- package/bin/runners/lib/doctor/failure-signatures.js +526 -0
- package/bin/runners/lib/doctor/fix-script.js +336 -0
- package/bin/runners/lib/doctor/index.js +37 -0
- package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
- package/bin/runners/lib/doctor/modules/index.js +105 -0
- package/bin/runners/lib/doctor/modules/network.js +250 -0
- package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
- package/bin/runners/lib/doctor/modules/project.js +312 -0
- package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
- package/bin/runners/lib/doctor/modules/runtime.js +224 -0
- package/bin/runners/lib/doctor/modules/security.js +350 -0
- package/bin/runners/lib/doctor/modules/system.js +213 -0
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
- package/bin/runners/lib/doctor/reporter.js +262 -0
- package/bin/runners/lib/doctor/safe-repair.js +384 -0
- package/bin/runners/lib/doctor/service.js +262 -0
- package/bin/runners/lib/doctor/types.js +113 -0
- package/bin/runners/lib/doctor/ui.js +263 -0
- package/bin/runners/lib/doctor-enhanced.js +233 -0
- package/bin/runners/lib/doctor-output.js +226 -0
- package/bin/runners/lib/doctor-v2.js +608 -0
- package/bin/runners/lib/drift.js +425 -0
- package/bin/runners/lib/enforcement.js +72 -0
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/attack-detector.js +1192 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -0
- package/bin/runners/lib/enterprise-init.js +942 -0
- package/bin/runners/lib/entitlements-v2.js +265 -0
- package/bin/runners/lib/entitlements.generated.js +0 -0
- package/bin/runners/lib/entitlements.js +340 -0
- package/bin/runners/lib/env-resolver.js +417 -0
- package/bin/runners/lib/env-template.js +66 -0
- package/bin/runners/lib/env.js +189 -0
- package/bin/runners/lib/error-handler.js +368 -0
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +684 -0
- package/bin/runners/lib/exit-codes.js +275 -0
- package/bin/runners/lib/extractors/client-calls.js +990 -0
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
- package/bin/runners/lib/extractors/fastify-routes.js +426 -0
- package/bin/runners/lib/extractors/index.js +363 -0
- package/bin/runners/lib/extractors/next-routes.js +524 -0
- package/bin/runners/lib/extractors/proof-graph.js +431 -0
- package/bin/runners/lib/extractors/route-matcher.js +451 -0
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
- package/bin/runners/lib/extractors/ui-bindings.js +547 -0
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/findings-schema.js +281 -0
- package/bin/runners/lib/fingerprint.js +377 -0
- package/bin/runners/lib/firewall-prompt.js +50 -0
- package/bin/runners/lib/fix-output.js +228 -0
- package/bin/runners/lib/global-flags.js +250 -0
- package/bin/runners/lib/graph/graph-builder.js +265 -0
- package/bin/runners/lib/graph/html-renderer.js +413 -0
- package/bin/runners/lib/graph/index.js +32 -0
- package/bin/runners/lib/graph/runtime-collector.js +215 -0
- package/bin/runners/lib/graph/static-extractor.js +518 -0
- package/bin/runners/lib/help-formatter.js +413 -0
- package/bin/runners/lib/html-proof-report.js +913 -0
- package/bin/runners/lib/html-report.js +650 -0
- package/bin/runners/lib/init-wizard.js +601 -0
- package/bin/runners/lib/interactive-menu.js +1496 -0
- package/bin/runners/lib/json-output.js +76 -0
- package/bin/runners/lib/llm.js +75 -0
- package/bin/runners/lib/logger.js +38 -0
- package/bin/runners/lib/meter.js +61 -0
- package/bin/runners/lib/missions/briefing.js +427 -0
- package/bin/runners/lib/missions/checkpoint.js +753 -0
- package/bin/runners/lib/missions/evidence.js +126 -0
- package/bin/runners/lib/missions/hardening.js +851 -0
- package/bin/runners/lib/missions/plan.js +648 -0
- package/bin/runners/lib/missions/safety-gates.js +645 -0
- package/bin/runners/lib/missions/schema.js +478 -0
- package/bin/runners/lib/missions/templates.js +317 -0
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/packs/bundle.js +675 -0
- package/bin/runners/lib/packs/evidence-pack.js +671 -0
- package/bin/runners/lib/packs/pack-factory.js +837 -0
- package/bin/runners/lib/packs/permissions-pack.js +686 -0
- package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
- package/bin/runners/lib/patch.js +40 -0
- package/bin/runners/lib/permissions/auth-model.js +213 -0
- package/bin/runners/lib/permissions/idor-prover.js +205 -0
- package/bin/runners/lib/permissions/index.js +45 -0
- package/bin/runners/lib/permissions/matrix-builder.js +198 -0
- package/bin/runners/lib/pkgjson.js +28 -0
- package/bin/runners/lib/policy.js +295 -0
- package/bin/runners/lib/polish/accessibility.js +62 -0
- package/bin/runners/lib/polish/analyzer.js +93 -0
- package/bin/runners/lib/polish/backend.js +87 -0
- package/bin/runners/lib/polish/configuration.js +83 -0
- package/bin/runners/lib/polish/documentation.js +83 -0
- package/bin/runners/lib/polish/frontend.js +817 -0
- package/bin/runners/lib/polish/index.js +27 -0
- package/bin/runners/lib/polish/infrastructure.js +80 -0
- package/bin/runners/lib/polish/internationalization.js +85 -0
- package/bin/runners/lib/polish/libraries.js +180 -0
- package/bin/runners/lib/polish/observability.js +75 -0
- package/bin/runners/lib/polish/performance.js +64 -0
- package/bin/runners/lib/polish/privacy.js +110 -0
- package/bin/runners/lib/polish/resilience.js +92 -0
- package/bin/runners/lib/polish/security.js +78 -0
- package/bin/runners/lib/polish/seo.js +71 -0
- package/bin/runners/lib/polish/styles.js +62 -0
- package/bin/runners/lib/polish/utils.js +104 -0
- package/bin/runners/lib/preflight.js +142 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/prove-output.js +220 -0
- package/bin/runners/lib/reality/correlation-detectors.js +359 -0
- package/bin/runners/lib/reality/index.js +318 -0
- package/bin/runners/lib/reality/request-hashing.js +416 -0
- package/bin/runners/lib/reality/request-mapper.js +453 -0
- package/bin/runners/lib/reality/safety-rails.js +463 -0
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
- package/bin/runners/lib/reality/toast-detector.js +393 -0
- package/bin/runners/lib/reality-findings.js +84 -0
- package/bin/runners/lib/reality-output.js +231 -0
- package/bin/runners/lib/receipts.js +179 -0
- package/bin/runners/lib/redact.js +29 -0
- package/bin/runners/lib/replay/capsule-manager.js +154 -0
- package/bin/runners/lib/replay/index.js +263 -0
- package/bin/runners/lib/replay/player.js +348 -0
- package/bin/runners/lib/replay/recorder.js +331 -0
- package/bin/runners/lib/report-engine.js +626 -0
- package/bin/runners/lib/report-html.js +1233 -0
- package/bin/runners/lib/report-output.js +366 -0
- package/bin/runners/lib/report-templates.js +967 -0
- package/bin/runners/lib/report.js +135 -0
- package/bin/runners/lib/route-detection.js +1209 -0
- package/bin/runners/lib/route-truth.js +1322 -0
- package/bin/runners/lib/safelist/index.js +96 -0
- package/bin/runners/lib/safelist/integration.js +334 -0
- package/bin/runners/lib/safelist/matcher.js +696 -0
- package/bin/runners/lib/safelist/schema.js +948 -0
- package/bin/runners/lib/safelist/store.js +438 -0
- package/bin/runners/lib/sandbox/index.js +59 -0
- package/bin/runners/lib/sandbox/proof-chain.js +399 -0
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
- package/bin/runners/lib/sandbox/worktree.js +174 -0
- package/bin/runners/lib/scan-cache.js +330 -0
- package/bin/runners/lib/scan-output-schema.js +344 -0
- package/bin/runners/lib/scan-output.js +631 -0
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schema-validator.js +350 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/contracts.schema.json +160 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/finding.schema.json +100 -0
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
- package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
- package/bin/runners/lib/schemas/validator.js +465 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/score-history.js +282 -0
- package/bin/runners/lib/security-bridge.js +249 -0
- package/bin/runners/lib/server-usage.js +513 -0
- package/bin/runners/lib/share-pack.js +239 -0
- package/bin/runners/lib/ship-gate.js +832 -0
- package/bin/runners/lib/ship-manifest.js +1153 -0
- package/bin/runners/lib/ship-output-enterprise.js +239 -0
- package/bin/runners/lib/ship-output.js +1128 -0
- package/bin/runners/lib/snippets.js +67 -0
- package/bin/runners/lib/status-output.js +340 -0
- package/bin/runners/lib/terminal-ui.js +356 -0
- package/bin/runners/lib/truth.js +1691 -0
- package/bin/runners/lib/ui.js +562 -0
- package/bin/runners/lib/unified-cli-output.js +947 -0
- package/bin/runners/lib/unified-output.js +197 -0
- package/bin/runners/lib/upsell.js +410 -0
- package/bin/runners/lib/usage.js +153 -0
- package/bin/runners/lib/validate-patch.js +156 -0
- package/bin/runners/lib/verdict-engine.js +628 -0
- package/bin/runners/lib/verification.js +345 -0
- package/bin/runners/lib/why-tree.js +650 -0
- package/bin/runners/reality/engine.js +917 -0
- package/bin/runners/reality/flows.js +122 -0
- package/bin/runners/reality/report.js +378 -0
- package/bin/runners/reality/session.js +193 -0
- package/bin/runners/runAIAgent.js +229 -0
- package/bin/runners/runAgent.d.ts +5 -0
- package/bin/runners/runAgent.js +161 -0
- package/bin/runners/runAllowlist.js +418 -0
- package/bin/runners/runApprove.js +320 -0
- package/bin/runners/runAudit.js +692 -0
- package/bin/runners/runAuth.js +731 -0
- package/bin/runners/runCI.js +353 -0
- package/bin/runners/runCheckpoint.js +530 -0
- package/bin/runners/runClassify.js +928 -0
- package/bin/runners/runCleanup.js +343 -0
- package/bin/runners/runContext.d.ts +4 -0
- package/bin/runners/runContext.js +175 -0
- package/bin/runners/runDoctor.js +877 -0
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewall.js +134 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runFirewallHook.js +56 -0
- package/bin/runners/runFix.js +1355 -0
- package/bin/runners/runForge.js +451 -0
- package/bin/runners/runGuard.js +262 -0
- package/bin/runners/runInit.js +1927 -0
- package/bin/runners/runIntent.js +906 -0
- package/bin/runners/runKickoff.js +878 -0
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runLaunch.js +2000 -0
- package/bin/runners/runLink.js +785 -0
- package/bin/runners/runMcp.js +1875 -0
- package/bin/runners/runPacks.js +2089 -0
- package/bin/runners/runPolish.d.ts +4 -0
- package/bin/runners/runPolish.js +390 -0
- package/bin/runners/runPromptFirewall.js +211 -0
- package/bin/runners/runProve.js +1411 -0
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +2260 -0
- package/bin/runners/runReport.js +726 -0
- package/bin/runners/runRuntime.js +110 -0
- package/bin/runners/runSafelist.js +1190 -0
- package/bin/runners/runScan.js +688 -0
- package/bin/runners/runShield.js +1282 -0
- package/bin/runners/runShip.js +1660 -0
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/runners/runTruth.js +101 -0
- package/bin/runners/runValidate.js +179 -0
- package/bin/runners/runWatch.js +478 -0
- package/bin/runners/utils.js +360 -0
- package/bin/scan.js +617 -0
- package/bin/vibecheck.js +1617 -0
- package/dist/guardrail/index.d.ts +2405 -0
- package/dist/guardrail/index.js +9747 -0
- package/dist/guardrail/index.js.map +1 -0
- package/dist/scanner/index.d.ts +282 -0
- package/dist/scanner/index.js +3395 -0
- package/dist/scanner/index.js.map +1 -0
- package/package.json +123 -104
- package/README.md +0 -491
- package/dist/index.js +0 -99711
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Scanner Module
|
|
3
|
+
* Scans context for secrets, vulnerabilities, and sensitive data
|
|
4
|
+
* Enhanced with entropy checking and better false positive prevention
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const crypto = require("crypto");
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calculate Shannon entropy of a string
|
|
13
|
+
* Higher entropy = more random = more likely to be a real secret
|
|
14
|
+
*/
|
|
15
|
+
function calculateEntropy(str) {
|
|
16
|
+
if (!str || str.length === 0) return 0;
|
|
17
|
+
|
|
18
|
+
const freq = {};
|
|
19
|
+
for (const char of str) {
|
|
20
|
+
freq[char] = (freq[char] || 0) + 1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let entropy = 0;
|
|
24
|
+
const len = str.length;
|
|
25
|
+
for (const count of Object.values(freq)) {
|
|
26
|
+
const p = count / len;
|
|
27
|
+
entropy -= p * Math.log2(p);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return entropy;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if a value is a known false positive
|
|
35
|
+
*/
|
|
36
|
+
function isFalsePositive(value, line, filePath) {
|
|
37
|
+
const lowerValue = value.toLowerCase();
|
|
38
|
+
const lowerLine = line.toLowerCase();
|
|
39
|
+
const lowerPath = filePath.toLowerCase();
|
|
40
|
+
|
|
41
|
+
// Common placeholder/test values
|
|
42
|
+
const falsePositiveValues = [
|
|
43
|
+
'example', 'test', 'sample', 'demo', 'placeholder', 'mock', 'fake', 'dummy',
|
|
44
|
+
'your_key', 'your_secret', 'your_token', 'changeme', 'replace_me', 'xxx',
|
|
45
|
+
'password', 'password123', 'secret', 'admin', '12345', 'qwerty'
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
for (const fp of falsePositiveValues) {
|
|
49
|
+
if (lowerValue.includes(fp)) return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Repeating characters (low entropy)
|
|
53
|
+
if (/^(.)\1{5,}$/.test(value)) return true;
|
|
54
|
+
|
|
55
|
+
// Sequential characters
|
|
56
|
+
if (/^(012|123|234|345|456|567|678|789|abc|bcd|cde)/i.test(value)) return true;
|
|
57
|
+
|
|
58
|
+
// Test/example context
|
|
59
|
+
if (lowerLine.includes('example') || lowerLine.includes('// test')) return true;
|
|
60
|
+
if (lowerPath.includes('.test.') || lowerPath.includes('.spec.')) return true;
|
|
61
|
+
if (lowerPath.includes('__tests__') || lowerPath.includes('__mocks__')) return true;
|
|
62
|
+
if (lowerPath.includes('/fixtures/') || lowerPath.includes('/examples/')) return true;
|
|
63
|
+
|
|
64
|
+
// Documentation context
|
|
65
|
+
if (lowerPath.endsWith('.md') || lowerPath.includes('/docs/')) return true;
|
|
66
|
+
|
|
67
|
+
// Env template files
|
|
68
|
+
if (lowerPath.includes('.env.example') || lowerPath.includes('.env.template')) return true;
|
|
69
|
+
if (lowerPath.includes('.env.sample')) return true;
|
|
70
|
+
|
|
71
|
+
// Type definitions
|
|
72
|
+
if (lowerLine.includes('type ') || lowerLine.includes('interface ')) return true;
|
|
73
|
+
|
|
74
|
+
// Import statements
|
|
75
|
+
if (lowerLine.startsWith('import ') || lowerLine.includes('require(')) return true;
|
|
76
|
+
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Secret patterns to detect
|
|
82
|
+
* Each pattern now includes minEntropy for generic patterns
|
|
83
|
+
*/
|
|
84
|
+
const SECRET_PATTERNS = [
|
|
85
|
+
// API Keys - specific formats (high confidence, no entropy check needed)
|
|
86
|
+
{ pattern: /AIza[0-9A-Za-z_-]{35}/, type: "Google API Key", minEntropy: 3.5 },
|
|
87
|
+
{ pattern: /AKIA[0-9A-Z]{16}/, type: "AWS Access Key", minEntropy: 3.5 },
|
|
88
|
+
{ pattern: /xoxb-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24}/, type: "Slack Bot Token", minEntropy: 0 },
|
|
89
|
+
{ pattern: /ghp_[a-zA-Z0-9]{36}/, type: "GitHub Personal Token", minEntropy: 3.5 },
|
|
90
|
+
{ pattern: /gho_[a-zA-Z0-9]{36}/, type: "GitHub OAuth Token", minEntropy: 3.5 },
|
|
91
|
+
{ pattern: /sk_live_[0-9a-zA-Z]{24,}/, type: "Stripe Live Key", minEntropy: 3.5 },
|
|
92
|
+
{ pattern: /pk_live_[0-9a-zA-Z]{24,}/, type: "Stripe Publishable Key", minEntropy: 0 },
|
|
93
|
+
|
|
94
|
+
// Generic patterns - require higher entropy to avoid false positives
|
|
95
|
+
{ pattern: /['"]?api[_-]?key['"]?\s*[:=]\s*['"]([^'"]{16,})['"]/, type: "API Key", minEntropy: 4.0, valueGroup: 1 },
|
|
96
|
+
{ pattern: /['"]?secret[_-]?key['"]?\s*[:=]\s*['"]([^'"]{16,})['"]/, type: "Secret Key", minEntropy: 4.0, valueGroup: 1 },
|
|
97
|
+
{ pattern: /['"]?password['"]?\s*[:=]\s*['"]([^'"]{8,})['"]/, type: "Password", minEntropy: 3.0, valueGroup: 1 },
|
|
98
|
+
{ pattern: /['"]?auth[_-]?token['"]?\s*[:=]\s*['"]([^'"]{16,})['"]/, type: "Auth Token", minEntropy: 4.0, valueGroup: 1 },
|
|
99
|
+
{ pattern: /['"]?private[_-]?key['"]?\s*[:=]\s*['"]([^'"]{20,})['"]/, type: "Private Key", minEntropy: 4.0, valueGroup: 1 },
|
|
100
|
+
|
|
101
|
+
// Database URLs (credentials embedded)
|
|
102
|
+
{ pattern: /mongodb(?:\+srv)?:\/\/([^:]+):([^@]+)@/, type: "MongoDB URL", minEntropy: 0 },
|
|
103
|
+
{ pattern: /postgres(?:ql)?:\/\/([^:]+):([^@]+)@/, type: "PostgreSQL URL", minEntropy: 0 },
|
|
104
|
+
{ pattern: /mysql:\/\/([^:]+):([^@]+)@/, type: "MySQL URL", minEntropy: 0 },
|
|
105
|
+
{ pattern: /redis:\/\/([^:]+):([^@]+)@/, type: "Redis URL", minEntropy: 0 },
|
|
106
|
+
|
|
107
|
+
// JWT tokens - validate structure
|
|
108
|
+
{ pattern: /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, type: "JWT Token", minEntropy: 4.0 },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Vulnerability patterns - refined to reduce false positives
|
|
113
|
+
* Each pattern now includes contextual requirements
|
|
114
|
+
*/
|
|
115
|
+
const VULNERABILITY_PATTERNS = [
|
|
116
|
+
// SQL Injection - require concatenation with user input indicators
|
|
117
|
+
{
|
|
118
|
+
pattern: /(?:query|execute|raw)\s*\(\s*['"`](?:SELECT|INSERT|UPDATE|DELETE|DROP)\s*[^'"]*\+\s*(?:req\.|user|input|param)/i,
|
|
119
|
+
type: "SQL Injection",
|
|
120
|
+
severity: "critical",
|
|
121
|
+
contextExclusions: ['parameterized', 'prepared', 'placeholder']
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
// XSS - dangerouslySetInnerHTML only when value comes from user/external
|
|
125
|
+
{
|
|
126
|
+
pattern: /dangerouslySetInnerHTML\s*=\s*{{\s*__html:\s*(?:props|data|user|input|param)/,
|
|
127
|
+
type: "XSS Risk",
|
|
128
|
+
severity: "high",
|
|
129
|
+
contextExclusions: ['sanitize', 'DOMPurify', 'escape']
|
|
130
|
+
},
|
|
131
|
+
// innerHTML with dynamic content
|
|
132
|
+
{
|
|
133
|
+
pattern: /\.innerHTML\s*=\s*(?:[^'";\n]*\+|`[^`]*\$\{)/,
|
|
134
|
+
type: "XSS Risk",
|
|
135
|
+
severity: "high",
|
|
136
|
+
contextExclusions: ['sanitize', 'escape', 'encode']
|
|
137
|
+
},
|
|
138
|
+
// document.write with variables
|
|
139
|
+
{
|
|
140
|
+
pattern: /document\.write\s*\([^)]*(?:\+|\$\{)/,
|
|
141
|
+
type: "XSS Risk",
|
|
142
|
+
severity: "high"
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
// Path Traversal - only flag when path comes from user input
|
|
146
|
+
{
|
|
147
|
+
pattern: /(?:readFile|readdir|open|access)\s*\([^)]*(?:req\.|user|input|param)[^)]*\)/,
|
|
148
|
+
type: "Path Traversal",
|
|
149
|
+
severity: "high",
|
|
150
|
+
contextExclusions: ['path.join', 'path.resolve', 'normalize', 'sanitize']
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
// Insecure Crypto - only for password/credential hashing, not checksums
|
|
154
|
+
{
|
|
155
|
+
pattern: /(?:createHash|crypto)\s*\(\s*['"](?:md5|sha1)['"]\s*\)[^;]*(?:password|credential|secret)/i,
|
|
156
|
+
type: "Weak Password Hash",
|
|
157
|
+
severity: "high",
|
|
158
|
+
contextExclusions: ['checksum', 'fingerprint', 'etag', 'cache']
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
// Hardcoded credentials - more specific patterns
|
|
162
|
+
{
|
|
163
|
+
pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}['"]\s*(?:,|;|$)/,
|
|
164
|
+
type: "Hardcoded Credentials",
|
|
165
|
+
severity: "high",
|
|
166
|
+
contextExclusions: ['process.env', 'config.', 'example', 'test', 'placeholder']
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
// Sensitive data in logs - only when logging actual variables
|
|
170
|
+
{
|
|
171
|
+
pattern: /console\.(?:log|info|debug)\s*\([^)]*(?:password|secret|token|apiKey|auth)[^)]*\)/,
|
|
172
|
+
type: "Sensitive Data in Log",
|
|
173
|
+
severity: "high",
|
|
174
|
+
contextExclusions: ['masked', 'redacted', '***', '[REDACTED]']
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// Eval with dynamic content
|
|
178
|
+
{
|
|
179
|
+
pattern: /\beval\s*\([^)]*(?:\+|`\$\{|concat)/,
|
|
180
|
+
type: "Code Injection",
|
|
181
|
+
severity: "critical"
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
// Insecure random for security purposes
|
|
185
|
+
{
|
|
186
|
+
pattern: /Math\.random\s*\(\s*\)[^;]*(?:token|secret|key|password|salt|nonce)/i,
|
|
187
|
+
type: "Insecure Random",
|
|
188
|
+
severity: "high"
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Find files recursively
|
|
194
|
+
*/
|
|
195
|
+
function findFiles(dir, extensions, maxDepth = 5, currentDepth = 0) {
|
|
196
|
+
if (currentDepth >= maxDepth || !fs.existsSync(dir)) return [];
|
|
197
|
+
|
|
198
|
+
const files = [];
|
|
199
|
+
try {
|
|
200
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
201
|
+
for (const entry of entries) {
|
|
202
|
+
const fullPath = path.join(dir, entry.name);
|
|
203
|
+
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
204
|
+
files.push(...findFiles(fullPath, extensions, maxDepth, currentDepth + 1));
|
|
205
|
+
} else if (entry.isFile() && extensions.some(ext => entry.name.endsWith(ext))) {
|
|
206
|
+
files.push(fullPath);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} catch {}
|
|
210
|
+
return files;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Scan file for secrets with entropy checking and false positive filtering
|
|
215
|
+
*/
|
|
216
|
+
function scanForSecrets(content, filePath) {
|
|
217
|
+
const secrets = [];
|
|
218
|
+
const lines = content.split("\n");
|
|
219
|
+
const relativePath = path.relative(process.cwd(), filePath).replace(/\\/g, "/");
|
|
220
|
+
|
|
221
|
+
// Skip known safe file types
|
|
222
|
+
if (/\.(md|txt|svg|png|jpg|gif|ico|woff|woff2|ttf|eot|map)$/i.test(filePath)) {
|
|
223
|
+
return secrets;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const patternDef of SECRET_PATTERNS) {
|
|
227
|
+
const regex = new RegExp(patternDef.pattern.source, 'gi');
|
|
228
|
+
let match;
|
|
229
|
+
|
|
230
|
+
while ((match = regex.exec(content)) !== null) {
|
|
231
|
+
const lineNum = content.substring(0, match.index).split("\n").length;
|
|
232
|
+
const line = lines[lineNum - 1] || '';
|
|
233
|
+
|
|
234
|
+
// Extract the actual secret value (use valueGroup if specified)
|
|
235
|
+
const secretValue = patternDef.valueGroup !== undefined
|
|
236
|
+
? (match[patternDef.valueGroup] || match[0])
|
|
237
|
+
: match[0];
|
|
238
|
+
|
|
239
|
+
// Check for false positives first
|
|
240
|
+
if (isFalsePositive(secretValue, line, filePath)) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Check entropy if required
|
|
245
|
+
if (patternDef.minEntropy && patternDef.minEntropy > 0) {
|
|
246
|
+
const entropy = calculateEntropy(secretValue);
|
|
247
|
+
if (entropy < patternDef.minEntropy) {
|
|
248
|
+
continue; // Too low entropy, likely not a real secret
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Additional validation for specific types
|
|
253
|
+
if (patternDef.type === "JWT Token") {
|
|
254
|
+
// Validate JWT structure
|
|
255
|
+
const parts = secretValue.split('.');
|
|
256
|
+
if (parts.length !== 3) continue;
|
|
257
|
+
// Check if header looks valid (should be base64 JSON starting with eyJ)
|
|
258
|
+
try {
|
|
259
|
+
const header = Buffer.from(parts[0], 'base64url').toString();
|
|
260
|
+
if (!header.includes('{') || !header.includes('alg')) continue;
|
|
261
|
+
} catch {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
secrets.push({
|
|
267
|
+
type: patternDef.type,
|
|
268
|
+
file: relativePath,
|
|
269
|
+
line: lineNum,
|
|
270
|
+
content: maskSensitiveLine(line.trim()),
|
|
271
|
+
severity: getSeverity(patternDef.type),
|
|
272
|
+
entropy: calculateEntropy(secretValue).toFixed(2),
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return secrets;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Mask sensitive values in the line for safe display
|
|
282
|
+
*/
|
|
283
|
+
function maskSensitiveLine(line) {
|
|
284
|
+
// Mask potential secret values (keep first 4 and last 4 chars if long enough)
|
|
285
|
+
return line.replace(/(['"])[A-Za-z0-9_\-/+=]{12,}(['"])/g, (match, q1, q2) => {
|
|
286
|
+
const inner = match.slice(1, -1);
|
|
287
|
+
if (inner.length > 12) {
|
|
288
|
+
return `${q1}${inner.slice(0, 4)}****${inner.slice(-4)}${q2}`;
|
|
289
|
+
}
|
|
290
|
+
return `${q1}****${q2}`;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Get severity based on secret type
|
|
296
|
+
*/
|
|
297
|
+
function getSeverity(type) {
|
|
298
|
+
const criticalTypes = [
|
|
299
|
+
"AWS Access Key", "Stripe Live Key", "GitHub Personal Token",
|
|
300
|
+
"GitHub OAuth Token", "Private Key", "Secret Key"
|
|
301
|
+
];
|
|
302
|
+
const highTypes = [
|
|
303
|
+
"Google API Key", "Slack Bot Token", "MongoDB URL",
|
|
304
|
+
"PostgreSQL URL", "MySQL URL", "Redis URL", "Password", "Auth Token"
|
|
305
|
+
];
|
|
306
|
+
|
|
307
|
+
if (criticalTypes.includes(type)) return "critical";
|
|
308
|
+
if (highTypes.includes(type)) return "high";
|
|
309
|
+
return "medium";
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Scan file for vulnerabilities with context-aware filtering
|
|
314
|
+
*/
|
|
315
|
+
function scanForVulnerabilities(content, filePath) {
|
|
316
|
+
const vulnerabilities = [];
|
|
317
|
+
const lines = content.split("\n");
|
|
318
|
+
const relativePath = path.relative(process.cwd(), filePath).replace(/\\/g, "/");
|
|
319
|
+
const lowerPath = relativePath.toLowerCase();
|
|
320
|
+
|
|
321
|
+
// Skip test files for vulnerability scanning (tests often contain intentional "bad" patterns)
|
|
322
|
+
if (lowerPath.includes('.test.') || lowerPath.includes('.spec.') ||
|
|
323
|
+
lowerPath.includes('__tests__') || lowerPath.includes('__mocks__')) {
|
|
324
|
+
return vulnerabilities;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Skip documentation and examples
|
|
328
|
+
if (lowerPath.endsWith('.md') || lowerPath.includes('/docs/') ||
|
|
329
|
+
lowerPath.includes('/examples/')) {
|
|
330
|
+
return vulnerabilities;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
for (const patternDef of VULNERABILITY_PATTERNS) {
|
|
334
|
+
const regex = new RegExp(patternDef.pattern.source, 'gi');
|
|
335
|
+
let match;
|
|
336
|
+
|
|
337
|
+
while ((match = regex.exec(content)) !== null) {
|
|
338
|
+
const lineNum = content.substring(0, match.index).split("\n").length;
|
|
339
|
+
const line = lines[lineNum - 1] || '';
|
|
340
|
+
const lowerLine = line.toLowerCase();
|
|
341
|
+
|
|
342
|
+
// Check context exclusions - skip if any exclusion pattern is present
|
|
343
|
+
if (patternDef.contextExclusions) {
|
|
344
|
+
const excluded = patternDef.contextExclusions.some(exclusion =>
|
|
345
|
+
lowerLine.includes(exclusion.toLowerCase())
|
|
346
|
+
);
|
|
347
|
+
if (excluded) continue;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Skip if the line is a comment
|
|
351
|
+
const trimmedLine = line.trim();
|
|
352
|
+
if (trimmedLine.startsWith('//') || trimmedLine.startsWith('/*') ||
|
|
353
|
+
trimmedLine.startsWith('*') || trimmedLine.startsWith('#')) {
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Skip if in a multi-line comment context
|
|
358
|
+
const beforeMatch = content.substring(0, match.index);
|
|
359
|
+
const lastCommentStart = beforeMatch.lastIndexOf('/*');
|
|
360
|
+
const lastCommentEnd = beforeMatch.lastIndexOf('*/');
|
|
361
|
+
if (lastCommentStart > lastCommentEnd) {
|
|
362
|
+
continue; // We're inside a multi-line comment
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
vulnerabilities.push({
|
|
366
|
+
type: patternDef.type,
|
|
367
|
+
file: relativePath,
|
|
368
|
+
line: lineNum,
|
|
369
|
+
content: trimmedLine.substring(0, 100), // Limit line length
|
|
370
|
+
severity: patternDef.severity || "medium",
|
|
371
|
+
recommendation: getRecommendation(patternDef.type),
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return vulnerabilities;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Get recommendation for vulnerability type
|
|
381
|
+
*/
|
|
382
|
+
function getRecommendation(type) {
|
|
383
|
+
const recommendations = {
|
|
384
|
+
"SQL Injection": "Use parameterized queries or prepared statements. Never concatenate user input into SQL.",
|
|
385
|
+
"XSS Risk": "Sanitize user input with DOMPurify or similar. Use textContent instead of innerHTML when possible.",
|
|
386
|
+
"Path Traversal": "Validate and sanitize file paths. Use path.join() and verify paths don't escape the base directory.",
|
|
387
|
+
"Weak Password Hash": "Use bcrypt, Argon2, or scrypt for password hashing. MD5/SHA1 are cryptographically broken.",
|
|
388
|
+
"Hardcoded Credentials": "Use environment variables or a secrets manager. Never commit credentials to version control.",
|
|
389
|
+
"Sensitive Data in Log": "Remove or mask sensitive data before logging. Use structured logging with redaction.",
|
|
390
|
+
"Code Injection": "Never use eval() with user input. Consider safer alternatives like JSON.parse() or a sandboxed environment.",
|
|
391
|
+
"Insecure Random": "Use crypto.randomBytes() or crypto.randomUUID() for security-sensitive random values.",
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
return recommendations[type] || "Review and fix the security issue";
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Scan project for security issues
|
|
399
|
+
*/
|
|
400
|
+
function scanProject(projectPath) {
|
|
401
|
+
const files = findFiles(projectPath, [".ts", ".tsx", ".js", ".jsx", ".json", ".env*", ".yml", ".yaml"], 5);
|
|
402
|
+
|
|
403
|
+
const results = {
|
|
404
|
+
secrets: [],
|
|
405
|
+
vulnerabilities: [],
|
|
406
|
+
stats: {
|
|
407
|
+
totalFiles: files.length,
|
|
408
|
+
filesWithSecrets: 0,
|
|
409
|
+
filesWithVulnerabilities: 0,
|
|
410
|
+
criticalIssues: 0,
|
|
411
|
+
highIssues: 0,
|
|
412
|
+
mediumIssues: 0,
|
|
413
|
+
},
|
|
414
|
+
scanned: new Date().toISOString(),
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
for (const file of files) {
|
|
418
|
+
try {
|
|
419
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
420
|
+
const relativePath = path.relative(projectPath, file).replace(/\\/g, "/");
|
|
421
|
+
|
|
422
|
+
// Skip certain files
|
|
423
|
+
if (relativePath.includes("node_modules") ||
|
|
424
|
+
relativePath.includes(".git") ||
|
|
425
|
+
relativePath.includes("dist/") ||
|
|
426
|
+
relativePath.includes("build/")) {
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const secrets = scanForSecrets(content, file);
|
|
431
|
+
const vulnerabilities = scanForVulnerabilities(content, file);
|
|
432
|
+
|
|
433
|
+
if (secrets.length > 0) {
|
|
434
|
+
results.secrets.push(...secrets);
|
|
435
|
+
results.stats.filesWithSecrets++;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (vulnerabilities.length > 0) {
|
|
439
|
+
results.vulnerabilities.push(...vulnerabilities);
|
|
440
|
+
results.stats.filesWithVulnerabilities++;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Count severity
|
|
444
|
+
for (const issue of [...secrets, ...vulnerabilities]) {
|
|
445
|
+
switch (issue.severity) {
|
|
446
|
+
case "critical":
|
|
447
|
+
results.stats.criticalIssues++;
|
|
448
|
+
break;
|
|
449
|
+
case "high":
|
|
450
|
+
results.stats.highIssues++;
|
|
451
|
+
break;
|
|
452
|
+
case "medium":
|
|
453
|
+
results.stats.mediumIssues++;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
} catch {}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return results;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Generate security report
|
|
465
|
+
*/
|
|
466
|
+
function generateSecurityReport(results) {
|
|
467
|
+
let report = `# Security Scan Report\n\n`;
|
|
468
|
+
report += `Scanned: ${new Date(results.scanned).toLocaleString()}\n`;
|
|
469
|
+
report += `Total Files: ${results.stats.totalFiles}\n\n`;
|
|
470
|
+
|
|
471
|
+
// Summary
|
|
472
|
+
report += `## Summary\n\n`;
|
|
473
|
+
report += `- Files with Secrets: ${results.stats.filesWithSecrets}\n`;
|
|
474
|
+
report += `- Files with Vulnerabilities: ${results.stats.filesWithVulnerabilities}\n`;
|
|
475
|
+
report += `- Critical Issues: ${results.stats.criticalIssues}\n`;
|
|
476
|
+
report += `- High Issues: ${results.stats.highIssues}\n`;
|
|
477
|
+
report += `- Medium Issues: ${results.stats.mediumIssues}\n\n`;
|
|
478
|
+
|
|
479
|
+
// Secrets
|
|
480
|
+
if (results.secrets.length > 0) {
|
|
481
|
+
report += `## 🔑 Secrets Found (${results.secrets.length})\n\n`;
|
|
482
|
+
for (const secret of results.secrets) {
|
|
483
|
+
report += `### ${secret.type} - ${secret.file}:${secret.line}\n`;
|
|
484
|
+
report += `\`\`\`\n${secret.content}\n\`\`\`\n\n`;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Vulnerabilities
|
|
489
|
+
if (results.vulnerabilities.length > 0) {
|
|
490
|
+
report += `## 🚨 Vulnerabilities Found (${results.vulnerabilities.length})\n\n`;
|
|
491
|
+
for (const vuln of results.vulnerabilities) {
|
|
492
|
+
const icon = vuln.severity === "critical" ? "🔴" :
|
|
493
|
+
vuln.severity === "high" ? "🟠" : "🟡";
|
|
494
|
+
report += `### ${icon} ${vuln.type} - ${vuln.file}:${vuln.line}\n`;
|
|
495
|
+
report += `**Severity:** ${vuln.severity}\n`;
|
|
496
|
+
report += `**Recommendation:** ${vuln.recommendation}\n\n`;
|
|
497
|
+
report += `\`\`\`\n${vuln.content}\n\`\`\`\n\n`;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (results.secrets.length === 0 && results.vulnerabilities.length === 0) {
|
|
502
|
+
report += `## ✅ No Security Issues Found\n\n`;
|
|
503
|
+
report += `Great job! No secrets or obvious vulnerabilities were detected.\n`;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
return report;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Filter content for safe AI consumption
|
|
511
|
+
*/
|
|
512
|
+
function filterForAI(content) {
|
|
513
|
+
let filtered = content;
|
|
514
|
+
|
|
515
|
+
// Remove detected secrets
|
|
516
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
517
|
+
filtered = filtered.replace(pattern.pattern, "[REDACTED_SECRET]");
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Remove sensitive lines
|
|
521
|
+
const lines = filtered.split("\n");
|
|
522
|
+
const safeLines = lines.filter(line => {
|
|
523
|
+
const lower = line.toLowerCase();
|
|
524
|
+
return !lower.includes("password") &&
|
|
525
|
+
!lower.includes("secret") &&
|
|
526
|
+
!lower.includes("private_key") &&
|
|
527
|
+
!lower.includes("api_key") &&
|
|
528
|
+
!line.includes("console.log") &&
|
|
529
|
+
!line.includes("debugger");
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
return safeLines.join("\n");
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
module.exports = {
|
|
536
|
+
scanProject,
|
|
537
|
+
generateSecurityReport,
|
|
538
|
+
filterForAI,
|
|
539
|
+
SECRET_PATTERNS,
|
|
540
|
+
VULNERABILITY_PATTERNS,
|
|
541
|
+
};
|