@clear-capabilities/agentic-security-scanner 0.143.0 → 0.145.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +555 -0
  2. package/bin/agentic-security.js +770 -49
  3. package/dist/1.index.js +223 -0
  4. package/dist/113.index.js +117 -18
  5. package/dist/144.index.js +163 -0
  6. package/dist/178.index.js +24 -6
  7. package/dist/238.index.js +3 -2
  8. package/dist/265.index.js +191 -0
  9. package/dist/271.index.js +165 -0
  10. package/dist/384.index.js +1 -1
  11. package/dist/435.index.js +187 -52
  12. package/dist/444.index.js +11 -2
  13. package/dist/449.index.js +76 -12
  14. package/dist/526.index.js +117 -18
  15. package/dist/552.index.js +97 -0
  16. package/dist/637.index.js +27 -5
  17. package/dist/730.index.js +311 -0
  18. package/dist/736.index.js +301 -0
  19. package/dist/824.index.js +7 -0
  20. package/dist/905.index.js +88 -22
  21. package/dist/920.index.js +491 -0
  22. package/dist/970.index.js +173 -0
  23. package/dist/agentic-security.mjs +13 -13
  24. package/dist/agentic-security.mjs.sha256 +1 -1
  25. package/dist/calibration-seed.json +2 -0
  26. package/package.json +23 -9
  27. package/src/compare.js +6 -1
  28. package/src/dataflow/CLAUDE.md +1 -1
  29. package/src/dataflow/index.js +18 -0
  30. package/src/dataflow/privacy-catalog.js +290 -0
  31. package/src/dataflow/privacy-deep-walker.js +515 -0
  32. package/src/dataflow/privacy-governance.js +126 -0
  33. package/src/dataflow/privacy-inventory.js +154 -0
  34. package/src/dataflow/privacy-sink-policy.js +125 -0
  35. package/src/dataflow/privacy-taint.js +115 -54
  36. package/src/dataflow/privacy-taxonomy.js +233 -0
  37. package/src/discovery/disprove.js +7 -3
  38. package/src/discovery/hunter.js +9 -5
  39. package/src/discovery/index.js +2 -2
  40. package/src/discovery/llm-invoke.js +69 -13
  41. package/src/egress/audit.js +147 -0
  42. package/src/egress/policy.js +313 -0
  43. package/src/egress/redact.js +180 -0
  44. package/src/engine.js +1048 -302
  45. package/src/fix/apply-fix-service.js +404 -0
  46. package/src/fix/approver-registry.js +157 -0
  47. package/src/history-scan.js +22 -5
  48. package/src/ir/CLAUDE.md +1 -1
  49. package/src/llm-validator/index.js +86 -9
  50. package/src/llm-validator/model-status.js +66 -0
  51. package/src/lsp/server.js +49 -2
  52. package/src/mcp/tools.js +177 -50
  53. package/src/pipeline/analyzer-supervisor.js +93 -0
  54. package/src/pipeline/analyzer-worker.js +26 -0
  55. package/src/pipeline/annotator-runner.js +33 -0
  56. package/src/pipeline/assurance-mode.js +154 -0
  57. package/src/pipeline/cascade-worker-pool.js +172 -0
  58. package/src/pipeline/cascade-worker.js +43 -0
  59. package/src/pipeline/coverage-ledger.js +0 -0
  60. package/src/pipeline/detector-runner.js +51 -0
  61. package/src/pipeline/enrichment-completion.js +58 -0
  62. package/src/pipeline/evidence-provenance.js +91 -0
  63. package/src/pipeline/finding-schema.js +108 -0
  64. package/src/pipeline/legacy-compat.js +101 -0
  65. package/src/pipeline/producer-collector.js +48 -0
  66. package/src/pipeline/producer-registry.js +112 -0
  67. package/src/pipeline/scan-health.js +144 -0
  68. package/src/posture/CLAUDE.md +123 -0
  69. package/src/posture/accuracy-scorecard.js +156 -1
  70. package/src/posture/adversary-agent.js +15 -3
  71. package/src/posture/artifact-registry.js +241 -0
  72. package/src/posture/auditor-walkthrough.js +186 -21
  73. package/src/posture/calibration-feedback.js +201 -0
  74. package/src/posture/calibration-seed.json +2 -0
  75. package/src/posture/calibration.js +25 -0
  76. package/src/posture/compliance-evidence-signing.js +131 -0
  77. package/src/posture/compliance-policy.js +324 -17
  78. package/src/posture/cross-repo-memory.js +7 -2
  79. package/src/posture/custom-rules.js +36 -0
  80. package/src/posture/deterministic.js +8 -1
  81. package/src/posture/encryption-provider.js +205 -0
  82. package/src/posture/evidence-grade-wording.js +71 -0
  83. package/src/posture/fix-history.js +137 -20
  84. package/src/posture/fix-honesty-gate.js +47 -6
  85. package/src/posture/fix-verify.js +65 -8
  86. package/src/posture/fleet.js +0 -0
  87. package/src/posture/flow-narration.js +7 -2
  88. package/src/posture/git-history.js +13 -5
  89. package/src/posture/legal-hold.js +140 -0
  90. package/src/posture/llm-redteam.js +10 -1
  91. package/src/posture/material-change.js +111 -2
  92. package/src/posture/mttr.js +75 -12
  93. package/src/posture/policy-bundle.js +274 -0
  94. package/src/posture/pre-incident-archaeology.js +39 -7
  95. package/src/posture/privacy-framework.js +47 -6
  96. package/src/posture/production-feedback.js +179 -0
  97. package/src/posture/provenance/ai-authorship.js +68 -0
  98. package/src/posture/provenance/branch-entry.js +80 -0
  99. package/src/posture/provenance/cache.js +143 -0
  100. package/src/posture/provenance/confidence.js +36 -0
  101. package/src/posture/provenance/coordinator.js +786 -0
  102. package/src/posture/provenance/dag-walk.js +249 -0
  103. package/src/posture/provenance/evidence-attribution.js +59 -0
  104. package/src/posture/provenance/git-evidence.js +310 -0
  105. package/src/posture/provenance/lifecycle.js +208 -0
  106. package/src/posture/provenance/missing-control-resolver.js +137 -0
  107. package/src/posture/provenance/origin-resolver.js +342 -0
  108. package/src/posture/provenance/predicate-replay.js +133 -0
  109. package/src/posture/provenance/providers/config.js +39 -0
  110. package/src/posture/provenance/providers/github.js +62 -0
  111. package/src/posture/provenance/providers/gitlab.js +58 -0
  112. package/src/posture/provenance/repo-lineage.js +74 -0
  113. package/src/posture/provenance/sca-origin.js +139 -0
  114. package/src/posture/provenance/schema.js +255 -0
  115. package/src/posture/provenance/transitive-sca.js +147 -0
  116. package/src/posture/provenance/validate.js +30 -0
  117. package/src/posture/provenance-evidence-bundle.js +144 -0
  118. package/src/posture/retention-policy.js +132 -0
  119. package/src/posture/risk-dollars.js +216 -26
  120. package/src/posture/sbom-diff.js +15 -2
  121. package/src/posture/scan-checkpoint.js +176 -31
  122. package/src/posture/secret-history.js +10 -2
  123. package/src/posture/state-dir.js +64 -5
  124. package/src/posture/state-lifecycle-report.js +77 -0
  125. package/src/posture/suppressions.js +59 -3
  126. package/src/posture/vuln-archaeology.js +8 -2
  127. package/src/pr-delta.js +25 -4
  128. package/src/privacy/ir-adapter.js +380 -0
  129. package/src/report/index.js +248 -5
  130. package/src/report/oscal.js +7 -2
  131. package/src/runScan.js +34 -5
  132. package/src/sast/cpp.js +3 -14
  133. package/src/sast/rate-limit.js +33 -3
  134. package/src/sca/llm-function-extract.js +6 -0
  135. package/src/util/git-hardening.js +128 -0
