@clear-capabilities/agentic-security-scanner 0.74.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/CHANGELOG.md +1580 -0
- package/bin/.agentic-security/findings.json +1577 -0
- package/bin/.agentic-security/last-scan.json +1577 -0
- package/bin/.agentic-security/last-scan.json.sig +1 -0
- package/bin/.agentic-security/scan-history.json +465 -0
- package/bin/.agentic-security/streak.json +25 -0
- package/bin/agentic-security-audit.js +198 -0
- package/bin/agentic-security-consistency.js +80 -0
- package/bin/agentic-security-diff.js +136 -0
- package/bin/agentic-security-lsp.js +12 -0
- package/bin/agentic-security-mcp.js +40 -0
- package/bin/agentic-security-rule.js +153 -0
- package/bin/agentic-security.js +1683 -0
- package/dist/117.index.js +207 -0
- package/dist/178.index.js +250 -0
- package/dist/218.index.js +793 -0
- package/dist/227.index.js +192 -0
- package/dist/301.index.js +167 -0
- package/dist/384.index.js +18 -0
- package/dist/476.index.js +126 -0
- package/dist/513.index.js +373 -0
- package/dist/520.index.js +13 -0
- package/dist/601.index.js +1038 -0
- package/dist/634.index.js +1892 -0
- package/dist/637.index.js +216 -0
- package/dist/660.index.js +131 -0
- package/dist/675.index.js +451 -0
- package/dist/826.index.js +188 -0
- package/dist/830.index.js +133 -0
- package/dist/agentic-security.mjs +272 -0
- package/dist/agentic-security.mjs.sha256 +1 -0
- package/dist/calibration-seed.json +27 -0
- package/package.json +77 -0
- package/src/.agentic-security/findings.json +80844 -0
- package/src/.agentic-security/last-scan.json +80844 -0
- package/src/.agentic-security/last-scan.json.sig +1 -0
- package/src/.agentic-security/scan-history.json +8408 -0
- package/src/.agentic-security/streak.json +26 -0
- package/src/badge.js +188 -0
- package/src/compare.js +203 -0
- package/src/dataflow/.agentic-security/findings.json +3487 -0
- package/src/dataflow/.agentic-security/last-scan.json +3487 -0
- package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
- package/src/dataflow/.agentic-security/scan-history.json +735 -0
- package/src/dataflow/.agentic-security/streak.json +24 -0
- package/src/dataflow/CLAUDE.md +38 -0
- package/src/dataflow/access-paths.js +172 -0
- package/src/dataflow/async-sequencing.js +177 -0
- package/src/dataflow/backward.js +201 -0
- package/src/dataflow/catalog-expanded.js +485 -0
- package/src/dataflow/catalog.js +659 -0
- package/src/dataflow/cross-repo.js +219 -0
- package/src/dataflow/engine.js +588 -0
- package/src/dataflow/exception-flow.js +116 -0
- package/src/dataflow/exploit-prover.js +187 -0
- package/src/dataflow/higher-order.js +221 -0
- package/src/dataflow/ifds.js +347 -0
- package/src/dataflow/implicit-flow.js +129 -0
- package/src/dataflow/incremental.js +229 -0
- package/src/dataflow/index.js +181 -0
- package/src/dataflow/numeric-domain.js +192 -0
- package/src/dataflow/path-feasibility.js +114 -0
- package/src/dataflow/points-to.js +337 -0
- package/src/dataflow/polyglot.js +190 -0
- package/src/dataflow/proven-clean.js +159 -0
- package/src/dataflow/receiver-context.js +76 -0
- package/src/dataflow/sanitizer-proof.js +154 -0
- package/src/dataflow/soft-taint.js +140 -0
- package/src/dataflow/string-domain.js +234 -0
- package/src/dataflow/stub-aware-filter.js +100 -0
- package/src/dataflow/summaries.js +132 -0
- package/src/dataflow/symbolic-exec.js +238 -0
- package/src/dataflow/tabulation.js +135 -0
- package/src/engine.js +7763 -0
- package/src/history-scan.js +229 -0
- package/src/index.js +3 -0
- package/src/integrations/.agentic-security/findings.json +1504 -0
- package/src/integrations/.agentic-security/last-scan.json +1504 -0
- package/src/integrations/.agentic-security/scan-history.json +40 -0
- package/src/integrations/.agentic-security/streak.json +21 -0
- package/src/integrations/index.js +321 -0
- package/src/integrations/tickets.js +200 -0
- package/src/ir/.agentic-security/findings.json +3036 -0
- package/src/ir/.agentic-security/last-scan.json +3036 -0
- package/src/ir/.agentic-security/last-scan.json.sig +1 -0
- package/src/ir/.agentic-security/scan-history.json +364 -0
- package/src/ir/.agentic-security/streak.json +23 -0
- package/src/ir/CLAUDE.md +172 -0
- package/src/ir/callgraph.js +73 -0
- package/src/ir/class-hierarchy.js +195 -0
- package/src/ir/index.js +152 -0
- package/src/ir/parser-cs.js +260 -0
- package/src/ir/parser-java.js +286 -0
- package/src/ir/parser-js.js +413 -0
- package/src/ir/parser-kt.js +258 -0
- package/src/ir/parser-py-cst.js +136 -0
- package/src/ir/parser-py.helper.py +501 -0
- package/src/ir/parser-py.js +312 -0
- package/src/ir/ssa.js +315 -0
- package/src/ir/type-stubs.js +288 -0
- package/src/leaderboard.js +152 -0
- package/src/llm-validator/.agentic-security/findings.json +1891 -0
- package/src/llm-validator/.agentic-security/last-scan.json +1891 -0
- package/src/llm-validator/.agentic-security/last-scan.json.sig +1 -0
- package/src/llm-validator/.agentic-security/scan-history.json +168 -0
- package/src/llm-validator/.agentic-security/streak.json +20 -0
- package/src/llm-validator/consistency.js +141 -0
- package/src/llm-validator/index.js +437 -0
- package/src/lsp/.agentic-security/findings.json +28 -0
- package/src/lsp/.agentic-security/last-scan.json +28 -0
- package/src/lsp/.agentic-security/scan-history.json +79 -0
- package/src/lsp/.agentic-security/streak.json +22 -0
- package/src/lsp/server.js +275 -0
- package/src/mcp/.agentic-security/findings.json +8358 -0
- package/src/mcp/.agentic-security/last-scan.json +8358 -0
- package/src/mcp/.agentic-security/last-scan.json.sig +1 -0
- package/src/mcp/.agentic-security/scan-history.json +1125 -0
- package/src/mcp/.agentic-security/streak.json +22 -0
- package/src/mcp/CLAUDE.md +54 -0
- package/src/mcp/audit.js +136 -0
- package/src/mcp/redact.js +75 -0
- package/src/mcp/server.js +158 -0
- package/src/mcp/stdio.js +83 -0
- package/src/mcp/tools.js +940 -0
- package/src/mcp/validate.js +49 -0
- package/src/personality.js +164 -0
- package/src/poc-video.js +239 -0
- package/src/posture/.agentic-security/findings.json +51239 -0
- package/src/posture/.agentic-security/last-scan.json +51239 -0
- package/src/posture/.agentic-security/last-scan.json.sig +1 -0
- package/src/posture/.agentic-security/scan-history.json +5557 -0
- package/src/posture/.agentic-security/streak.json +24 -0
- package/src/posture/CLAUDE.md +42 -0
- package/src/posture/adversarial-self-test.js +114 -0
- package/src/posture/adversary-agent.js +204 -0
- package/src/posture/agents-memory.js +135 -0
- package/src/posture/ai-code-fingerprint.js +171 -0
- package/src/posture/aibom.js +284 -0
- package/src/posture/api-inventory.js +96 -0
- package/src/posture/attack-playbooks.js +305 -0
- package/src/posture/auditor-agent.js +115 -0
- package/src/posture/auth-posture-import.js +135 -0
- package/src/posture/baseline-compare.js +114 -0
- package/src/posture/blast-radius.js +836 -0
- package/src/posture/bounty-prediction.js +141 -0
- package/src/posture/business-logic.js +239 -0
- package/src/posture/calibration-drift.js +93 -0
- package/src/posture/calibration-seed.json +27 -0
- package/src/posture/calibration.js +204 -0
- package/src/posture/clustering.js +75 -0
- package/src/posture/concurrency-checker.js +265 -0
- package/src/posture/confidence.js +65 -0
- package/src/posture/container-runtime.js +149 -0
- package/src/posture/counterfactual.js +109 -0
- package/src/posture/cross-lang-graphql.js +165 -0
- package/src/posture/cross-lang-grpc.js +166 -0
- package/src/posture/cross-lang-meta.js +101 -0
- package/src/posture/cross-lang-openapi.js +187 -0
- package/src/posture/cross-lang-orm.js +153 -0
- package/src/posture/cross-lang-queues.js +210 -0
- package/src/posture/crown-jewels.js +110 -0
- package/src/posture/custom-rules.js +361 -0
- package/src/posture/cve-alert-daemon.js +433 -0
- package/src/posture/cve-lookup.js +129 -0
- package/src/posture/dead-code.js +430 -0
- package/src/posture/defender-agent.js +158 -0
- package/src/posture/deploy-platform.js +204 -0
- package/src/posture/detector-fuzz.js +61 -0
- package/src/posture/deterministic.js +99 -0
- package/src/posture/drift.js +165 -0
- package/src/posture/epss.js +156 -0
- package/src/posture/exploitability-probability.js +212 -0
- package/src/posture/exploitability.js +121 -0
- package/src/posture/feature-flags.js +110 -0
- package/src/posture/finding-defaults.js +132 -0
- package/src/posture/fix-history.js +411 -0
- package/src/posture/fix-plan.js +121 -0
- package/src/posture/fix-verify-loop.js +157 -0
- package/src/posture/fix-verify.js +130 -0
- package/src/posture/flow-narration.js +105 -0
- package/src/posture/grader-calibration.js +156 -0
- package/src/posture/harness-discovery.js +113 -0
- package/src/posture/holdout-eval.js +144 -0
- package/src/posture/iac-reachability.js +163 -0
- package/src/posture/iam-policy.js +128 -0
- package/src/posture/integrity.js +97 -0
- package/src/posture/learning.js +166 -0
- package/src/posture/license-policy.js +109 -0
- package/src/posture/llm-redteam-prompts.js +418 -0
- package/src/posture/llm-redteam.js +303 -0
- package/src/posture/material-change.js +163 -0
- package/src/posture/mitigation-composite.js +55 -0
- package/src/posture/mttr.js +91 -0
- package/src/posture/network-policy-import.js +126 -0
- package/src/posture/path-predicates.js +99 -0
- package/src/posture/persona-prioritization.js +153 -0
- package/src/posture/poc-cwe-map.js +51 -0
- package/src/posture/poc-generator.js +500 -0
- package/src/posture/policy-gate.js +174 -0
- package/src/posture/pre-incident-archaeology.js +110 -0
- package/src/posture/profile.js +93 -0
- package/src/posture/reachability-filter.js +42 -0
- package/src/posture/regression-test-gen.js +200 -0
- package/src/posture/reverse-blast-radius.js +110 -0
- package/src/posture/router.js +109 -0
- package/src/posture/rule-overrides.js +198 -0
- package/src/posture/rule-pack-signing.js +209 -0
- package/src/posture/rule-packs.js +143 -0
- package/src/posture/rule-synthesis.js +108 -0
- package/src/posture/ruleset-version.js +71 -0
- package/src/posture/sbom.js +129 -0
- package/src/posture/schema-aware-bridge.js +207 -0
- package/src/posture/security-trend.js +87 -0
- package/src/posture/semantic-clone.js +114 -0
- package/src/posture/specification-mining.js +170 -0
- package/src/posture/stable-id.js +75 -0
- package/src/posture/stack-playbook.js +229 -0
- package/src/posture/streak.js +249 -0
- package/src/posture/suppressions.js +135 -0
- package/src/posture/telemetry-ingest.js +112 -0
- package/src/posture/threat-model.js +145 -0
- package/src/posture/three-agent-pipeline.js +74 -0
- package/src/posture/triage.js +146 -0
- package/src/posture/trust-boundary-diagram.js +115 -0
- package/src/posture/type-narrowing.js +129 -0
- package/src/posture/validator-metrics.js +179 -0
- package/src/posture/verifier-ephemeral.js +118 -0
- package/src/posture/verifier-target.js +147 -0
- package/src/posture/verifier.js +257 -0
- package/src/posture/version.js +75 -0
- package/src/posture/waf-ingest.js +200 -0
- package/src/posture/why-fired.js +141 -0
- package/src/pr-comment.js +172 -0
- package/src/pr-delta.js +198 -0
- package/src/report/.agentic-security/findings.json +79 -0
- package/src/report/.agentic-security/last-scan.json +79 -0
- package/src/report/.agentic-security/last-scan.json.sig +1 -0
- package/src/report/.agentic-security/scan-history.json +332 -0
- package/src/report/.agentic-security/streak.json +23 -0
- package/src/report/index.js +1136 -0
- package/src/report/mascot.js +42 -0
- package/src/runScan.js +141 -0
- package/src/sast/.agentic-security/findings.json +5051 -0
- package/src/sast/.agentic-security/last-scan.json +5051 -0
- package/src/sast/.agentic-security/last-scan.json.sig +1 -0
- package/src/sast/.agentic-security/scan-history.json +788 -0
- package/src/sast/.agentic-security/streak.json +23 -0
- package/src/sast/CLAUDE.md +39 -0
- package/src/sast/_comment-strip.js +46 -0
- package/src/sast/agent-tool-escalation.js +131 -0
- package/src/sast/auth-provider.js +171 -0
- package/src/sast/authz.js +236 -0
- package/src/sast/bench-shape/.agentic-security/findings.json +28 -0
- package/src/sast/bench-shape/.agentic-security/last-scan.json +28 -0
- package/src/sast/bench-shape/.agentic-security/scan-history.json +24 -0
- package/src/sast/bench-shape/.agentic-security/streak.json +22 -0
- package/src/sast/bench-shape/index.js +62 -0
- package/src/sast/claude-hook-injection.js +199 -0
- package/src/sast/claude-md-prompt-injection.js +170 -0
- package/src/sast/claude-settings.js +165 -0
- package/src/sast/client-side.js +149 -0
- package/src/sast/cpp-bench-extras.js +122 -0
- package/src/sast/cpp-dataflow.js +430 -0
- package/src/sast/cpp.js +248 -0
- package/src/sast/csharp.js +152 -0
- package/src/sast/csrf.js +82 -0
- package/src/sast/dart-flutter.js +173 -0
- package/src/sast/db-rls.js +147 -0
- package/src/sast/db-taint.js +215 -0
- package/src/sast/defi-deep.js +242 -0
- package/src/sast/deserialization-gadgets.js +113 -0
- package/src/sast/django-hardening.js +230 -0
- package/src/sast/env-hygiene.js +125 -0
- package/src/sast/fastapi-hardening.js +145 -0
- package/src/sast/go-extended.js +84 -0
- package/src/sast/host-header.js +106 -0
- package/src/sast/index.js +17 -0
- package/src/sast/java-ast-folding.js +561 -0
- package/src/sast/java-bench-extras.js +708 -0
- package/src/sast/java-collection-passthrough.js +178 -0
- package/src/sast/java-constant-fold.js +244 -0
- package/src/sast/java-deserialization.js +125 -0
- package/src/sast/jndi.js +104 -0
- package/src/sast/juliet-shape.js +324 -0
- package/src/sast/jwt-exp.js +104 -0
- package/src/sast/kotlin.js +82 -0
- package/src/sast/laravel-hardening.js +198 -0
- package/src/sast/ldap-injection.js +100 -0
- package/src/sast/llm-owasp.js +465 -0
- package/src/sast/llm-stored-prompt.js +103 -0
- package/src/sast/llm-trading-agent.js +161 -0
- package/src/sast/llm.js +308 -0
- package/src/sast/logic.js +140 -0
- package/src/sast/mass-assignment.js +101 -0
- package/src/sast/mcp-audit.js +242 -0
- package/src/sast/mobile-manifest.js +195 -0
- package/src/sast/model-load.js +164 -0
- package/src/sast/mutation-xss.js +87 -0
- package/src/sast/nosql-injection.js +82 -0
- package/src/sast/open-redirect.js +119 -0
- package/src/sast/php.js +91 -0
- package/src/sast/pipeline.js +122 -0
- package/src/sast/primary-cwe-java.js +155 -0
- package/src/sast/prompt-firewall.js +151 -0
- package/src/sast/prompt-template.js +157 -0
- package/src/sast/prototype-pollution.js +112 -0
- package/src/sast/python-sinks.js +195 -0
- package/src/sast/quarkus-hardening.js +102 -0
- package/src/sast/rag-poisoning.js +118 -0
- package/src/sast/rate-limit.js +128 -0
- package/src/sast/response-splitting.js +138 -0
- package/src/sast/ruby.js +108 -0
- package/src/sast/rust.js +105 -0
- package/src/sast/solidity.js +167 -0
- package/src/sast/springboot-hardening.js +186 -0
- package/src/sast/ssrf-cloud-metadata.js +80 -0
- package/src/sast/ssti.js +116 -0
- package/src/sast/swift.js +162 -0
- package/src/sast/toctou.js +95 -0
- package/src/sast/webhook.js +101 -0
- package/src/sast/xpath-injection.js +51 -0
- package/src/sast/xxe.js +140 -0
- package/src/sast/zip-slip.js +200 -0
- package/src/sca/base-images.json +45 -0
- package/src/sca/container.js +107 -0
- package/src/sca/dep-confusion.js +134 -0
- package/src/sca/index.js +6 -0
- package/src/sca/popular-packages.json +41 -0
- package/src/sca/sarif-ingest.js +187 -0
- package/src/sca/vuln-function-hints.json +89 -0
- package/src/secrets/index.js +4 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
export const id = 117;
|
|
2
|
+
export const ids = [117];
|
|
3
|
+
export const modules = {
|
|
4
|
+
|
|
5
|
+
/***/ 3117:
|
|
6
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
7
|
+
|
|
8
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9
|
+
/* harmony export */ iI: () => (/* binding */ summarizeForBadge),
|
|
10
|
+
/* harmony export */ renderBadge: () => (/* binding */ renderBadge)
|
|
11
|
+
/* harmony export */ });
|
|
12
|
+
/* unused harmony exports badgeFromScanRoot, renderSvg, _internal */
|
|
13
|
+
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3024);
|
|
14
|
+
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6760);
|
|
15
|
+
// Live SVG badge generator (v0.72).
|
|
16
|
+
//
|
|
17
|
+
// Every repo can drop a badge in its README pulling from the latest scan:
|
|
18
|
+
//
|
|
19
|
+
// 
|
|
20
|
+
//
|
|
21
|
+
// or self-hosted via the CLI subcommand emitting an inline <img> URL or
|
|
22
|
+
// a static SVG. The badge format borrows from shields.io for visual
|
|
23
|
+
// consistency. Reads from .agentic-security/last-scan.json or accepts a
|
|
24
|
+
// scan object directly.
|
|
25
|
+
//
|
|
26
|
+
// Output formats:
|
|
27
|
+
// - 'svg' — inline SVG string (default; the bytes you'd serve)
|
|
28
|
+
// - 'json' — { label, count, color, severity } for a frontend renderer
|
|
29
|
+
//
|
|
30
|
+
// Style variants:
|
|
31
|
+
// - 'flat' — shields.io flat
|
|
32
|
+
// - 'for-the-badge' — caps + thicker
|
|
33
|
+
//
|
|
34
|
+
// Color is driven by the highest non-zero severity:
|
|
35
|
+
// critical → red
|
|
36
|
+
// high → orange
|
|
37
|
+
// medium → yellow
|
|
38
|
+
// low → blue
|
|
39
|
+
// info → lightgrey
|
|
40
|
+
// none → brightgreen
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const COLORS = {
|
|
46
|
+
critical: '#e05d44', // red
|
|
47
|
+
high: '#fe7d37', // orange
|
|
48
|
+
medium: '#dfb317', // yellow
|
|
49
|
+
low: '#007ec6', // blue
|
|
50
|
+
info: '#9f9f9f', // grey
|
|
51
|
+
none: '#4c1', // brightgreen
|
|
52
|
+
label: '#555',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const SEVERITIES = ['critical', 'high', 'medium', 'low', 'info'];
|
|
56
|
+
|
|
57
|
+
function _readLastScan(scanRoot) {
|
|
58
|
+
if (!scanRoot) return null;
|
|
59
|
+
const fp = node_path__WEBPACK_IMPORTED_MODULE_1__.join(scanRoot, '.agentic-security', 'last-scan.json');
|
|
60
|
+
if (!node_fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(fp)) return null;
|
|
61
|
+
try { return JSON.parse(node_fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(fp, 'utf8')); }
|
|
62
|
+
catch { return null; }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function _ageString(ts) {
|
|
66
|
+
if (!ts) return null;
|
|
67
|
+
const ageMs = Date.now() - new Date(ts).getTime();
|
|
68
|
+
if (isNaN(ageMs) || ageMs < 0) return null;
|
|
69
|
+
const min = Math.floor(ageMs / 60_000);
|
|
70
|
+
if (min < 60) return `${min}m ago`;
|
|
71
|
+
const hr = Math.floor(min / 60);
|
|
72
|
+
if (hr < 24) return `${hr}h ago`;
|
|
73
|
+
const day = Math.floor(hr / 24);
|
|
74
|
+
return `${day}d ago`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Compute the badge value from a scan object.
|
|
79
|
+
*
|
|
80
|
+
* Returns:
|
|
81
|
+
* {
|
|
82
|
+
* label: 'agentic-security',
|
|
83
|
+
* summary: 'critical 0 · high 2 · medium 5' | 'passing' | 'no scan',
|
|
84
|
+
* color: '#fe7d37',
|
|
85
|
+
* highest: 'high' | 'none' | 'unknown',
|
|
86
|
+
* ageStr: '4h ago' | null,
|
|
87
|
+
* counts: { critical, high, medium, low, info },
|
|
88
|
+
* total: 7,
|
|
89
|
+
* }
|
|
90
|
+
*/
|
|
91
|
+
function summarizeForBadge(scan) {
|
|
92
|
+
if (!scan || !Array.isArray(scan.findings)) {
|
|
93
|
+
return {
|
|
94
|
+
label: 'agentic-security',
|
|
95
|
+
summary: 'no scan',
|
|
96
|
+
color: COLORS.info,
|
|
97
|
+
highest: 'unknown',
|
|
98
|
+
ageStr: null,
|
|
99
|
+
counts: { critical: 0, high: 0, medium: 0, low: 0, info: 0 },
|
|
100
|
+
total: 0,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const counts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
|
|
104
|
+
for (const f of scan.findings) {
|
|
105
|
+
const s = f.severity || 'info';
|
|
106
|
+
if (counts[s] !== undefined) counts[s]++;
|
|
107
|
+
}
|
|
108
|
+
let highest = 'none';
|
|
109
|
+
for (const s of SEVERITIES) { if (counts[s] > 0) { highest = s; break; } }
|
|
110
|
+
const color = COLORS[highest] || COLORS.info;
|
|
111
|
+
const summary = highest === 'none'
|
|
112
|
+
? 'passing'
|
|
113
|
+
: `crit ${counts.critical} · high ${counts.high} · med ${counts.medium}`;
|
|
114
|
+
const total = SEVERITIES.reduce((a, s) => a + counts[s], 0);
|
|
115
|
+
return {
|
|
116
|
+
label: 'agentic-security',
|
|
117
|
+
summary,
|
|
118
|
+
color,
|
|
119
|
+
highest,
|
|
120
|
+
ageStr: _ageString(scan.timestamp || scan.when || scan.lastScan),
|
|
121
|
+
counts,
|
|
122
|
+
total,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Compute the badge from .agentic-security/last-scan.json under `scanRoot`.
|
|
128
|
+
*/
|
|
129
|
+
function badgeFromScanRoot(scanRoot) {
|
|
130
|
+
return summarizeForBadge(_readLastScan(scanRoot));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function _xmlEscape(s) {
|
|
134
|
+
return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function _textWidth(s) {
|
|
138
|
+
// Rough character width — works fine for the small badge label range.
|
|
139
|
+
return s.length * 7 + 10;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Render an inline SVG matching shields.io's flat style. Self-contained
|
|
144
|
+
* (no external font references) so the badge works in any README.
|
|
145
|
+
*/
|
|
146
|
+
function renderSvg(b, opts = {}) {
|
|
147
|
+
if (!b) b = summarizeForBadge(null);
|
|
148
|
+
const style = opts.style || 'flat';
|
|
149
|
+
const labelText = b.label;
|
|
150
|
+
const valueText = b.ageStr ? `${b.summary} · ${b.ageStr}` : b.summary;
|
|
151
|
+
const lblW = _textWidth(labelText);
|
|
152
|
+
const valW = _textWidth(valueText);
|
|
153
|
+
const totalW = lblW + valW;
|
|
154
|
+
const h = style === 'for-the-badge' ? 28 : 20;
|
|
155
|
+
const fontSize = style === 'for-the-badge' ? 12 : 11;
|
|
156
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalW}" height="${h}" role="img" aria-label="${_xmlEscape(labelText)}: ${_xmlEscape(valueText)}">
|
|
157
|
+
<title>${_xmlEscape(labelText)}: ${_xmlEscape(valueText)}</title>
|
|
158
|
+
<linearGradient id="s" x2="0" y2="100%">
|
|
159
|
+
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
160
|
+
<stop offset="1" stop-opacity=".1"/>
|
|
161
|
+
</linearGradient>
|
|
162
|
+
<clipPath id="r"><rect width="${totalW}" height="${h}" rx="3" fill="#fff"/></clipPath>
|
|
163
|
+
<g clip-path="url(#r)">
|
|
164
|
+
<rect width="${lblW}" height="${h}" fill="${COLORS.label}"/>
|
|
165
|
+
<rect x="${lblW}" width="${valW}" height="${h}" fill="${b.color}"/>
|
|
166
|
+
<rect width="${totalW}" height="${h}" fill="url(#s)"/>
|
|
167
|
+
</g>
|
|
168
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="${fontSize}">
|
|
169
|
+
<text aria-hidden="true" x="${lblW / 2}" y="${h - 6}" fill="#010101" fill-opacity=".3">${_xmlEscape(labelText)}</text>
|
|
170
|
+
<text x="${lblW / 2}" y="${h - 7}">${_xmlEscape(labelText)}</text>
|
|
171
|
+
<text aria-hidden="true" x="${lblW + valW / 2}" y="${h - 6}" fill="#010101" fill-opacity=".3">${_xmlEscape(valueText)}</text>
|
|
172
|
+
<text x="${lblW + valW / 2}" y="${h - 7}">${_xmlEscape(valueText)}</text>
|
|
173
|
+
</g>
|
|
174
|
+
</svg>`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Public entry: produce the badge in the requested format.
|
|
179
|
+
*
|
|
180
|
+
* format: 'svg' (default) | 'json'
|
|
181
|
+
* style: 'flat' (default) | 'for-the-badge'
|
|
182
|
+
* scanRoot: directory containing .agentic-security/last-scan.json
|
|
183
|
+
* scan: pre-loaded scan object (skips disk read)
|
|
184
|
+
*/
|
|
185
|
+
function renderBadge({ format = 'svg', style = 'flat', scanRoot, scan } = {}) {
|
|
186
|
+
const summary = summarizeForBadge(scan || _readLastScan(scanRoot));
|
|
187
|
+
if (format === 'json') {
|
|
188
|
+
return JSON.stringify({
|
|
189
|
+
schemaVersion: 1,
|
|
190
|
+
label: summary.label,
|
|
191
|
+
message: summary.summary,
|
|
192
|
+
color: summary.color,
|
|
193
|
+
highest: summary.highest,
|
|
194
|
+
ageStr: summary.ageStr,
|
|
195
|
+
counts: summary.counts,
|
|
196
|
+
total: summary.total,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return renderSvg(summary, { style });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const _internal = { COLORS, _ageString, _readLastScan };
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
/***/ })
|
|
206
|
+
|
|
207
|
+
};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
export const id = 178;
|
|
2
|
+
export const ids = [178];
|
|
3
|
+
export const modules = {
|
|
4
|
+
|
|
5
|
+
/***/ 7178:
|
|
6
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
7
|
+
|
|
8
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9
|
+
/* harmony export */ runHistory: () => (/* binding */ runHistory),
|
|
10
|
+
/* harmony export */ runWhatIf: () => (/* binding */ runWhatIf)
|
|
11
|
+
/* harmony export */ });
|
|
12
|
+
/* unused harmony export listHistoricalRefs */
|
|
13
|
+
/* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1421);
|
|
14
|
+
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3024);
|
|
15
|
+
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6760);
|
|
16
|
+
/* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3291);
|
|
17
|
+
// Time-travel + counterfactual scanning (v0.68).
|
|
18
|
+
//
|
|
19
|
+
// Two new modes that exploit the pure-input shape of runFullScan:
|
|
20
|
+
//
|
|
21
|
+
// 1. `runHistory` — walks N historical git refs, scans each, emits a
|
|
22
|
+
// per-ref timeline of finding counts + identifies findings introduced
|
|
23
|
+
// and resolved between each pair of consecutive refs.
|
|
24
|
+
//
|
|
25
|
+
// 2. `runWhatIf` — overlays virtual file contents onto the working tree,
|
|
26
|
+
// scans the modified state, returns delta vs. the baseline scan.
|
|
27
|
+
// Useful for "what if I delete this middleware" / "what if I add this
|
|
28
|
+
// new route" / "what if I downgrade this dependency."
|
|
29
|
+
//
|
|
30
|
+
// Both modes read source via `git show <ref>:<path>` and feed the byte
|
|
31
|
+
// content into runFullScan's fileContents map directly. No `git checkout`
|
|
32
|
+
// or worktree write — the user's working tree is never disturbed.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
const MAX_FILES_PER_SCAN = 5000;
|
|
40
|
+
|
|
41
|
+
function _git(root, args) {
|
|
42
|
+
const r = (0,node_child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync)('git', args, { cwd: root, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
43
|
+
return { ok: r.status === 0, stdout: r.stdout || '', stderr: r.stderr || '' };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Enumerate refs going back `since` from HEAD at `interval` steps.
|
|
47
|
+
// `since`: a git-readable duration like '6.months', '30.days', '1.year'.
|
|
48
|
+
// `interval`: same shape; used to step backward.
|
|
49
|
+
function listHistoricalRefs(root, { since = '6.months', interval = '1.month' } = {}) {
|
|
50
|
+
// First, get the oldest reachable commit within `since`.
|
|
51
|
+
const log = _git(root, ['log', `--since=${since}`, '--format=%H %at %s']);
|
|
52
|
+
if (!log.ok) return [];
|
|
53
|
+
const rows = log.stdout.trim().split('\n').filter(Boolean).map(l => {
|
|
54
|
+
const [sha, ts, ...subject] = l.split(' ');
|
|
55
|
+
return { sha, timestamp: Number(ts), subject: subject.join(' ') };
|
|
56
|
+
});
|
|
57
|
+
if (rows.length === 0) return [];
|
|
58
|
+
// Step backward by `interval`-equivalent timestamps. Convert interval
|
|
59
|
+
// to seconds (rough: assume month=30d).
|
|
60
|
+
const ivSec = _approxSeconds(interval);
|
|
61
|
+
const picks = [];
|
|
62
|
+
let last = rows[0].timestamp + 1; // ensure HEAD itself is included
|
|
63
|
+
for (const row of rows) {
|
|
64
|
+
if (row.timestamp <= last - ivSec) {
|
|
65
|
+
picks.push(row);
|
|
66
|
+
last = row.timestamp;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Always include HEAD as the first sample.
|
|
70
|
+
return [{ sha: 'HEAD', timestamp: rows[0].timestamp, subject: rows[0].subject }, ...picks];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function _approxSeconds(d) {
|
|
74
|
+
const m = String(d).match(/^(\d+(?:\.\d+)?)\.(seconds?|minutes?|hours?|days?|weeks?|months?|years?)$/);
|
|
75
|
+
if (!m) return 30 * 86400;
|
|
76
|
+
const v = Number(m[1]);
|
|
77
|
+
const u = m[2];
|
|
78
|
+
const mult = u.startsWith('second') ? 1
|
|
79
|
+
: u.startsWith('minute') ? 60
|
|
80
|
+
: u.startsWith('hour') ? 3600
|
|
81
|
+
: u.startsWith('day') ? 86400
|
|
82
|
+
: u.startsWith('week') ? 7 * 86400
|
|
83
|
+
: u.startsWith('month') ? 30 * 86400
|
|
84
|
+
: u.startsWith('year') ? 365 * 86400
|
|
85
|
+
: 86400;
|
|
86
|
+
return v * mult;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// List all the source files at a given ref (relative paths). Filter to
|
|
90
|
+
// files the scanner actually processes.
|
|
91
|
+
function _listFilesAtRef(root, ref) {
|
|
92
|
+
const r = _git(root, ['ls-tree', '-r', '--name-only', ref]);
|
|
93
|
+
if (!r.ok) return [];
|
|
94
|
+
return r.stdout.trim().split('\n').filter(p => {
|
|
95
|
+
if (!p) return false;
|
|
96
|
+
if (p.includes('/node_modules/') || p.includes('/.venv/')) return false;
|
|
97
|
+
return /\.(?:js|jsx|ts|tsx|mjs|cjs|py|java|cs|kt|go|rb|php|sol|swift|rs|tf|yml|yaml|json|toml|md)$/i.test(p);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function _readFileAtRef(root, ref, file) {
|
|
102
|
+
const r = _git(root, ['show', `${ref}:${file}`]);
|
|
103
|
+
if (!r.ok) return null;
|
|
104
|
+
return r.stdout;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function _scanAtRef(root, ref) {
|
|
108
|
+
const files = _listFilesAtRef(root, ref).slice(0, MAX_FILES_PER_SCAN);
|
|
109
|
+
const fileContents = {};
|
|
110
|
+
for (const f of files) {
|
|
111
|
+
const c = _readFileAtRef(root, ref, f);
|
|
112
|
+
if (c != null) fileContents[f] = c;
|
|
113
|
+
}
|
|
114
|
+
const scan = await (0,_engine_js__WEBPACK_IMPORTED_MODULE_3__/* .runFullScan */ .wW)({ fileContents, scanRoot: root }, () => {});
|
|
115
|
+
return {
|
|
116
|
+
ref,
|
|
117
|
+
fileCount: Object.keys(fileContents).length,
|
|
118
|
+
findings: (scan.findings || []).map(_compact),
|
|
119
|
+
logicVulns: (scan.logicVulns || []).length,
|
|
120
|
+
secrets: (scan.secrets || []).length,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function _compact(f) {
|
|
125
|
+
return {
|
|
126
|
+
stableId: f.stableId || f.id,
|
|
127
|
+
file: f.file,
|
|
128
|
+
line: f.line,
|
|
129
|
+
vuln: f.vuln,
|
|
130
|
+
severity: f.severity,
|
|
131
|
+
cwe: f.cwe,
|
|
132
|
+
family: f.family || null,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Top-level: scan each historical ref + diff consecutive snapshots.
|
|
137
|
+
//
|
|
138
|
+
// Returns:
|
|
139
|
+
// {
|
|
140
|
+
// refs: [{ ref, when, fileCount, findings, secretsN, logicVulnsN }],
|
|
141
|
+
// timeline: [{ from, to, introduced: [...], resolved: [...] }],
|
|
142
|
+
// }
|
|
143
|
+
async function runHistory(root, opts = {}) {
|
|
144
|
+
const refs = listHistoricalRefs(root, opts);
|
|
145
|
+
if (refs.length === 0) return { error: 'no-refs-in-window', refs: [], timeline: [] };
|
|
146
|
+
const snapshots = [];
|
|
147
|
+
for (const r of refs) {
|
|
148
|
+
try {
|
|
149
|
+
const s = await _scanAtRef(root, r.sha);
|
|
150
|
+
snapshots.push({ ...s, when: new Date(r.timestamp * 1000).toISOString(), subject: r.subject });
|
|
151
|
+
} catch (e) {
|
|
152
|
+
snapshots.push({ ref: r.sha, error: e.message, when: new Date(r.timestamp * 1000).toISOString() });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Walk pairs from oldest → newest. snapshots[] is currently HEAD→old;
|
|
156
|
+
// reverse so timeline reads forward in time.
|
|
157
|
+
const ordered = [...snapshots].reverse();
|
|
158
|
+
const timeline = [];
|
|
159
|
+
for (let i = 1; i < ordered.length; i++) {
|
|
160
|
+
const a = ordered[i - 1];
|
|
161
|
+
const b = ordered[i];
|
|
162
|
+
const idsA = new Set((a.findings || []).map(f => f.stableId));
|
|
163
|
+
const idsB = new Set((b.findings || []).map(f => f.stableId));
|
|
164
|
+
const introduced = (b.findings || []).filter(f => !idsA.has(f.stableId));
|
|
165
|
+
const resolved = (a.findings || []).filter(f => !idsB.has(f.stableId));
|
|
166
|
+
timeline.push({
|
|
167
|
+
from: a.ref, fromWhen: a.when, to: b.ref, toWhen: b.when,
|
|
168
|
+
introducedN: introduced.length,
|
|
169
|
+
resolvedN: resolved.length,
|
|
170
|
+
introduced: introduced.slice(0, 50),
|
|
171
|
+
resolved: resolved.slice(0, 50),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return { refs: snapshots, timeline };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Counterfactual scan: apply a virtual overlay then scan.
|
|
178
|
+
// overlays: [{ file, content }]
|
|
179
|
+
// remove: [file] — files to virtually delete (skipped from scan input)
|
|
180
|
+
async function runWhatIf(root, { overlays = [], remove = [] } = {}) {
|
|
181
|
+
// Collect baseline working-tree files.
|
|
182
|
+
const baseFiles = _walkWorkingTree(root).slice(0, MAX_FILES_PER_SCAN);
|
|
183
|
+
const fileContents = {};
|
|
184
|
+
const removeSet = new Set(remove);
|
|
185
|
+
for (const rel of baseFiles) {
|
|
186
|
+
if (removeSet.has(rel)) continue;
|
|
187
|
+
try { fileContents[rel] = node_fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(node_path__WEBPACK_IMPORTED_MODULE_2__.join(root, rel), 'utf8'); } catch {}
|
|
188
|
+
}
|
|
189
|
+
// Apply overlays — these replace or add files.
|
|
190
|
+
for (const o of overlays) {
|
|
191
|
+
if (o && typeof o.file === 'string' && typeof o.content === 'string') {
|
|
192
|
+
fileContents[o.file] = o.content;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Baseline (without overlays) for delta computation.
|
|
196
|
+
const baseScan = await (0,_engine_js__WEBPACK_IMPORTED_MODULE_3__/* .runFullScan */ .wW)({ fileContents: _baselineFor(fileContents, overlays, remove, root), scanRoot: root }, () => {});
|
|
197
|
+
const whatIfScan = await (0,_engine_js__WEBPACK_IMPORTED_MODULE_3__/* .runFullScan */ .wW)({ fileContents, scanRoot: root }, () => {});
|
|
198
|
+
const baseIds = new Set((baseScan.findings || []).map(f => f.stableId || f.id));
|
|
199
|
+
const wIds = new Set((whatIfScan.findings || []).map(f => f.stableId || f.id));
|
|
200
|
+
const introduced = (whatIfScan.findings || []).filter(f => !baseIds.has(f.stableId || f.id)).map(_compact);
|
|
201
|
+
const removed = (baseScan.findings || []).filter(f => !wIds.has(f.stableId || f.id)).map(_compact);
|
|
202
|
+
return {
|
|
203
|
+
baselineFindings: (baseScan.findings || []).length,
|
|
204
|
+
whatIfFindings: (whatIfScan.findings || []).length,
|
|
205
|
+
delta: whatIfScan.findings.length - baseScan.findings.length,
|
|
206
|
+
introduced,
|
|
207
|
+
removed,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function _baselineFor(fileContents, overlays, remove, root) {
|
|
212
|
+
// Reverse the overlay: restore original content (from disk) for any
|
|
213
|
+
// overlay'd file; re-add any virtually-removed file. Paths are resolved
|
|
214
|
+
// relative to the scan root, NOT the cwd.
|
|
215
|
+
const base = { ...fileContents };
|
|
216
|
+
for (const o of overlays) {
|
|
217
|
+
if (!o || typeof o.file !== 'string') continue;
|
|
218
|
+
try { base[o.file] = node_fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(node_path__WEBPACK_IMPORTED_MODULE_2__.join(root, o.file), 'utf8'); }
|
|
219
|
+
catch { delete base[o.file]; }
|
|
220
|
+
}
|
|
221
|
+
for (const rel of (remove || [])) {
|
|
222
|
+
try { base[rel] = node_fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(node_path__WEBPACK_IMPORTED_MODULE_2__.join(root, rel), 'utf8'); } catch {}
|
|
223
|
+
}
|
|
224
|
+
return base;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function _walkWorkingTree(root) {
|
|
228
|
+
const out = [];
|
|
229
|
+
const exclude = new Set(['node_modules', '.git', '.venv', 'dist', 'build', '__pycache__', 'target', '.next', '.nuxt']);
|
|
230
|
+
function walk(dir, rel = '') {
|
|
231
|
+
let entries;
|
|
232
|
+
try { entries = node_fs__WEBPACK_IMPORTED_MODULE_1__.readdirSync(dir, { withFileTypes: true }); } catch { return; }
|
|
233
|
+
for (const e of entries) {
|
|
234
|
+
if (exclude.has(e.name)) continue;
|
|
235
|
+
const full = node_path__WEBPACK_IMPORTED_MODULE_2__.join(dir, e.name);
|
|
236
|
+
const r = rel ? `${rel}/${e.name}` : e.name;
|
|
237
|
+
if (e.isDirectory()) walk(full, r);
|
|
238
|
+
else if (e.isFile() && /\.(?:js|jsx|ts|tsx|mjs|cjs|py|java|cs|kt|go|rb|php|sol|swift|rs|tf|yml|yaml|json|toml|md)$/i.test(e.name)) {
|
|
239
|
+
out.push(r);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
walk(root);
|
|
244
|
+
return out;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
/***/ })
|
|
249
|
+
|
|
250
|
+
};
|