@clear-capabilities/agentic-security-scanner 0.161.0 → 0.163.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 (182) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/bin/agentic-security.js +98 -2
  3. package/dist/1340.index.js +1871 -0
  4. package/dist/3477.index.js +727 -0
  5. package/dist/3499.index.js +23 -3
  6. package/dist/4113.index.js +59 -8
  7. package/dist/5014.index.js +833 -0
  8. package/dist/5756.index.js +2 -2
  9. package/dist/6257.index.js +1 -1
  10. package/dist/6907.index.js +248 -0
  11. package/dist/6994.index.js +1 -1
  12. package/dist/7033.index.js +33 -5
  13. package/dist/7439.index.js +1822 -0
  14. package/dist/7838.index.js +38 -2
  15. package/dist/8798.index.js +1 -1
  16. package/dist/9207.index.js +5 -0
  17. package/dist/9560.index.js +2336 -27
  18. package/dist/957.index.js +1 -1
  19. package/dist/{1905.index.js → 9999.index.js} +306 -13
  20. package/dist/agentic-security.mjs +12 -12
  21. package/dist/agentic-security.mjs.sha256 +1 -1
  22. package/package.json +39 -7
  23. package/src/capabilities/CLAUDE.md +114 -0
  24. package/src/capabilities/address.js +73 -0
  25. package/src/capabilities/attack-coverage.js +93 -0
  26. package/src/capabilities/decide.js +256 -0
  27. package/src/capabilities/delegate.js +69 -0
  28. package/src/capabilities/egress.js +20 -0
  29. package/src/capabilities/hook-advice.js +50 -0
  30. package/src/capabilities/index.js +32 -0
  31. package/src/capabilities/manifest.js +344 -0
  32. package/src/capabilities/outbound.js +189 -0
  33. package/src/capabilities/paths.js +57 -0
  34. package/src/capabilities/probes.js +211 -0
  35. package/src/capabilities/proxy.js +182 -0
  36. package/src/capabilities/reasons.js +67 -0
  37. package/src/capabilities/receipts.js +356 -0
  38. package/src/capabilities/records.js +58 -0
  39. package/src/capabilities/recovery.js +367 -0
  40. package/src/capabilities/report.js +81 -0
  41. package/src/capabilities/runner.js +236 -0
  42. package/src/capabilities/secrets.js +26 -0
  43. package/src/capabilities/tool-gate.js +119 -0
  44. package/src/capabilities/tool-registry.js +60 -0
  45. package/src/dataflow/CLAUDE.md +29 -0
  46. package/src/dataflow/catalog.js +21 -0
  47. package/src/dataflow/engine.js +20 -0
  48. package/src/dataflow/guard-dominance.js +352 -0
  49. package/src/discovery/CLAUDE.md +18 -0
  50. package/src/discovery/index.js +43 -1
  51. package/src/discovery/lenses.js +18 -0
  52. package/src/discovery/memory.js +7 -5
  53. package/src/engine.js +80 -15
  54. package/src/fix/apply-fix-service.js +33 -3
  55. package/src/integrations/index.js +5 -2
  56. package/src/ir/CLAUDE.md +14 -0
  57. package/src/ir/implicit-handler-params.js +74 -0
  58. package/src/ir/parser-cs.js +20 -0
  59. package/src/ir/parser-go.js +30 -13
  60. package/src/ir/parser-java.js +11 -0
  61. package/src/language/nix-eval-isolation.js +33 -5
  62. package/src/lineage/CLAUDE.md +31 -0
  63. package/src/lineage/deployment/adapter-cloud.js +202 -0
  64. package/src/lineage/deployment/adapter-compose.js +90 -0
  65. package/src/lineage/deployment/adapter-kit.js +142 -0
  66. package/src/lineage/deployment/adapter-kubernetes.js +247 -0
  67. package/src/lineage/deployment/attack-paths.js +443 -0
  68. package/src/lineage/deployment/boundaries-run.js +223 -0
  69. package/src/lineage/deployment/boundary-graph.js +567 -0
  70. package/src/lineage/deployment/cross-repo.js +253 -0
  71. package/src/lineage/deployment/drift.js +383 -0
  72. package/src/lineage/deployment/ingest.js +221 -0
  73. package/src/lineage/deployment/projection.js +244 -0
  74. package/src/lineage/deployment/trace-correlation.js +541 -0
  75. package/src/lineage/source-registry.js +19 -0
  76. package/src/mcp/CLAUDE.md +14 -3
  77. package/src/mcp/invariant-tools.js +64 -0
  78. package/src/mcp/portfolio-tools.js +79 -0
  79. package/src/mcp/redact.js +15 -0
  80. package/src/mcp/server.js +24 -3
  81. package/src/mcp/tools.js +30 -5
  82. package/src/posture/CLAUDE.md +505 -0
  83. package/src/posture/accuracy-scorecard.js +95 -4
  84. package/src/posture/assurance/baseline-inventory.js +218 -0
  85. package/src/posture/assurance/baseline.js +322 -0
  86. package/src/posture/assurance/bounded-io.js +145 -0
  87. package/src/posture/assurance/config.js +299 -0
  88. package/src/posture/assurance/contracts.js +315 -0
  89. package/src/posture/assurance/identity.js +62 -0
  90. package/src/posture/assurance/migrations.js +259 -0
  91. package/src/posture/assurance/rollback.js +214 -0
  92. package/src/posture/assurance/rollout.js +200 -0
  93. package/src/posture/assurance/schema-kit.js +111 -0
  94. package/src/posture/assurance/verification-record.js +258 -0
  95. package/src/posture/attestation.js +5 -0
  96. package/src/posture/autopilot.js +28 -1
  97. package/src/posture/business-logic.js +26 -4
  98. package/src/posture/evaluation/bakeoff.js +148 -0
  99. package/src/posture/evaluation/custody.js +200 -0
  100. package/src/posture/evaluation/deployment-ablation.js +416 -0
  101. package/src/posture/evaluation/dev-cases.js +65 -0
  102. package/src/posture/evaluation/economics.js +85 -0
  103. package/src/posture/evaluation/gates.js +161 -0
  104. package/src/posture/evaluation/grouping.js +101 -0
  105. package/src/posture/evaluation/interval.js +132 -0
  106. package/src/posture/evaluation/invariant-ablation.js +325 -0
  107. package/src/posture/evaluation/labels.js +200 -0
  108. package/src/posture/evaluation/protocol.js +308 -0
  109. package/src/posture/evaluation/release-gate.js +209 -0
  110. package/src/posture/evaluation/report.js +158 -0
  111. package/src/posture/evaluation/runner.js +273 -0
  112. package/src/posture/evaluation/scan-child.js +80 -0
  113. package/src/posture/evaluation/score.js +174 -0
  114. package/src/posture/evaluation/synthetic.js +90 -0
  115. package/src/posture/evaluation/why-missed.js +219 -0
  116. package/src/posture/evidence-bundle.js +93 -7
  117. package/src/posture/execution-proof.js +11 -1
  118. package/src/posture/fix-verify-loop.js +20 -6
  119. package/src/posture/fix-verify.js +37 -2
  120. package/src/posture/fleet.js +11 -2
  121. package/src/posture/invariants/cli.js +95 -0
  122. package/src/posture/invariants/coverage.js +164 -0
  123. package/src/posture/invariants/export.js +178 -0
  124. package/src/posture/invariants/expressions.js +46 -0
  125. package/src/posture/invariants/lifecycle.js +289 -0
  126. package/src/posture/invariants/project-input.js +55 -0
  127. package/src/posture/invariants/repair.js +340 -0
  128. package/src/posture/invariants/run.js +45 -0
  129. package/src/posture/invariants/scenarios.js +311 -0
  130. package/src/posture/invariants/schema.js +167 -0
  131. package/src/posture/invariants/shrink.js +407 -0
  132. package/src/posture/invariants/state-assertions.js +165 -0
  133. package/src/posture/logic-claims.js +12 -0
  134. package/src/posture/model-routing.js +40 -0
  135. package/src/posture/oracles/adapters.js +531 -0
  136. package/src/posture/oracles/conformance.js +276 -0
  137. package/src/posture/oracles/oracle.js +453 -0
  138. package/src/posture/oracles/registry.js +76 -0
  139. package/src/posture/oracles/scenario-classes.js +223 -0
  140. package/src/posture/portfolio/backend.js +279 -0
  141. package/src/posture/portfolio/bundle.js +314 -0
  142. package/src/posture/portfolio/cli.js +142 -0
  143. package/src/posture/portfolio/manifest.js +263 -0
  144. package/src/posture/portfolio/progress.js +267 -0
  145. package/src/posture/portfolio/resume.js +130 -0
  146. package/src/posture/portfolio/retention.js +207 -0
  147. package/src/posture/portfolio/scheduler.js +488 -0
  148. package/src/posture/portfolio/signing.js +155 -0
  149. package/src/posture/portfolio/wording.js +59 -0
  150. package/src/posture/portfolio/work-units.js +405 -0
  151. package/src/posture/replay/replay.js +250 -0
  152. package/src/posture/routing/adapter.js +140 -0
  153. package/src/posture/routing/calibration.js +278 -0
  154. package/src/posture/routing/canary.js +141 -0
  155. package/src/posture/routing/control.js +35 -0
  156. package/src/posture/routing/decide.js +211 -0
  157. package/src/posture/routing/drift.js +137 -0
  158. package/src/posture/routing/economics.js +185 -0
  159. package/src/posture/routing/feedback.js +207 -0
  160. package/src/posture/routing/index.js +31 -0
  161. package/src/posture/routing/outcomes.js +281 -0
  162. package/src/posture/routing/promotion.js +291 -0
  163. package/src/posture/routing/receipts.js +59 -0
  164. package/src/posture/routing/report.js +142 -0
  165. package/src/posture/routing/shadow.js +53 -0
  166. package/src/posture/specification-mining.js +26 -0
  167. package/src/posture/verification/advisory-state.js +71 -0
  168. package/src/posture/verification/emit.js +257 -0
  169. package/src/posture/verification/hypothesis-promotion.js +211 -0
  170. package/src/posture/verification/patch-negative.js +226 -0
  171. package/src/posture/verification/patch-promotion.js +113 -0
  172. package/src/posture/verification/projection.js +183 -0
  173. package/src/posture/verification/repair-records.js +124 -0
  174. package/src/posture/verifier.js +16 -0
  175. package/src/report/index.js +100 -1
  176. package/src/sandbox/CLAUDE.md +51 -0
  177. package/src/sandbox/backend-namespace.js +7 -0
  178. package/src/sandbox/backend-userspace.js +151 -34
  179. package/src/sandbox/control-probes.js +215 -0
  180. package/src/sandbox/supervise.js +201 -0
  181. package/src/sandbox/trust-boundary.js +113 -0
  182. package/src/sandbox/trust-domains.js +171 -0