@@ -0,0 +1,128 @@
1
+ // Hardening for every `git` subprocess call this scanner makes against a
2
+ // SCANNED repository it does not control — i.e. any git invocation whose
3
+ // `cwd` (or `-C <dir>`) is a project the scanner was asked to scan, as
4
+ // opposed to this project's own trusted checkout.
5
+ //
6
+ // Verified RCE (second independent Finding Provenance PRD audit,
7
+ // FR-PROV-024 / PRD Section 8 "never run repository hooks or untrusted
8
+ // build scripts"): git-evidence.js's `_run` invoked `git` with no config
9
+ // hardening at all. A hostile repo's `.git/config` can set `core.fsmonitor`
10
+ // to point at an attacker script; git executes it on an ordinary READ-ONLY
11
+ // command like `git status --porcelain` — no clone, no checkout, no
12
+ // deliberate command needed, just `getRepoState()` reading repo state.
13
+ // Reproduced against this exact repro shape before this module existed:
14
+ // `getRepoState()` alone wrote a marker file outside the repo.
15
+ //
16
+ // Four independent hostile-config surfaces, each closed by a different
17
+ // flag/env var (do not assume one covers another — a same-class RCE
18
+ // survived the first round of this hardening precisely because
19
+ // `--no-textconv` was assumed to cover `git diff` the same way it covers
20
+ // `git show`/`git log -p`/`git blame`, and it does not):
21
+ // - `core.fsmonitor` -> fires on `git status` (and other porcelain
22
+ // commands that consult the index). Closed by
23
+ // `-c core.fsmonitor=` (empty value disables it).
24
+ // - `core.hooksPath` -> redirects git's hook lookup to an
25
+ // attacker-controlled directory (pre-commit,
26
+ // post-checkout, ...). None of THIS module's
27
+ // read-only operations should fire a hook, but a
28
+ // caller elsewhere in the tree that does invoke a
29
+ // hook-shaped command (checkout, commit) inherits
30
+ // the same exposure — hardened uniformly rather
31
+ // than relying on each call site to reason about
32
+ // whether its own command can trigger a hook.
33
+ // Closed by `-c core.hooksPath=/dev/null`
34
+ // (verified: git tries to stat
35
+ // `/dev/null/<hookname>`, which is not a
36
+ // directory, so hook lookup fails closed — this
37
+ // is NOT relying on /dev/null being an empty
38
+ // *file*, it works because it isn't a directory).
39
+ // - `.gitattributes` -> a `diff=<name>` attribute + a matching
40
+ // textconv driver `diff.<name>.textconv` config key points a text
41
+ // filter at an attacker script; fires on any
42
+ // command that renders blob/diff CONTENT (`git
43
+ // show`/`git diff`/`git log -p`/`git log -L`/
44
+ // `git blame`) unless `--no-textconv` is passed.
45
+ // Verified per-subcommand: `git show -s` (no
46
+ // content shown) and `git show <sha>:<path>`
47
+ // (blob cat, not a diff) were NOT exploitable in
48
+ // this git version, but `git show -U0`, `git log
49
+ // -L`, and `git blame` all were.
50
+ // - `.git/config` / an EXTERNAL diff driver — `.gitattributes`
51
+ // `.gitattributes` `diff=<name>` + `.git/config [diff "<name>"]
52
+ // external diff driver command=<script>`, or the repo-local/global
53
+ // `diff.external` config key — is a DIFFERENT
54
+ // mechanism from the textconv driver above and is
55
+ // NOT closed by `--no-textconv`. VERIFIED: `git
56
+ // -c core.fsmonitor= -c core.hooksPath=/dev/null
57
+ // diff --unified=0 --no-textconv <ref>...HEAD`
58
+ // still runs the attacker's `diff.evil.command`
59
+ // script — `--no-textconv` only suppresses the
60
+ // TEXTCONV driver, and `git diff` (unlike `git
61
+ // show`/`git log -p`/`git blame`, which were all
62
+ // verified safe with just `--no-textconv`) honours
63
+ // an external diff driver by default regardless.
64
+ // Closed by `--no-ext-diff`, which must be passed
65
+ // explicitly on every `git diff` invocation (same
66
+ // reason `--no-textconv` isn't a `-c` flag: it's a
67
+ // diff-machinery option, not repo config). This
68
+ // was the live RCE a second review found after the
69
+ // first round of this hardening shipped —
70
+ // material-change.js's `classifyGitDiff` (the real
71
+ // entry point for `/scan --diff`) had
72
+ // `--no-textconv` but not `--no-ext-diff` and was
73
+ // still exploitable end-to-end.
74
+ //
75
+ // A FIFTH surface is known but not exploitable through any call site in this
76
+ // codebase today, so it is documented rather than closed: a `clean` smudge
77
+ // filter (`.gitattributes` `filter=<name>` + `filter.<name>.clean`) fires on
78
+ // a WORKTREE diff (e.g. `git diff --name-only HEAD` with no `<ref>` on the
79
+ // other side) and has no git flag to disable it at all (unlike textconv/
80
+ // ext-diff). Every `git diff` call site in this codebase diffs two refs
81
+ // (`<ref>...HEAD`), never the worktree against HEAD, so nothing here hits
82
+ // it — but a future worktree-diff call site would silently reintroduce this
83
+ // exact vulnerability class and must not assume `hardenGitArgs` covers it.
84
+ //
85
+ // `GIT_CONFIG_NOSYSTEM=1` additionally blocks a SYSTEM-level git config
86
+ // (outside any repository, e.g. /etc/gitconfig) from re-introducing a
87
+ // hostile setting the `-c` flags above didn't anticipate; `GIT_TERMINAL_PROMPT=0`
88
+ // stops a git invocation from ever blocking on an interactive credential
89
+ // prompt (a hostile repo pointing `origin`/a submodule at a URL that
90
+ // prompts). Both are environment variables, not `-c` flags — git does not
91
+ // expose either as repo-local config.
92
+ //
93
+ // Every `git` subprocess call this scanner makes against a scan target's
94
+ // repository MUST route its args through `hardenGitArgs` and its env
95
+ // through `hardenGitEnv`. A `git show`/`git diff`/`git log -p`/`git log -L`/
96
+ // `git blame` invocation must ALSO pass `--no-textconv` explicitly (it is
97
+ // not a `-c` config value, so it isn't folded into `GIT_HARDENED_CONFIG_ARGS`
98
+ // — it must appear in the invocation's own args, after the config args), and
99
+ // a `git diff` invocation must ADDITIONALLY pass `--no-ext-diff` (a
100
+ // different flag for a different surface — see above; `--no-textconv` does
101
+ // not imply it).
102
+
103
+ export const GIT_HARDENED_CONFIG_ARGS = Object.freeze([
104
+ '-c', 'core.fsmonitor=',
105
+ '-c', 'core.hooksPath=/dev/null',
106
+ ]);
107
+
108
+ export const GIT_HARDENED_ENV = Object.freeze({
109
+ GIT_CONFIG_NOSYSTEM: '1',
110
+ GIT_TERMINAL_PROMPT: '0',
111
+ });
112
+
113
+ // Prepend the hardening `-c` flags to a git argv. These are GLOBAL options
114
+ // and must appear before the subcommand, which is why this always prepends
115
+ // rather than appending — a `-c` after the subcommand name is parsed as a
116
+ // positional argument to that subcommand, not a global option.
117
+ export function hardenGitArgs(args) {
118
+ return [...GIT_HARDENED_CONFIG_ARGS, ...(Array.isArray(args) ? args : [])];
119
+ }
120
+
121
+ // Build the `env` option for execFileSync/spawnSync. Node's `env` option
122
+ // REPLACES the child's environment rather than merging with it, so this
123
+ // always spreads `process.env` first — passing `hardenGitEnv()` with no
124
+ // argument must be behaviourally identical to inheriting the parent
125
+ // environment plus the two hardening vars, never a stripped-down one.
126
+ export function hardenGitEnv(extraEnv) {
127
+ return { ...process.env, ...GIT_HARDENED_ENV, ...(extraEnv || {}) };
128
+ }