@quantakrypto/core 0.2.2 → 0.4.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 (173) hide show
  1. package/dist/agent-types.d.ts +48 -0
  2. package/dist/agent-types.d.ts.map +1 -0
  3. package/dist/agent-types.js +2 -0
  4. package/dist/agent-types.js.map +1 -0
  5. package/dist/cache.d.ts +27 -0
  6. package/dist/cache.d.ts.map +1 -0
  7. package/dist/cache.js +93 -0
  8. package/dist/cache.js.map +1 -0
  9. package/dist/cbom.d.ts.map +1 -1
  10. package/dist/cbom.js +26 -1
  11. package/dist/cbom.js.map +1 -1
  12. package/dist/changed.d.ts.map +1 -1
  13. package/dist/changed.js +14 -2
  14. package/dist/changed.js.map +1 -1
  15. package/dist/codemods/config-toggle.d.ts +3 -0
  16. package/dist/codemods/config-toggle.d.ts.map +1 -0
  17. package/dist/codemods/config-toggle.js +26 -0
  18. package/dist/codemods/config-toggle.js.map +1 -0
  19. package/dist/codemods/registry.d.ts +26 -0
  20. package/dist/codemods/registry.d.ts.map +1 -0
  21. package/dist/codemods/registry.js +8 -0
  22. package/dist/codemods/registry.js.map +1 -0
  23. package/dist/comments.d.ts +45 -0
  24. package/dist/comments.d.ts.map +1 -0
  25. package/dist/comments.js +164 -0
  26. package/dist/comments.js.map +1 -0
  27. package/dist/config.d.ts +1 -1
  28. package/dist/config.d.ts.map +1 -1
  29. package/dist/config.js +7 -0
  30. package/dist/config.js.map +1 -1
  31. package/dist/dependencies.d.ts +31 -13
  32. package/dist/dependencies.d.ts.map +1 -1
  33. package/dist/dependencies.js +460 -40
  34. package/dist/dependencies.js.map +1 -1
  35. package/dist/detect-utils.d.ts +70 -2
  36. package/dist/detect-utils.d.ts.map +1 -1
  37. package/dist/detect-utils.js +139 -17
  38. package/dist/detect-utils.js.map +1 -1
  39. package/dist/detectors/c.d.ts +20 -0
  40. package/dist/detectors/c.d.ts.map +1 -0
  41. package/dist/detectors/c.js +104 -0
  42. package/dist/detectors/c.js.map +1 -0
  43. package/dist/detectors/csharp.d.ts +15 -0
  44. package/dist/detectors/csharp.d.ts.map +1 -0
  45. package/dist/detectors/csharp.js +76 -0
  46. package/dist/detectors/csharp.js.map +1 -0
  47. package/dist/detectors/go.d.ts +25 -0
  48. package/dist/detectors/go.d.ts.map +1 -0
  49. package/dist/detectors/go.js +132 -0
  50. package/dist/detectors/go.js.map +1 -0
  51. package/dist/detectors/java.d.ts +25 -0
  52. package/dist/detectors/java.d.ts.map +1 -0
  53. package/dist/detectors/java.js +200 -0
  54. package/dist/detectors/java.js.map +1 -0
  55. package/dist/detectors/pem.d.ts +4 -0
  56. package/dist/detectors/pem.d.ts.map +1 -1
  57. package/dist/detectors/pem.js +113 -91
  58. package/dist/detectors/pem.js.map +1 -1
  59. package/dist/detectors/python.d.ts +26 -0
  60. package/dist/detectors/python.d.ts.map +1 -0
  61. package/dist/detectors/python.js +171 -0
  62. package/dist/detectors/python.js.map +1 -0
  63. package/dist/detectors/ruby.d.ts +15 -0
  64. package/dist/detectors/ruby.d.ts.map +1 -0
  65. package/dist/detectors/ruby.js +75 -0
  66. package/dist/detectors/ruby.js.map +1 -0
  67. package/dist/detectors/rust.d.ts +13 -0
  68. package/dist/detectors/rust.d.ts.map +1 -0
  69. package/dist/detectors/rust.js +94 -0
  70. package/dist/detectors/rust.js.map +1 -0
  71. package/dist/detectors/source.d.ts +9 -2
  72. package/dist/detectors/source.d.ts.map +1 -1
  73. package/dist/detectors/source.js +435 -286
  74. package/dist/detectors/source.js.map +1 -1
  75. package/dist/index.d.ts +19 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +16 -2
  78. package/dist/index.js.map +1 -1
  79. package/dist/parallel.d.ts +4 -0
  80. package/dist/parallel.d.ts.map +1 -1
  81. package/dist/parallel.js +61 -8
  82. package/dist/parallel.js.map +1 -1
  83. package/dist/patch-policy.d.ts +22 -0
  84. package/dist/patch-policy.d.ts.map +1 -0
  85. package/dist/patch-policy.js +21 -0
  86. package/dist/patch-policy.js.map +1 -0
  87. package/dist/redact.d.ts +19 -0
  88. package/dist/redact.d.ts.map +1 -0
  89. package/dist/redact.js +77 -0
  90. package/dist/redact.js.map +1 -0
  91. package/dist/registry.d.ts +29 -4
  92. package/dist/registry.d.ts.map +1 -1
  93. package/dist/registry.js +62 -4
  94. package/dist/registry.js.map +1 -1
  95. package/dist/remediate-pipeline.d.ts +41 -0
  96. package/dist/remediate-pipeline.d.ts.map +1 -0
  97. package/dist/remediate-pipeline.js +38 -0
  98. package/dist/remediate-pipeline.js.map +1 -0
  99. package/dist/remediate-request.d.ts +21 -0
  100. package/dist/remediate-request.d.ts.map +1 -0
  101. package/dist/remediate-request.js +28 -0
  102. package/dist/remediate-request.js.map +1 -0
  103. package/dist/remediation.d.ts +10 -0
  104. package/dist/remediation.d.ts.map +1 -1
  105. package/dist/remediation.js +21 -8
  106. package/dist/remediation.js.map +1 -1
  107. package/dist/report.d.ts +9 -1
  108. package/dist/report.d.ts.map +1 -1
  109. package/dist/report.js +72 -24
  110. package/dist/report.js.map +1 -1
  111. package/dist/scan-worker.js +7 -3
  112. package/dist/scan-worker.js.map +1 -1
  113. package/dist/scan.d.ts +6 -5
  114. package/dist/scan.d.ts.map +1 -1
  115. package/dist/scan.js +59 -30
  116. package/dist/scan.js.map +1 -1
  117. package/dist/triage.d.ts +27 -0
  118. package/dist/triage.d.ts.map +1 -0
  119. package/dist/triage.js +33 -0
  120. package/dist/triage.js.map +1 -0
  121. package/dist/types.d.ts +106 -3
  122. package/dist/types.d.ts.map +1 -1
  123. package/dist/verify.d.ts +30 -0
  124. package/dist/verify.d.ts.map +1 -0
  125. package/dist/verify.js +65 -0
  126. package/dist/verify.js.map +1 -0
  127. package/dist/version.d.ts +1 -1
  128. package/dist/version.js +1 -1
  129. package/dist/walk.d.ts +7 -0
  130. package/dist/walk.d.ts.map +1 -1
  131. package/dist/walk.js +85 -11
  132. package/dist/walk.js.map +1 -1
  133. package/dist/worktree.d.ts +6 -0
  134. package/dist/worktree.d.ts.map +1 -0
  135. package/dist/worktree.js +43 -0
  136. package/dist/worktree.js.map +1 -0
  137. package/package.json +1 -1
  138. package/src/agent-types.ts +52 -0
  139. package/src/cache.ts +120 -0
  140. package/src/cbom.ts +27 -1
  141. package/src/changed.ts +13 -4
  142. package/src/codemods/config-toggle.ts +35 -0
  143. package/src/codemods/registry.ts +31 -0
  144. package/src/comments.ts +180 -0
  145. package/src/config.ts +8 -0
  146. package/src/dependencies.ts +483 -51
  147. package/src/detect-utils.ts +180 -16
  148. package/src/detectors/c.ts +132 -0
  149. package/src/detectors/csharp.ts +98 -0
  150. package/src/detectors/go.ts +167 -0
  151. package/src/detectors/java.ts +235 -0
  152. package/src/detectors/pem.ts +124 -105
  153. package/src/detectors/python.ts +212 -0
  154. package/src/detectors/ruby.ts +97 -0
  155. package/src/detectors/rust.ts +112 -0
  156. package/src/detectors/source.ts +535 -364
  157. package/src/index.ts +47 -2
  158. package/src/parallel.ts +72 -7
  159. package/src/patch-policy.ts +42 -0
  160. package/src/redact.ts +92 -0
  161. package/src/registry.ts +71 -5
  162. package/src/remediate-pipeline.ts +81 -0
  163. package/src/remediate-request.ts +52 -0
  164. package/src/remediation.ts +27 -11
  165. package/src/report.ts +106 -24
  166. package/src/scan-worker.ts +18 -7
  167. package/src/scan.ts +74 -29
  168. package/src/triage.ts +58 -0
  169. package/src/types.ts +120 -3
  170. package/src/verify.ts +82 -0
  171. package/src/version.ts +1 -1
  172. package/src/walk.ts +81 -12
  173. package/src/worktree.ts +45 -0