@@ -0,0 +1,171 @@
1
+ // Trust domains for verification (CORE-003).
2
+ //
3
+ // Four domains stay separate, and this module is the single place that says
4
+ // which one may do what. It is deliberately data plus small pure functions: the
5
+ // ENFORCEMENT lives at the process boundary (`trust-boundary.js`, the sandbox
6
+ // profile, file modes), not here. A table nobody consults at the boundary would
7
+ // be documentation pretending to be a control, so every entry below has an
8
+ // attack test that tries the forbidden action through the real boundary.
9
+ //
10
+ // target analyzed code and anything it spawns. Adversarial by assumption.
11
+ // worker the model/agent that proposes hypotheses, scenarios and patches.
12
+ // Adversarial for authority purposes: may be prompt-injected by the
13
+ // target. Authors proposals, never truth.
14
+ // verifier the protected verifier / evaluation custodian. Holds sealed labels,
15
+ // runs oracles, writes authoritative evidence.
16
+ // signer holds signing key material and issues signatures over evidence the
17
+ // verifier produced. Never executes target or worker code.
18
+ //
19
+ // What a lower-trust domain may NEVER do, whatever it prints or writes:
20
+ // - read signing keys, the install HMAC key or sealed labels
21
+ // - write authoritative evidence
22
+ // - set a verification status (only verifier-observed evidence can)
23
+ // - read host paths unrelated to its own workspace (credential directories)
24
+ import os from 'node:os';
25
+ import path from 'node:path';
26
+
27
+ export const DOMAINS = Object.freeze({
28
+ TARGET: 'target',
29
+ WORKER: 'worker',
30
+ VERIFIER: 'verifier',
31
+ SIGNER: 'signer',
32
+ });
33
+
34
+ export const RESOURCES = Object.freeze({
35
+ SIGNING_KEY: 'signing-key',
36
+ HMAC_KEY: 'hmac-key',
37
+ SEALED_LABELS: 'sealed-labels',
38
+ AUTHORITATIVE_EVIDENCE: 'authoritative-evidence',
39
+ VERIFICATION_STATUS: 'verification-status',
40
+ HOST_CREDENTIALS: 'host-credentials',
41
+ WORKSPACE: 'workspace',
42
+ });
43
+
44
+ // domain -> resource -> allowed actions. Absence means DENIED (default deny).
45
+ const POLICY = Object.freeze({
46
+ [DOMAINS.TARGET]: { [RESOURCES.WORKSPACE]: ['read', 'write'] },
47
+ [DOMAINS.WORKER]: { [RESOURCES.WORKSPACE]: ['read', 'write'] },
48
+ [DOMAINS.VERIFIER]: {
49
+ [RESOURCES.WORKSPACE]: ['read'],
50
+ [RESOURCES.SEALED_LABELS]: ['read'],
51
+ [RESOURCES.AUTHORITATIVE_EVIDENCE]: ['read', 'write'],
52
+ [RESOURCES.VERIFICATION_STATUS]: ['write'],
53
+ [RESOURCES.HMAC_KEY]: ['read'],
54
+ },
55
+ [DOMAINS.SIGNER]: {
56
+ [RESOURCES.SIGNING_KEY]: ['read'],
57
+ [RESOURCES.AUTHORITATIVE_EVIDENCE]: ['read'],
58
+ },
59
+ });
60
+
61
+ /** Default-deny policy lookup. */
62
+ export function mayDo(domain, resource, action) {
63
+ return !!POLICY[domain]?.[resource]?.includes(action);
64
+ }
65
+
66
+ /** Domains that execute or are influenced by untrusted content. */
67
+ export function isUntrusted(domain) {
68
+ return domain === DOMAINS.TARGET || domain === DOMAINS.WORKER;
69
+ }
70
+
71
+ // ---- protected host paths --------------------------------------------------
72
+
73
+ /** Config directory holding the Ed25519 keys and the install HMAC key. */
74
+ export function keyDirectory(env = process.env) {
75
+ const xdg = env.XDG_CONFIG_HOME;
76
+ const base = xdg && xdg.length ? xdg : path.join(os.homedir(), '.config');
77
+ return path.join(base, 'agentic-security');
78
+ }
79
+
80
+ // Credential locations under the user's home that no target has a reason to
81
+ // read. A denylist can never be complete, so it is the floor, not the claim:
82
+ // the caller adds sealed-label and evidence directories explicitly.
83
+ const HOME_CREDENTIAL_PATHS = Object.freeze([
84
+ '.ssh', '.aws', '.gnupg', '.azure', '.kube', '.docker', '.netrc', '.npmrc',
85
+ '.pypirc', '.git-credentials', '.claude', '.config/gcloud', '.config/gh',
86
+ ]);
87
+
88
+ /**
89
+ * Every host path a target process must not read. The signing/HMAC key
90
+ * directory is always included.
91
+ */
92
+ export function protectedReadPaths({
93
+ home = os.homedir(), env = process.env, labelDirs = [], evidenceDirs = [], extra = [],
94
+ } = {}) {
95
+ const out = [keyDirectory(env)];
96
+ for (const rel of HOME_CREDENTIAL_PATHS) out.push(path.join(home, rel));
97
+ for (const p of [...labelDirs, ...evidenceDirs, ...extra]) if (p) out.push(path.resolve(p));
98
+ return [...new Set(out)];
99
+ }
100
+
101
+ // ---- secret material in worker environments --------------------------------
102
+
103
+ const SECRET_NAME = /(?:^|_)(?:secret|token|password|passwd|api_?key|private_?key|credential|hmac|signing|auth)(?:_|$)|^(?:AWS_|GITHUB_|NPM_|ANTHROPIC_|OPENAI_)/i;
104
+ const PEM_PRIVATE = /-----BEGIN [A-Z ]*PRIVATE KEY-----/;
105
+ // An explicit allowlist wins over the name heuristic: these carry no secret.
106
+ const SAFE_NAMES = new Set(['PATH', 'HOME', 'TMPDIR', 'LANG', 'ROOT', 'LC_ALL', 'TZ', 'CI']);
107
+
108
+ /** Names (never values) of environment entries that look like secret material. */
109
+ export function secretEnvNames(env = {}) {
110
+ const out = [];
111
+ for (const [k, v] of Object.entries(env || {})) {
112
+ if (SAFE_NAMES.has(k)) continue;
113
+ if (SECRET_NAME.test(k) || PEM_PRIVATE.test(String(v ?? ''))) out.push(k);
114
+ }
115
+ return out.sort();
116
+ }
117
+
118
+ /** `{ ok:false, offenders }` when an environment bound for a worker holds secrets. */
119
+ export function assertNoSecretMaterial(env = {}) {
120
+ const offenders = secretEnvNames(env);
121
+ return { ok: offenders.length === 0, offenders };
122
+ }
123
+
124
+ /** Copy of `env` without secret-looking entries. */
125
+ export function scrubEnv(env = {}) {
126
+ const drop = new Set(secretEnvNames(env));
127
+ return Object.fromEntries(Object.entries(env || {}).filter(([k]) => !drop.has(k)));
128
+ }
129
+
130
+ // ---- verification status ---------------------------------------------------
131
+
132
+ // Mirrors the PRD state model. Only this module decides how a status is formed
133
+ // from a boundary run, and it never reads target output.
134
+ export const VERIFICATION_STATUSES = Object.freeze(
135
+ ['not-run', 'unsupported', 'inconclusive', 'error', 'refuted', 'confirmed'],
136
+ );
137
+
138
+ /**
139
+ * Status from what the BOUNDARY observed (did it run, did it error). A run on
140
+ * its own can never confirm anything: that takes verifier-observed evidence
141
+ * (`settleVerification`).
142
+ */
143
+ export function classifyRun(run) {
144
+ if (!run || run.executed !== true) return 'not-run';
145
+ if (run.status === 'error') return 'error';
146
+ return 'inconclusive';
147
+ }
148
+
149
+ /**
150
+ * Settle a verification status. `evidence` must come from verifier-domain code
151
+ * (`observedBy: 'verifier'`) that examined state the target cannot write (for
152
+ * example by re-running the oracle outside the target's reach). Target stdout,
153
+ * stderr and workspace files are NOT evidence. `confirmed` is only reachable
154
+ * from an executed run plus satisfied verifier evidence; `refuted` needs the
155
+ * oracle to declare its preconditions held.
156
+ */
157
+ export function settleVerification(run, evidence) {
158
+ const base = classifyRun(run);
159
+ if (base !== 'inconclusive') return base;
160
+ if (!evidence || evidence.observedBy !== DOMAINS.VERIFIER) return base;
161
+ if (evidence.satisfied === true) return 'confirmed';
162
+ if (evidence.satisfied === false && evidence.preconditionsHeld === true) return 'refuted';
163
+ return base;
164
+ }
165
+
166
+ const STATUS_LIKE = /\b(?:verified|confirmed|execution-proven|status\s*[:=])\b/i;
167
+
168
+ /** Count of target-output lines that merely LOOK like a status claim (informational). */
169
+ export function countStatusLikeLines(text) {
170
+ return String(text || '').split('\n').filter((l) => STATUS_LIKE.test(l)).length;
171
+ }