@quantakrypto/qscan 0.3.0 → 0.4.1
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/README.md +14 -0
- package/dist/args.d.ts +28 -1
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +60 -0
- package/dist/args.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -0
- package/dist/config.js.map +1 -1
- package/dist/help.d.ts +1 -1
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +14 -0
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -2
- package/dist/index.js.map +1 -1
- package/dist/remediate-bin.d.ts +3 -0
- package/dist/remediate-bin.d.ts.map +1 -0
- package/dist/remediate-bin.js +59 -0
- package/dist/remediate-bin.js.map +1 -0
- package/dist/remediate-cli.d.ts +67 -0
- package/dist/remediate-cli.d.ts.map +1 -0
- package/dist/remediate-cli.js +315 -0
- package/dist/remediate-cli.js.map +1 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +46 -4
- package/dist/report.js.map +1 -1
- package/dist/triage-run.d.ts +29 -0
- package/dist/triage-run.d.ts.map +1 -0
- package/dist/triage-run.js +98 -0
- package/dist/triage-run.js.map +1 -0
- package/package.json +5 -3
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Finding, Patch, ScanResult } from "@quantakrypto/core";
|
|
2
|
+
import type { LlmProvider } from "./args.js";
|
|
3
|
+
export type RemediateMode = "diff" | "apply" | "pr";
|
|
4
|
+
export interface RemediateOptions {
|
|
5
|
+
path: string;
|
|
6
|
+
mode: RemediateMode;
|
|
7
|
+
/** Use a BYOK LLM to propose fixes codemods can't. */
|
|
8
|
+
llm: boolean;
|
|
9
|
+
provider?: LlmProvider;
|
|
10
|
+
model?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RemediateRun {
|
|
13
|
+
output: string;
|
|
14
|
+
exitCode: number;
|
|
15
|
+
/** Relative paths written (apply mode) or included in the PR. */
|
|
16
|
+
written: string[];
|
|
17
|
+
}
|
|
18
|
+
/** A verified fix set ready to become a draft PR. */
|
|
19
|
+
export interface DraftPrPlan {
|
|
20
|
+
branch: string;
|
|
21
|
+
title: string;
|
|
22
|
+
body: string;
|
|
23
|
+
patches: {
|
|
24
|
+
path: string;
|
|
25
|
+
newContent: string;
|
|
26
|
+
}[];
|
|
27
|
+
}
|
|
28
|
+
/** Open a draft PR for the plan (injectable; default shells git + gh in a worktree). */
|
|
29
|
+
export type OpenDraftPr = (plan: DraftPrPlan) => Promise<{
|
|
30
|
+
url?: string;
|
|
31
|
+
}>;
|
|
32
|
+
export interface RemediateHooks {
|
|
33
|
+
scanFn?: (root: string) => Promise<ScanResult>;
|
|
34
|
+
readFile?: (abs: string) => Promise<string>;
|
|
35
|
+
writeFile?: (abs: string, content: string) => Promise<void>;
|
|
36
|
+
/** LLM patch source (default wraps `@quantakrypto/agent`'s proposeFix). */
|
|
37
|
+
llmPatchSource?: (finding: Finding, content: string) => Promise<Patch | null>;
|
|
38
|
+
/** Draft-PR backend (default: git worktree + gh). */
|
|
39
|
+
openDraftPr?: OpenDraftPr;
|
|
40
|
+
resolveKey?: () => string | undefined;
|
|
41
|
+
stderr?: (s: string) => void;
|
|
42
|
+
/** Branch suffix (injected for deterministic tests). */
|
|
43
|
+
branchSuffix?: string;
|
|
44
|
+
}
|
|
45
|
+
export declare const REMEDIATE_EXIT: {
|
|
46
|
+
readonly OK: 0;
|
|
47
|
+
readonly CHANGES: 0;
|
|
48
|
+
readonly ERROR: 2;
|
|
49
|
+
};
|
|
50
|
+
/** Minimal unified diff for a localized change (3 lines of context). */
|
|
51
|
+
export declare function unifiedDiff(relPath: string, before: string, after: string): string;
|
|
52
|
+
/** Run a complete qremediate pass. Pure w.r.t. process; the bin prints + exits. */
|
|
53
|
+
export declare function runRemediate(options: RemediateOptions, hooks?: RemediateHooks): Promise<RemediateRun>;
|
|
54
|
+
/** Parse qremediate argv. */
|
|
55
|
+
export declare function parseRemediateArgs(argv: readonly string[]): {
|
|
56
|
+
kind: "run";
|
|
57
|
+
options: RemediateOptions;
|
|
58
|
+
} | {
|
|
59
|
+
kind: "help";
|
|
60
|
+
} | {
|
|
61
|
+
kind: "version";
|
|
62
|
+
} | {
|
|
63
|
+
kind: "error";
|
|
64
|
+
message: string;
|
|
65
|
+
};
|
|
66
|
+
export declare const REMEDIATE_HELP = "qremediate \u2014 apply deterministic, verified fixes for insecure crypto findings\n\nUSAGE\n qremediate [path] [--mode diff|apply|pr] [--llm] [--llm-provider <p>] [--llm-model <m>]\n\nOPTIONS\n --mode diff Print a unified diff of every verified fix (default; writes nothing)\n --mode apply Write verified fixes into the working tree\n --mode pr Commit verified fixes to a new branch and open a DRAFT PR (never merges)\n --llm Also let a BYOK LLM propose fixes codemods can't (needs an API key)\n --llm-provider anthropic | openai-compatible (default: anthropic)\n --llm-model Model id for the BYOK provider\n -h, --help Show this help\n -v, --version Show version\n\nEvery fix must pass the verify_fix gate (the finding is gone, no new finding) and\nthe patch policy (only files with findings + dependency manifests). Never merges.\n";
|
|
67
|
+
//# sourceMappingURL=remediate-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediate-cli.d.ts","sourceRoot":"","sources":["../src/remediate-cli.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAgC,MAAM,oBAAoB,CAAC;AAEnG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;IACpB,sDAAsD;IACtD,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED,wFAAwF;AACxF,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3E,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,2EAA2E;IAC3E,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAC9E,qDAAqD;IACrD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,cAAc;;;;CAA2C,CAAC;AAavE,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAuBlF;AA8DD,mFAAmF;AACnF,wBAAsB,YAAY,CAChC,OAAO,EAAE,gBAAgB,EACzB,KAAK,GAAE,cAAmB,GACzB,OAAO,CAAC,YAAY,CAAC,CAgIvB;AA8BD,6BAA6B;AAC7B,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,GAErB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAmDrC;AAED,eAAO,MAAM,cAAc,22BAiB1B,CAAC"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `qremediate` — apply deterministic, verified fixes to quantum-vulnerable /
|
|
3
|
+
* insecure crypto findings.
|
|
4
|
+
*
|
|
5
|
+
* Pipeline: scan → for each finding, a codemod (then optionally the LLM with
|
|
6
|
+
* `--llm`) proposes a patch → the core remediation pipeline gates it
|
|
7
|
+
* (patch-policy + verify_fix) → verified patches are shown (`diff`), written
|
|
8
|
+
* (`apply`), or opened as a DRAFT PR (`pr`). Never auto-merges.
|
|
9
|
+
*/
|
|
10
|
+
import { readFile as fsReadFile, writeFile as fsWriteFile } from "node:fs/promises";
|
|
11
|
+
import { execFile } from "node:child_process";
|
|
12
|
+
import { promisify } from "node:util";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { scan, codemodFor, remediateFindings, isManifestFile, fingerprintFinding, withWorktree, } from "@quantakrypto/core";
|
|
15
|
+
const exec = promisify(execFile);
|
|
16
|
+
export const REMEDIATE_EXIT = { OK: 0, CHANGES: 0, ERROR: 2 };
|
|
17
|
+
function envKey(provider) {
|
|
18
|
+
return (process.env.QK_LLM_API_KEY ??
|
|
19
|
+
(provider === "anthropic" ? process.env.ANTHROPIC_API_KEY : process.env.OPENAI_API_KEY));
|
|
20
|
+
}
|
|
21
|
+
function defaultModel(provider) {
|
|
22
|
+
return provider === "anthropic" ? "claude-sonnet-5" : "gpt-4o-mini";
|
|
23
|
+
}
|
|
24
|
+
/** Minimal unified diff for a localized change (3 lines of context). */
|
|
25
|
+
export function unifiedDiff(relPath, before, after) {
|
|
26
|
+
if (before === after)
|
|
27
|
+
return "";
|
|
28
|
+
const a = before.split("\n");
|
|
29
|
+
const b = after.split("\n");
|
|
30
|
+
let start = 0;
|
|
31
|
+
while (start < a.length && start < b.length && a[start] === b[start])
|
|
32
|
+
start++;
|
|
33
|
+
let endA = a.length - 1;
|
|
34
|
+
let endB = b.length - 1;
|
|
35
|
+
while (endA >= start && endB >= start && a[endA] === b[endB]) {
|
|
36
|
+
endA--;
|
|
37
|
+
endB--;
|
|
38
|
+
}
|
|
39
|
+
const ctx = 3;
|
|
40
|
+
const from = Math.max(0, start - ctx);
|
|
41
|
+
const toA = Math.min(a.length - 1, endA + ctx);
|
|
42
|
+
const toB = Math.min(b.length - 1, endB + ctx);
|
|
43
|
+
const lines = [`--- a/${relPath}`, `+++ b/${relPath}`];
|
|
44
|
+
lines.push(`@@ -${from + 1},${toA - from + 1} +${from + 1},${toB - from + 1} @@`);
|
|
45
|
+
for (let i = from; i < start; i++)
|
|
46
|
+
lines.push(` ${a[i]}`);
|
|
47
|
+
for (let i = start; i <= endA; i++)
|
|
48
|
+
lines.push(`-${a[i]}`);
|
|
49
|
+
for (let i = start; i <= endB; i++)
|
|
50
|
+
lines.push(`+${b[i]}`);
|
|
51
|
+
for (let i = endA + 1; i <= toA; i++)
|
|
52
|
+
lines.push(` ${a[i]}`);
|
|
53
|
+
return lines.join("\n");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Default draft-PR backend: apply the patches inside an ephemeral worktree
|
|
57
|
+
* (never touching the user's checkout), commit on a new branch, push it, and
|
|
58
|
+
* `gh pr create --draft`. NEVER merges.
|
|
59
|
+
*/
|
|
60
|
+
async function defaultOpenDraftPr(root, plan) {
|
|
61
|
+
return withWorktree(root, async (dir) => {
|
|
62
|
+
await exec("git", ["-C", dir, "checkout", "-b", plan.branch]);
|
|
63
|
+
for (const p of plan.patches) {
|
|
64
|
+
await fsWriteFile(path.resolve(dir, p.path), p.newContent, "utf8");
|
|
65
|
+
}
|
|
66
|
+
await exec("git", ["-C", dir, "add", ...plan.patches.map((p) => p.path)]);
|
|
67
|
+
await exec("git", ["-C", dir, "commit", "-m", plan.title]);
|
|
68
|
+
await exec("git", ["-C", dir, "push", "-u", "origin", plan.branch]);
|
|
69
|
+
const { stdout } = await exec("gh", [
|
|
70
|
+
"pr",
|
|
71
|
+
"create",
|
|
72
|
+
"--draft",
|
|
73
|
+
"--head",
|
|
74
|
+
plan.branch,
|
|
75
|
+
"--title",
|
|
76
|
+
plan.title,
|
|
77
|
+
"--body",
|
|
78
|
+
plan.body,
|
|
79
|
+
], { cwd: dir });
|
|
80
|
+
return { url: stdout.trim() };
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function prBody(patches, rejected, options) {
|
|
84
|
+
const lines = [
|
|
85
|
+
"Automated post-quantum remediation from `qremediate`.",
|
|
86
|
+
"",
|
|
87
|
+
`**${patches.length} fix(es)** — each passed the verify_fix gate (finding gone, no new finding) and the patch policy.`,
|
|
88
|
+
"",
|
|
89
|
+
];
|
|
90
|
+
for (const vp of patches) {
|
|
91
|
+
lines.push(`- \`${vp.patch.path}\` — ${vp.finding.ruleId} (${vp.patch.source})`);
|
|
92
|
+
}
|
|
93
|
+
if (options.llm) {
|
|
94
|
+
lines.push("", `LLM-proposed fixes were included; context shared at the \`file\` level with secrets redacted.`);
|
|
95
|
+
}
|
|
96
|
+
if (rejected.length) {
|
|
97
|
+
lines.push("", `${rejected.length} finding(s) were not auto-fixable and need review.`);
|
|
98
|
+
}
|
|
99
|
+
lines.push("", "This is a **draft** PR and was NOT merged. Review every change before merging.");
|
|
100
|
+
return lines.join("\n");
|
|
101
|
+
}
|
|
102
|
+
/** Run a complete qremediate pass. Pure w.r.t. process; the bin prints + exits. */
|
|
103
|
+
export async function runRemediate(options, hooks = {}) {
|
|
104
|
+
const root = path.resolve(options.path);
|
|
105
|
+
const readFile = hooks.readFile ?? ((abs) => fsReadFile(abs, "utf8"));
|
|
106
|
+
const writeFile = hooks.writeFile ?? ((abs, content) => fsWriteFile(abs, content, "utf8"));
|
|
107
|
+
const scanFn = hooks.scanFn ?? ((r) => scan({ root: r }));
|
|
108
|
+
const stderr = hooks.stderr ?? ((s) => void process.stderr.write(s));
|
|
109
|
+
const result = await scanFn(root);
|
|
110
|
+
const findings = result.findings;
|
|
111
|
+
const findingFiles = new Set(findings.map((f) => f.location.file));
|
|
112
|
+
const manifestFiles = new Set(findings.filter((f) => isManifestFile(f.location.file)).map((f) => f.location.file));
|
|
113
|
+
// Build the optional LLM patch source (codemods always run first).
|
|
114
|
+
const provider = options.provider ?? "anthropic";
|
|
115
|
+
const model = options.model ?? defaultModel(provider);
|
|
116
|
+
let llmSource = hooks.llmPatchSource;
|
|
117
|
+
if (!llmSource && options.llm) {
|
|
118
|
+
const key = hooks.resolveKey ? hooks.resolveKey() : envKey(provider);
|
|
119
|
+
if (!key) {
|
|
120
|
+
stderr("qremediate: --llm needs an API key (QK_LLM_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY). Using codemods only.\n");
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
llmSource = async (finding) => {
|
|
124
|
+
const agent = await import("@quantakrypto/agent");
|
|
125
|
+
const client = agent.resolveClient({ provider, model, apiKey: key });
|
|
126
|
+
const proposal = await agent.proposeFix(finding, {
|
|
127
|
+
client,
|
|
128
|
+
readFile: (rel) => readFile(path.resolve(root, rel)),
|
|
129
|
+
fingerprint: fingerprintFinding,
|
|
130
|
+
});
|
|
131
|
+
if (!proposal)
|
|
132
|
+
return null;
|
|
133
|
+
return {
|
|
134
|
+
path: proposal.path,
|
|
135
|
+
newContent: proposal.newContent,
|
|
136
|
+
ruleId: finding.ruleId,
|
|
137
|
+
source: "llm",
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const patchSource = async (finding, content) => {
|
|
143
|
+
const codemod = codemodFor(finding);
|
|
144
|
+
if (codemod)
|
|
145
|
+
return codemod.apply(content, finding);
|
|
146
|
+
if (llmSource)
|
|
147
|
+
return llmSource(finding, content);
|
|
148
|
+
return null;
|
|
149
|
+
};
|
|
150
|
+
const contentCache = new Map();
|
|
151
|
+
const readContent = async (finding) => {
|
|
152
|
+
const abs = path.resolve(root, finding.location.file);
|
|
153
|
+
let c = contentCache.get(abs);
|
|
154
|
+
if (c === undefined) {
|
|
155
|
+
c = await readFile(abs);
|
|
156
|
+
contentCache.set(abs, c);
|
|
157
|
+
}
|
|
158
|
+
return c;
|
|
159
|
+
};
|
|
160
|
+
const rem = await remediateFindings(findings, {
|
|
161
|
+
readContent,
|
|
162
|
+
patchSource,
|
|
163
|
+
policy: { findingFiles, manifestFiles },
|
|
164
|
+
});
|
|
165
|
+
const byPath = new Map();
|
|
166
|
+
for (const vp of rem.applied)
|
|
167
|
+
if (!byPath.has(vp.patch.path))
|
|
168
|
+
byPath.set(vp.patch.path, vp);
|
|
169
|
+
const patches = [...byPath.values()];
|
|
170
|
+
if (patches.length === 0) {
|
|
171
|
+
return {
|
|
172
|
+
output: summarize(findings, patches, rem.rejected, options.mode, []),
|
|
173
|
+
exitCode: REMEDIATE_EXIT.OK,
|
|
174
|
+
written: [],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (options.mode === "pr") {
|
|
178
|
+
const openPr = hooks.openDraftPr ?? ((plan) => defaultOpenDraftPr(root, plan));
|
|
179
|
+
const suffix = hooks.branchSuffix ?? `${Date.now()}`;
|
|
180
|
+
const plan = {
|
|
181
|
+
branch: `quantakrypto/remediate-${suffix}`,
|
|
182
|
+
title: `qremediate: migrate ${patches.length} quantum-vulnerable finding(s)`,
|
|
183
|
+
body: prBody(patches, rem.rejected, options),
|
|
184
|
+
patches: patches.map((vp) => ({ path: vp.patch.path, newContent: vp.patch.newContent })),
|
|
185
|
+
};
|
|
186
|
+
try {
|
|
187
|
+
const { url } = await openPr(plan);
|
|
188
|
+
return {
|
|
189
|
+
output: `qremediate: opened a DRAFT PR${url ? ` (${url})` : ""} on branch ${plan.branch} with ${patches.length} verified fix(es). Nothing was merged — review it.`,
|
|
190
|
+
exitCode: REMEDIATE_EXIT.OK,
|
|
191
|
+
written: plan.patches.map((p) => p.path),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
196
|
+
return {
|
|
197
|
+
output: `qremediate: could not open a draft PR (${msg}). No changes were pushed; run with --mode diff/apply instead.`,
|
|
198
|
+
exitCode: REMEDIATE_EXIT.ERROR,
|
|
199
|
+
written: [],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const written = [];
|
|
204
|
+
const diffs = [];
|
|
205
|
+
for (const vp of patches) {
|
|
206
|
+
const abs = path.resolve(root, vp.patch.path);
|
|
207
|
+
const before = contentCache.get(abs) ?? (await readContent(vp.finding));
|
|
208
|
+
if (options.mode === "apply") {
|
|
209
|
+
await writeFile(abs, vp.patch.newContent);
|
|
210
|
+
written.push(vp.patch.path);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
diffs.push(unifiedDiff(vp.patch.path, before, vp.patch.newContent));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const body = options.mode === "diff" ? `${diffs.join("\n\n")}\n\n` : "";
|
|
217
|
+
return {
|
|
218
|
+
output: body + summarize(findings, patches, rem.rejected, options.mode, written),
|
|
219
|
+
exitCode: REMEDIATE_EXIT.OK,
|
|
220
|
+
written,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function summarize(findings, patches, rejected, mode, written) {
|
|
224
|
+
const lines = [];
|
|
225
|
+
lines.push(`qremediate: ${findings.length} finding(s), ${patches.length} verified fix(es), ${rejected.length} not auto-fixable.`);
|
|
226
|
+
if (mode === "apply" && written.length) {
|
|
227
|
+
lines.push(`Wrote: ${written.join(", ")}`);
|
|
228
|
+
}
|
|
229
|
+
else if (mode === "diff" && patches.length) {
|
|
230
|
+
lines.push("Review the diff above, then re-run with --mode apply to write it.");
|
|
231
|
+
}
|
|
232
|
+
if (rejected.length) {
|
|
233
|
+
lines.push("Not auto-fixed (needs review or the LLM layer):");
|
|
234
|
+
for (const r of rejected.slice(0, 10)) {
|
|
235
|
+
lines.push(` - ${r.finding.ruleId} ${r.finding.location.file}:${r.finding.location.line} — ${r.reason}`);
|
|
236
|
+
}
|
|
237
|
+
if (rejected.length > 10)
|
|
238
|
+
lines.push(` … and ${rejected.length - 10} more.`);
|
|
239
|
+
}
|
|
240
|
+
return lines.join("\n");
|
|
241
|
+
}
|
|
242
|
+
/** Parse qremediate argv. */
|
|
243
|
+
export function parseRemediateArgs(argv) {
|
|
244
|
+
const options = { path: ".", mode: "diff", llm: false };
|
|
245
|
+
let positional;
|
|
246
|
+
for (let i = 0; i < argv.length; i++) {
|
|
247
|
+
const arg = argv[i];
|
|
248
|
+
let flag = arg;
|
|
249
|
+
let inline;
|
|
250
|
+
if (arg.startsWith("--") && arg.includes("=")) {
|
|
251
|
+
const eq = arg.indexOf("=");
|
|
252
|
+
flag = arg.slice(0, eq);
|
|
253
|
+
inline = arg.slice(eq + 1);
|
|
254
|
+
}
|
|
255
|
+
const take = () => inline ?? argv[++i];
|
|
256
|
+
switch (flag) {
|
|
257
|
+
case "-h":
|
|
258
|
+
case "--help":
|
|
259
|
+
return { kind: "help" };
|
|
260
|
+
case "-v":
|
|
261
|
+
case "--version":
|
|
262
|
+
return { kind: "version" };
|
|
263
|
+
case "--mode": {
|
|
264
|
+
const v = take();
|
|
265
|
+
if (v !== "diff" && v !== "apply" && v !== "pr") {
|
|
266
|
+
return { kind: "error", message: `invalid --mode "${v ?? ""}" (expected diff|apply|pr)` };
|
|
267
|
+
}
|
|
268
|
+
options.mode = v;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
case "--llm":
|
|
272
|
+
options.llm = true;
|
|
273
|
+
break;
|
|
274
|
+
case "--llm-provider": {
|
|
275
|
+
const v = take();
|
|
276
|
+
if (v !== "anthropic" && v !== "openai-compatible") {
|
|
277
|
+
return { kind: "error", message: `invalid --llm-provider "${v ?? ""}"` };
|
|
278
|
+
}
|
|
279
|
+
options.provider = v;
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
case "--llm-model":
|
|
283
|
+
options.model = take();
|
|
284
|
+
break;
|
|
285
|
+
default:
|
|
286
|
+
if (flag.startsWith("-"))
|
|
287
|
+
return { kind: "error", message: `unknown option "${flag}"` };
|
|
288
|
+
if (positional !== undefined)
|
|
289
|
+
return { kind: "error", message: `unexpected argument "${arg}"` };
|
|
290
|
+
positional = arg;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (positional !== undefined)
|
|
294
|
+
options.path = positional;
|
|
295
|
+
return { kind: "run", options };
|
|
296
|
+
}
|
|
297
|
+
export const REMEDIATE_HELP = `qremediate — apply deterministic, verified fixes for insecure crypto findings
|
|
298
|
+
|
|
299
|
+
USAGE
|
|
300
|
+
qremediate [path] [--mode diff|apply|pr] [--llm] [--llm-provider <p>] [--llm-model <m>]
|
|
301
|
+
|
|
302
|
+
OPTIONS
|
|
303
|
+
--mode diff Print a unified diff of every verified fix (default; writes nothing)
|
|
304
|
+
--mode apply Write verified fixes into the working tree
|
|
305
|
+
--mode pr Commit verified fixes to a new branch and open a DRAFT PR (never merges)
|
|
306
|
+
--llm Also let a BYOK LLM propose fixes codemods can't (needs an API key)
|
|
307
|
+
--llm-provider anthropic | openai-compatible (default: anthropic)
|
|
308
|
+
--llm-model Model id for the BYOK provider
|
|
309
|
+
-h, --help Show this help
|
|
310
|
+
-v, --version Show version
|
|
311
|
+
|
|
312
|
+
Every fix must pass the verify_fix gate (the finding is gone, no new finding) and
|
|
313
|
+
the patch policy (only files with findings + dependency manifests). Never merges.
|
|
314
|
+
`;
|
|
315
|
+
//# sourceMappingURL=remediate-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediate-cli.js","sourceRoot":"","sources":["../src/remediate-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/report.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH,OAAO,KAAK,EAAW,aAAa,EAAE,UAAU,EAAY,MAAM,oBAAoB,CAAC;AAwBvF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAS5E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,MAAM,CAgGR"}
|
package/dist/report.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Only `human` lives here; `json`/`sarif` delegate to `@quantakrypto/core` so the
|
|
11
11
|
* serialized shape stays consistent across every tool in the monorepo.
|
|
12
12
|
*/
|
|
13
|
-
import { defaultRegistry, SEVERITY_ORDER, severityRank, toCbom, toJson, toSarif, } from "@quantakrypto/core";
|
|
13
|
+
import { ANALYZABLE_LANGUAGES_LABEL, defaultRegistry, DEP_VULNERABLE_RULE, SEVERITY_ORDER, severityRank, toCbom, toJson, toSarif, } from "@quantakrypto/core";
|
|
14
14
|
const PLAIN = { reset: "", bold: "", dim: "", red: "", yellow: "", green: "", cyan: "" };
|
|
15
15
|
const COLOR = {
|
|
16
16
|
reset: "\x1b[0m",
|
|
@@ -39,8 +39,13 @@ export function renderJson(result, opts) {
|
|
|
39
39
|
*/
|
|
40
40
|
export function renderSarif(result, opts) {
|
|
41
41
|
// Advertise the full rule catalog (not just the rules that fired) so SARIF
|
|
42
|
-
// consumers see complete metadata for every rule qScan can emit.
|
|
43
|
-
|
|
42
|
+
// consumers see complete metadata for every rule qScan can emit. The detector
|
|
43
|
+
// registry's catalog is source/config rules only; `dep-vulnerable` comes from
|
|
44
|
+
// the manifest scanner, so add its generic entry — otherwise SARIF would build
|
|
45
|
+
// that rule from the first dependency finding and leak one package's specifics
|
|
46
|
+
// into the shared rule description.
|
|
47
|
+
const catalog = [...defaultRegistry.ruleCatalog(), DEP_VULNERABLE_RULE];
|
|
48
|
+
return JSON.stringify(toSarif(result, { catalog, ...opts }), null, 2);
|
|
44
49
|
}
|
|
45
50
|
/**
|
|
46
51
|
* Render a CycloneDX 1.6 CBOM (cryptographic bill of materials) for the scan,
|
|
@@ -61,11 +66,41 @@ export function renderHuman(result, opts = {}) {
|
|
|
61
66
|
const c = opts.color ? COLOR : PLAIN;
|
|
62
67
|
const topN = opts.topN ?? 5;
|
|
63
68
|
const { findings, inventory, filesScanned } = result;
|
|
69
|
+
// `analyzedFiles`: of the scanned files, how many were in a language the
|
|
70
|
+
// scanner can actually inspect for crypto (JS/TS, Python, Go, Java). When it's 0 the
|
|
71
|
+
// readiness score reflects no analyzable code — say so rather than imply safe.
|
|
72
|
+
const analyzedFiles = result.analyzedFiles;
|
|
73
|
+
const noAnalyzable = analyzedFiles === 0;
|
|
64
74
|
const lines = [];
|
|
65
75
|
lines.push(`${c.bold}qScan — quantum-vulnerable cryptography report${c.reset}`);
|
|
66
|
-
|
|
76
|
+
const coverage = analyzedFiles === undefined
|
|
77
|
+
? ""
|
|
78
|
+
: ` • analyzed: ${analyzedFiles} (${ANALYZABLE_LANGUAGES_LABEL})`;
|
|
79
|
+
lines.push(`${c.dim}root: ${result.root} • files scanned: ${filesScanned}${coverage} • qscan v${result.toolVersion}${c.reset}`);
|
|
80
|
+
// Coverage diagnostics: warn when files were skipped, so a low finding count
|
|
81
|
+
// isn't mistaken for a clean scan of the whole tree.
|
|
82
|
+
const diag = result.diagnostics;
|
|
83
|
+
if (diag && (diag.unreadable > 0 || diag.skippedMinified > 0)) {
|
|
84
|
+
const parts = [];
|
|
85
|
+
if (diag.unreadable > 0)
|
|
86
|
+
parts.push(`${diag.unreadable} unreadable`);
|
|
87
|
+
if (diag.skippedMinified > 0)
|
|
88
|
+
parts.push(`${diag.skippedMinified} skipped (minified)`);
|
|
89
|
+
lines.push(`${c.yellow}Coverage: ${parts.join(", ")} — results may be incomplete.${c.reset}`);
|
|
90
|
+
}
|
|
67
91
|
lines.push("");
|
|
68
92
|
if (findings.length === 0) {
|
|
93
|
+
if (noAnalyzable && filesScanned > 0) {
|
|
94
|
+
// Honesty guard: don't let a 100/100 read as "safe" when nothing the
|
|
95
|
+
// scanner understands was analyzed — the crypto may live in an
|
|
96
|
+
// unsupported language (Go, Java, Rust, C#, …).
|
|
97
|
+
lines.push(`${c.yellow}No analyzable source found.${c.reset} Scanned ${filesScanned} file${filesScanned === 1 ? "" : "s"}, but none were in a supported language (${ANALYZABLE_LANGUAGES_LABEL}).`);
|
|
98
|
+
lines.push(`${c.dim}The score below covers only what qScan can read today — it is NOT a clean bill of health for this codebase.${c.reset}`);
|
|
99
|
+
lines.push(`${c.bold}Readiness score: ${readiness(inventory.readinessScore, c)}/100 (no analyzable source)${c.reset}`);
|
|
100
|
+
lines.push("");
|
|
101
|
+
lines.push(`${c.dim}Next step:${c.reset} multi-language support is expanding; track coverage before relying on the score.`);
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
69
104
|
lines.push(`${c.green}No quantum-vulnerable cryptography detected.${c.reset}`);
|
|
70
105
|
lines.push(`${c.bold}Readiness score: ${readiness(inventory.readinessScore, c)}/100${c.reset}`);
|
|
71
106
|
lines.push("");
|
|
@@ -106,6 +141,13 @@ function nextStep(findings) {
|
|
|
106
141
|
const worst = [...findings].sort(compareFindings)[0];
|
|
107
142
|
if (!worst)
|
|
108
143
|
return "review the findings above.";
|
|
144
|
+
// A dependency finding points at a manifest — you replace the *package*, not
|
|
145
|
+
// "migrate package.json". Phrase it as a dependency swap.
|
|
146
|
+
if (worst.category === "dependency") {
|
|
147
|
+
return worst.remediation
|
|
148
|
+
? `replace the vulnerable dependency in ${worst.location.file} — ${worst.remediation}`
|
|
149
|
+
: `replace the vulnerable dependency in ${worst.location.file}.`;
|
|
150
|
+
}
|
|
109
151
|
if (worst.remediation) {
|
|
110
152
|
return `migrate ${worst.location.file} — ${worst.remediation}`;
|
|
111
153
|
}
|
package/dist/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,YAAY,EACZ,MAAM,EACN,MAAM,EACN,OAAO,GACR,MAAM,oBAAoB,CAAC;AAc5B,MAAM,KAAK,GAAY,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAClG,MAAM,KAAK,GAAY;IACrB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,UAAU;IAClB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAkB,EAAE,IAAoB;IACjE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,MAAkB,EAAE,IAAoB;IAClE,2EAA2E;IAC3E,
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ContextLevel, Finding, ScanResult, Severity, TriageVerdict } from "@quantakrypto/core";
|
|
2
|
+
import type { LlmProvider } from "./args.js";
|
|
3
|
+
/** Injectable triage function (default wraps `@quantakrypto/agent`). */
|
|
4
|
+
export type TriageFn = (findings: readonly Finding[]) => Promise<Map<string, TriageVerdict>>;
|
|
5
|
+
export interface RunTriageOptions {
|
|
6
|
+
level: ContextLevel;
|
|
7
|
+
floor?: Severity;
|
|
8
|
+
dryRun?: boolean;
|
|
9
|
+
provider?: LlmProvider;
|
|
10
|
+
model?: string;
|
|
11
|
+
cacheFile?: string;
|
|
12
|
+
/** Base directory for resolving finding file paths (defaults to result.root). */
|
|
13
|
+
root?: string;
|
|
14
|
+
triageFn?: TriageFn;
|
|
15
|
+
resolveKey?: () => string | undefined;
|
|
16
|
+
readFile?: (relPath: string) => Promise<string>;
|
|
17
|
+
stderr?: (s: string) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface RunTriageResult {
|
|
20
|
+
/** When `--dry-run`, the preflight text to show instead of a normal report. */
|
|
21
|
+
preflight?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Annotate `result.findings` with triage verdicts (mutating `result`). Returns a
|
|
25
|
+
* preflight string when `--dry-run` is set (no provider is contacted). Failures
|
|
26
|
+
* degrade gracefully: the scan/report proceed without triage.
|
|
27
|
+
*/
|
|
28
|
+
export declare function runTriage(result: ScanResult, opts: RunTriageOptions): Promise<RunTriageResult>;
|
|
29
|
+
//# sourceMappingURL=triage-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-run.d.ts","sourceRoot":"","sources":["../src/triage-run.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAU7C,wEAAwE;AACxE,MAAM,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;AAE7F,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,CAAC,CAsE1B"}
|