package/dist/walk.js CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { readdir, stat } from "node:fs/promises";
8
8
  import * as path from "node:path";
9
+ import { isManifestFile } from "./dependencies.js";
9
10
  /** Directories ignored by default (can be disabled with noDefaultIgnores). */
10
11
  export const DEFAULT_IGNORES = [
11
12
  "node_modules",
@@ -95,13 +96,86 @@ const BINARY_EXTENSIONS = new Set([
95
96
  export function toPosix(p) {
96
97
  return p.split(path.sep).join("/");
97
98
  }
98
- /** True if `rel` (a POSIX relative path) matches any pattern (substring/prefix). */
99
- function matchesAny(rel, patterns) {
99
+ /** A pattern is treated as a glob when it contains one of these metacharacters. */
100
+ function hasGlobMeta(pattern) {
101
+ return /[*?[]/.test(pattern);
102
+ }
103
+ /**
104
+ * Translate a glob into an anchored RegExp: `*` matches within a path segment
105
+ * (not `/`), `**` matches across segments, a leading `**` before a slash is an
106
+ * optional path prefix, `?` matches a single non-`/` char, `[...]` is a
107
+ * character class. Other regex
108
+ * metacharacters are escaped.
109
+ */
110
+ function globToRegExp(glob) {
111
+ let re = "";
112
+ for (let i = 0; i < glob.length; i++) {
113
+ const c = glob[i];
114
+ if (c === "*") {
115
+ if (glob[i + 1] === "*") {
116
+ i++; // consume the second '*'
117
+ if (glob[i + 1] === "/") {
118
+ i++; // consume the trailing '/'
119
+ re += "(?:.*/)?"; // zero or more path segments
120
+ }
121
+ else {
122
+ re += ".*"; // '**' spanning segments
123
+ }
124
+ }
125
+ else {
126
+ re += "[^/]*"; // '*' within a segment
127
+ }
128
+ }
129
+ else if (c === "?") {
130
+ re += "[^/]";
131
+ }
132
+ else if (c === "[") {
133
+ // Pass a character class through; find its closing ']'.
134
+ const end = glob.indexOf("]", i + 1);
135
+ if (end === -1) {
136
+ re += "\\[";
137
+ }
138
+ else {
139
+ re += glob.slice(i, end + 1);
140
+ i = end;
141
+ }
142
+ }
143
+ else if ("\\^$.|+(){}".includes(c)) {
144
+ re += "\\" + c;
145
+ }
146
+ else {
147
+ re += c;
148
+ }
149
+ }
150
+ return new RegExp(`^${re}$`);
151
+ }
152
+ /** Memoized glob→RegExp so a pattern is compiled once, not once per file. */
153
+ const GLOB_CACHE = new Map();
154
+ function globRegExp(pattern) {
155
+ let re = GLOB_CACHE.get(pattern);
156
+ if (!re) {
157
+ re = globToRegExp(pattern);
158
+ GLOB_CACHE.set(pattern, re);
159
+ }
160
+ return re;
161
+ }
162
+ /**
163
+ * True if `rel` (a POSIX relative path) matches any pattern. A pattern with a
164
+ * glob metacharacter (`*`, `?`, `[`) is matched as an anchored glob; a plain
165
+ * pattern keeps the historical substring / path-prefix semantics (so `"src"`
166
+ * still matches `src/a.ts` and `"secrets"` matches anywhere).
167
+ */
168
+ export function matchesAny(rel, patterns) {
100
169
  for (const pattern of patterns) {
101
170
  if (!pattern)
102
171
  continue;
103
172
  const p = toPosix(pattern).replace(/\/+$/, "");
104
- // Substring match (handles "src/legacy" or "secrets")...
173
+ if (hasGlobMeta(p)) {
174
+ if (globRegExp(p).test(rel))
175
+ return true;
176
+ continue;
177
+ }
178
+ // Plain pattern: substring match (handles "src/legacy" or "secrets")...
105
179
  if (rel.includes(p))
106
180
  return true;
107
181
  // ...and explicit path-prefix match ("foo" should match "foo/bar.ts").
@@ -200,15 +274,12 @@ export async function* walkFiles(root, options = {}) {
200
274
  * scanned for vulnerable dependencies instead of being silently dropped.
201
275
  */
202
276
  function passesSizeLimit(rel, size, maxFileSize) {
203
- if (isManifestPath(rel))
277
+ // Dependency manifests are always read (they can exceed the size cap but carry
278
+ // the whole dependency tree). Uses the single {@link isManifestFile} definition.
279
+ if (isManifestFile(rel))
204
280
  return true;
205
281
  return size <= maxFileSize;
206
282
  }
207
- /** True if the path's basename is a dependency manifest we always read. */
208
- function isManifestPath(rel) {
209
- const base = rel.split("/").pop() ?? rel;
210
- return base === "package.json" || base === "package-lock.json";
211
- }
212
283
  /** Internal recursive directory walker. `relDir` is POSIX-relative to the root. */
213
284
  async function* walkDir(absDir, relDir, ctx) {
214
285
  let entries;
@@ -242,9 +313,12 @@ async function* walkDir(absDir, relDir, ctx) {
242
313
  continue;
243
314
  if (!isIncluded(rel, ctx.include))
244
315
  continue;
245
- if (isBinaryPath(rel))
316
+ // Dependency manifests (incl. yarn.lock / pnpm-lock.yaml) are always read —
317
+ // they carry the dependency tree and must not be dropped as binary/generated.
318
+ const manifest = isManifestFile(rel);
319
+ if (!manifest && isBinaryPath(rel))
246
320
  continue;
247
- if (isGeneratedPath(rel))
321
+ if (!manifest && isGeneratedPath(rel))
248
322
  continue;
249
323
  try {
250
324
  const s = await stat(abs);
package/dist/walk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"walk.js","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"walk.js","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Create a detached worktree of `repoRoot` at HEAD, run `fn` with its path, and
3
+ * always tear it down. Throws if `repoRoot` is not a git repository.
4
+ */
5
+ export declare function withWorktree<T>(repoRoot: string, fn: (dir: string) => Promise<T>): Promise<T>;
6
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9B,OAAO,CAAC,CAAC,CAAC,CAmBZ"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Ephemeral git worktree runner. Remediation applies candidate patches inside a
3
+ * throwaway `git worktree` checked out at HEAD, so the user's working tree is
4
+ * never touched while patches are being tried and verified. The worktree is
5
+ * always removed afterwards, even if the callback throws.
6
+ */
7
+ import { execFile } from "node:child_process";
8
+ import { promisify } from "node:util";
9
+ import { mkdtemp, rm } from "node:fs/promises";
10
+ import { tmpdir } from "node:os";
11
+ import { join } from "node:path";
12
+ const exec = promisify(execFile);
13
+ async function git(args, cwd) {
14
+ await exec("git", args, { cwd });
15
+ }
16
+ /**
17
+ * Create a detached worktree of `repoRoot` at HEAD, run `fn` with its path, and
18
+ * always tear it down. Throws if `repoRoot` is not a git repository.
19
+ */
20
+ export async function withWorktree(repoRoot, fn) {
21
+ try {
22
+ await git(["rev-parse", "--is-inside-work-tree"], repoRoot);
23
+ }
24
+ catch {
25
+ throw new Error(`withWorktree: "${repoRoot}" is not a git repository`);
26
+ }
27
+ const base = await mkdtemp(join(tmpdir(), "quantakrypto-wt-"));
28
+ const dir = join(base, "wt");
29
+ await git(["worktree", "add", "--detach", dir], repoRoot);
30
+ try {
31
+ return await fn(dir);
32
+ }
33
+ finally {
34
+ try {
35
+ await git(["worktree", "remove", "--force", dir], repoRoot);
36
+ }
37
+ catch {
38
+ // best effort — the temp dir removal below still reclaims the disk.
39
+ }
40
+ await rm(base, { recursive: true, force: true });
41
+ }
42
+ }
43
+ //# sourceMappingURL=worktree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.js","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEjC,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,GAAY;IAC7C,MAAM,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,EAA+B;IAE/B,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,kBAAkB,QAAQ,2BAA2B,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7B,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1D,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantakrypto/core",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "description": "Shared post-quantum readiness library: crypto detectors, vulnerable-dependency database, inventory + SARIF reporting. Zero runtime dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Dandelion Labs <hello@dandelionlabs.io> (https://dandelionlabs.io)",
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Shared types for the agent (BYOK) plane. These live in `@quantakrypto/core`
3
+ * (offline) so both the deterministic MCP tools and the networked
4
+ * `@quantakrypto/agent` package speak the same shapes without the offline side
5
+ * ever importing the network client.
6
+ */
7
+ import type { Severity, TriageAnnotation } from "./types.js";
8
+
9
+ /** How much source context a redacted request carries. */
10
+ export type ContextLevel = "metadata" | "snippet" | "function" | "file";
11
+
12
+ /** A finding's context, redacted to a {@link ContextLevel} and secret-stripped. */
13
+ export interface RedactedContext {
14
+ level: ContextLevel;
15
+ meta: {
16
+ ruleId: string;
17
+ algorithm?: string;
18
+ severity: Severity;
19
+ hndl: boolean;
20
+ file: string;
21
+ line: number;
22
+ message: string;
23
+ };
24
+ /** Redacted source, or null at `metadata` level / for a `sensitive` finding. */
25
+ code: string | null;
26
+ /** True when key material was stripped from the context. */
27
+ redactedSecret: boolean;
28
+ }
29
+
30
+ /** An LLM triage verdict for a single finding (never suppresses it). The
31
+ * exposure/priority/rationale body is the {@link TriageAnnotation} that gets
32
+ * attached to the finding; `fingerprint` links it back to that finding. */
33
+ export interface TriageVerdict extends TriageAnnotation {
34
+ fingerprint: string;
35
+ }
36
+
37
+ /** A concrete proposed edit: the full new content for a single file. */
38
+ export interface Patch {
39
+ path: string;
40
+ /** Full replacement content for `path` after the fix. */
41
+ newContent: string;
42
+ ruleId: string;
43
+ source: "codemod" | "llm";
44
+ }
45
+
46
+ /** An LLM-proposed fix before it enters the deterministic pipeline. */
47
+ export interface FixProposal {
48
+ fingerprint: string;
49
+ path: string;
50
+ newContent: string;
51
+ explanation: string;
52
+ }
package/src/cache.ts ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Optional on-disk scan cache. Keyed by file content hash so an unchanged file
3
+ * reuses its previous findings instead of re-running every detector — the big
4
+ * win on large monorepos where most files don't change between runs.
5
+ *
6
+ * Invalidation is conservative and whole-cache: the cache stores a RULESET
7
+ * FINGERPRINT (tool version + the active detector ids + disabled rules). If any
8
+ * of those differ from the current run, the entire cache is discarded and
9
+ * rebuilt, so upgrading the tool or changing the rules never serves stale
10
+ * results. Per file, a content-hash mismatch re-scans just that file.
11
+ *
12
+ * The cache is opt-in (`ScanOptions.cacheFile`); with no cache file, scans are
13
+ * exactly as before. A corrupt / unreadable / wrong-version cache file is
14
+ * ignored (treated as empty), never fatal.
15
+ */
16
+ import { createHash } from "node:crypto";
17
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
18
+ import * as path from "node:path";
19
+
20
+ import type { Detector, Finding } from "./types.js";
21
+ import { VERSION } from "./version.js";
22
+
23
+ const CACHE_VERSION = 1;
24
+
25
+ /** One cached file: the content hash it was computed for, and its findings. */
26
+ export interface CacheEntry {
27
+ hash: string;
28
+ findings: Finding[];
29
+ }
30
+
31
+ interface CacheFileShape {
32
+ version: number;
33
+ ruleset: string;
34
+ entries: Record<string, CacheEntry>;
35
+ }
36
+
37
+ /** sha256 of a file's content (hex). */
38
+ export function hashContent(content: string): string {
39
+ return createHash("sha256").update(content, "utf8").digest("hex");
40
+ }
41
+
42
+ /**
43
+ * Fingerprint of everything that changes what a scan produces: the tool version,
44
+ * the active detector ids (sorted), and the disabled-rule set (sorted). A change
45
+ * to any of these invalidates the whole cache.
46
+ */
47
+ export function rulesetFingerprint(
48
+ detectors: readonly Detector[],
49
+ disabledRules: readonly string[] | undefined,
50
+ ): string {
51
+ const ids = detectors.map((d) => d.id).sort();
52
+ const disabled = [...(disabledRules ?? [])].sort();
53
+ return `v${VERSION}|d:${ids.join(",")}|x:${disabled.join(",")}`;
54
+ }
55
+
56
+ /**
57
+ * Load the cache file into a `Map<relPath, CacheEntry>`. Returns an empty map
58
+ * when the file is missing, unparseable, the wrong version, or was written for a
59
+ * different ruleset (in which case its entries are stale and must not be reused).
60
+ */
61
+ export async function loadCache(
62
+ cacheFile: string,
63
+ ruleset: string,
64
+ ): Promise<Map<string, CacheEntry>> {
65
+ let raw: string;
66
+ try {
67
+ raw = await readFile(cacheFile, "utf8");
68
+ } catch {
69
+ return new Map();
70
+ }
71
+ let parsed: CacheFileShape;
72
+ try {
73
+ parsed = JSON.parse(raw) as CacheFileShape;
74
+ } catch {
75
+ return new Map();
76
+ }
77
+ if (
78
+ parsed === null ||
79
+ typeof parsed !== "object" ||
80
+ parsed.version !== CACHE_VERSION ||
81
+ parsed.ruleset !== ruleset ||
82
+ typeof parsed.entries !== "object" ||
83
+ parsed.entries === null
84
+ ) {
85
+ return new Map();
86
+ }
87
+ const map = new Map<string, CacheEntry>();
88
+ for (const [file, entry] of Object.entries(parsed.entries)) {
89
+ if (entry && typeof entry.hash === "string" && Array.isArray(entry.findings)) {
90
+ map.set(file, entry);
91
+ }
92
+ }
93
+ return map;
94
+ }
95
+
96
+ /**
97
+ * Write the cache atomically (temp file + rename) so a concurrent reader never
98
+ * sees a half-written file. Errors are swallowed — a cache is an optimization,
99
+ * never a reason to fail a scan.
100
+ */
101
+ export async function saveCache(
102
+ cacheFile: string,
103
+ ruleset: string,
104
+ entries: Map<string, CacheEntry>,
105
+ ): Promise<void> {
106
+ const doc: CacheFileShape = {
107
+ version: CACHE_VERSION,
108
+ ruleset,
109
+ entries: Object.fromEntries(entries),
110
+ };
111
+ try {
112
+ await mkdir(path.dirname(cacheFile), { recursive: true });
113
+ const tmp = `${cacheFile}.tmp-${process.pid}`;
114
+ await writeFile(tmp, JSON.stringify(doc), "utf8");
115
+ const { rename } = await import("node:fs/promises");
116
+ await rename(tmp, cacheFile);
117
+ } catch {
118
+ // best effort
119
+ }
120
+ }
package/src/cbom.ts CHANGED
@@ -56,6 +56,32 @@ function isQuantumVulnerable(algorithm: AlgorithmFamily): boolean {
56
56
  return algorithm !== "unknown";
57
57
  }
58
58
 
59
+ /**
60
+ * Approximate CLASSICAL security strength (bits) of the common parameterisation
61
+ * of a classical family — RSA-2048 / DH-2048 ≈ 112-bit, 256-bit curves ≈ 128-bit,
62
+ * X448 ≈ 224-bit. (The QUANTUM level is 0 for all of these: Shor breaks them.)
63
+ * 0 when the family is unknown. Reported so a CBOM doesn't imply these primitives
64
+ * have zero classical strength today.
65
+ */
66
+ function classicalSecurityLevelFor(algorithm: AlgorithmFamily): number {
67
+ switch (algorithm) {
68
+ case "RSA":
69
+ case "DH":
70
+ case "DSA":
71
+ return 112;
72
+ case "ECDH":
73
+ case "ECDSA":
74
+ case "EdDSA":
75
+ case "X25519":
76
+ case "ECIES":
77
+ return 128;
78
+ case "X448":
79
+ return 224;
80
+ default:
81
+ return 0;
82
+ }
83
+ }
84
+
59
85
  /** Deterministic bom-ref for a (algorithm, primitive) asset key. */
60
86
  function bomRef(key: string): string {
61
87
  return `crypto:${createHash("sha256").update(key, "utf8").digest("hex").slice(0, 16)}`;
@@ -107,7 +133,7 @@ export function toCbom(result: ScanResult): CycloneDxBom {
107
133
  primitive: g.primitive,
108
134
  parameterSetIdentifier: g.algorithm,
109
135
  executionEnvironment: "software-plain-ram",
110
- classicalSecurityLevel: 0,
136
+ classicalSecurityLevel: classicalSecurityLevelFor(g.algorithm),
111
137
  nistQuantumSecurityLevel: 0,
112
138
  cryptoFunctions:
113
139
  g.primitive === "signature"
package/src/changed.ts CHANGED
@@ -53,11 +53,20 @@ export async function changedFiles(root: string, since?: string): Promise<string
53
53
  // than repo-root-relative, so `scan()` can join them against a sub-directory
54
54
  // root. Without it, a `--changed` scan of a subdirectory resolves nothing.
55
55
  if (since) {
56
- for (const f of toLines(
57
- await git(root, ["diff", "--name-only", "--relative", "--diff-filter=ACMR", since]),
58
- )) {
59
- out.add(f);
56
+ // A `git diff` against `since` returns null ONLY when the command failed —
57
+ // almost always an unknown ref/range (a typo like `--since maiin`). Surface
58
+ // it instead of silently scanning just the uncommitted files and passing CI.
59
+ const diff = await git(root, [
60
+ "diff",
61
+ "--name-only",
62
+ "--relative",
63
+ "--diff-filter=ACMR",
64
+ since,
65
+ ]);
66
+ if (diff === null) {
67
+ throw new Error(`--since: git could not diff against "${since}" (unknown ref or range).`);
60
68
  }
69
+ for (const f of toLines(diff)) out.add(f);
61
70
  }
62
71
 
63
72
  // Always include local uncommitted edits (staged + unstaged), filtered to ACMR.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Config-toggle codemod: mechanical, unambiguous fixes for insecure TLS config.
3
+ * Both target rules have a single correct replacement, so the fix is
4
+ * deterministic and clears the finding (verified by the pipeline's gate).
5
+ *
6
+ * - `tls-legacy-version` — bump a pinned TLS 1.0/1.1 to TLS 1.3.
7
+ * - `tls-reject-unauthorized` — turn certificate verification back on.
8
+ */
9
+ import type { Finding } from "../types.js";
10
+ import type { Patch } from "../agent-types.js";
11
+ import type { Codemod } from "./registry.js";
12
+
13
+ export const configToggleCodemod: Codemod = {
14
+ id: "config-toggle",
15
+ applies(finding: Finding): boolean {
16
+ return finding.ruleId === "tls-legacy-version" || finding.ruleId === "tls-reject-unauthorized";
17
+ },
18
+ apply(content: string, finding: Finding): Patch | null {
19
+ let out = content;
20
+ if (finding.ruleId === "tls-legacy-version") {
21
+ out = out
22
+ .replace(/((?:minVersion|maxVersion)\s*:\s*['"`])TLSv1(?:\.1)?(['"`])/g, "$1TLSv1.3$2")
23
+ .replace(/(secureProtocol\s*:\s*['"`])TLSv1(?:_1)?_method(['"`])/g, "$1TLSv1_3_method$2");
24
+ } else if (finding.ruleId === "tls-reject-unauthorized") {
25
+ out = out.replace(/(rejectUnauthorized\s*:\s*)false/g, "$1true");
26
+ }
27
+ if (out === content) return null;
28
+ return {
29
+ path: finding.location.file,
30
+ newContent: out,
31
+ ruleId: finding.ruleId,
32
+ source: "codemod",
33
+ };
34
+ },
35
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Codemod registry — deterministic, template-able fixes keyed by finding.
3
+ *
4
+ * A codemod only earns a place here if its output reliably CLEARS the finding
5
+ * (the remediation pipeline enforces this with the `verify_fix` gate). That
6
+ * makes the set deliberately small: mechanical config toggles qualify;
7
+ * dependency swaps and source crypto rewrites generally do NOT (there is no
8
+ * safe drop-in replacement, and a manifest fix can't "remove" the finding
9
+ * without deleting the dependency) — those are left to triage + the LLM
10
+ * remediation layer, not an auto-codemod.
11
+ */
12
+ import type { Finding } from "../types.js";
13
+ import type { Patch } from "../agent-types.js";
14
+ import { configToggleCodemod } from "./config-toggle.js";
15
+
16
+ /** A deterministic fix for a class of findings. */
17
+ export interface Codemod {
18
+ id: string;
19
+ /** True when this codemod can produce a deterministic fix for the finding. */
20
+ applies(finding: Finding): boolean;
21
+ /** Produce a patch (full new file content), or null if it changed nothing. */
22
+ apply(content: string, finding: Finding): Patch | null;
23
+ }
24
+
25
+ /** All registered codemods, in priority order. */
26
+ export const codemodRegistry: Codemod[] = [configToggleCodemod];
27
+
28
+ /** The first codemod that applies to `finding`, or undefined. */
29
+ export function codemodFor(finding: Finding): Codemod | undefined {
30
+ return codemodRegistry.find((c) => c.applies(finding));
31
+ }