@quantakrypto/qscan 0.4.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -9
- package/dist/args.d.ts +69 -9
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +123 -5
- package/dist/args.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +98 -10
- package/dist/cli.js.map +1 -1
- package/dist/color.d.ts +38 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +44 -0
- package/dist/color.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -1
- 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 +50 -2
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +60 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +178 -23
- package/dist/index.js.map +1 -1
- package/dist/remediate-cli.d.ts +3 -4
- package/dist/remediate-cli.d.ts.map +1 -1
- package/dist/remediate-cli.js +1 -1
- package/dist/remediate-cli.js.map +1 -1
- package/dist/report.d.ts +14 -2
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +61 -6
- package/dist/report.js.map +1 -1
- package/dist/sign.d.ts +4 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +61 -0
- package/dist/sign.js.map +1 -0
- package/dist/triage-run.d.ts +3 -4
- package/dist/triage-run.d.ts.map +1 -1
- package/dist/triage-run.js +13 -6
- package/dist/triage-run.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,7 +14,8 @@ step.
|
|
|
14
14
|
- **CI-friendly.** Severity thresholds drive the exit code; baselines suppress
|
|
15
15
|
known findings so the build only fails on *new* problems.
|
|
16
16
|
- **Multiple formats.** `human` (default), `json`, SARIF 2.1.0 for code-scanning
|
|
17
|
-
dashboards,
|
|
17
|
+
dashboards, a CycloneDX 1.6 **CBOM** for compliance tooling, an ISO 27001
|
|
18
|
+
A.8.24 **evidence** report, and an **OpenVEX** 0.2.0 document for VEX pipelines.
|
|
18
19
|
- **Fast on big repos.** Optional worker-thread parallelism (`--parallel`) and
|
|
19
20
|
git-aware incremental scanning (`--changed`).
|
|
20
21
|
|
|
@@ -23,10 +24,15 @@ step.
|
|
|
23
24
|
Inline crypto detection currently covers **JavaScript/TypeScript**, **Python**,
|
|
24
25
|
**Go**, **Java/Kotlin/Scala** (JCA + BouncyCastle), **C#/.NET**, **Rust**, **Ruby**,
|
|
25
26
|
**PHP** (openssl / phpseclib3 / libsodium), **Elixir** (`:crypto` / X509 / JOSE),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
`
|
|
29
|
-
|
|
27
|
+
**C/C++** (OpenSSL, Mbed TLS, wolfSSL), **Swift** (CryptoKit / Security),
|
|
28
|
+
**Objective-C** (Security `SecKey*`), and **Dart/Flutter** (pointycastle /
|
|
29
|
+
`cryptography`), and **smart contracts** (Solidity/Move/Cairo on-chain
|
|
30
|
+
signature verification) source — **14 languages**. PEM key material, SSH keys (including
|
|
31
|
+
SSH-CA certificates), TLS/certificate config, reverse-proxy/gRPC TLS, WebAuthn/FIDO2,
|
|
32
|
+
code-signing, weak signature hashes (SHA-1/MD5), DKIM, SPIFFE/SPIRE, and dependency
|
|
33
|
+
manifests for **seven ecosystems** — npm (plus `yarn.lock` / `pnpm-lock.yaml`),
|
|
34
|
+
PyPI, Cargo, Go modules, Maven, RubyGems, and NuGet — are detected in **any**
|
|
35
|
+
file regardless of language.
|
|
30
36
|
|
|
31
37
|
qScan is **honest about coverage**: if a scan walks files but finds none in a
|
|
32
38
|
supported source language, it says so and will **not** present a bare `100/100`
|
|
@@ -56,7 +62,7 @@ qscan [path] [options]
|
|
|
56
62
|
|
|
57
63
|
| Flag | Description | Default |
|
|
58
64
|
| --- | --- | --- |
|
|
59
|
-
| `--format <human\|json\|sarif\|cbom>` | Output format. | `human` |
|
|
65
|
+
| `--format <human\|json\|sarif\|cbom\|evidence\|vex>` | Output format. | `human` |
|
|
60
66
|
| `--cbom` | Alias for `--format cbom` (CycloneDX 1.6 CBOM). | — |
|
|
61
67
|
| `-o, --output <file>` | Write the report to a file instead of stdout. | stdout |
|
|
62
68
|
| `--severity-threshold <level>` | Exit 1 if any finding is at/above this level. One of `critical`, `high`, `medium`, `low`, `info`. | `high` |
|
|
@@ -108,7 +114,7 @@ with `--config <path>`, or disable discovery with `--no-config-file`. See
|
|
|
108
114
|
|
|
109
115
|
```
|
|
110
116
|
qScan — quantum-vulnerable cryptography report
|
|
111
|
-
root: ./examples/vulnerable-app • files scanned: 2 • qscan v0.
|
|
117
|
+
root: ./examples/vulnerable-app • files scanned: 2 • qscan v0.5.0
|
|
112
118
|
|
|
113
119
|
3 findings (2 high, 1 medium)
|
|
114
120
|
2 exposed to harvest-now-decrypt-later (HNDL).
|
|
@@ -194,8 +200,11 @@ qscan . --concurrency 4 # pin the worker count (implies --parallel)
|
|
|
194
200
|
## CBOM (CycloneDX)
|
|
195
201
|
|
|
196
202
|
Emit a CycloneDX 1.6 **cryptographic bill of materials** — one
|
|
197
|
-
`cryptographic-asset` component per distinct (algorithm,
|
|
198
|
-
file:line occurrence evidence — for compliance and supply-chain tooling
|
|
203
|
+
`cryptographic-asset` component per distinct (assetType, algorithm, discriminator),
|
|
204
|
+
with file:line occurrence evidence — for compliance and supply-chain tooling.
|
|
205
|
+
Findings are classified into their proper CycloneDX `assetType`: `algorithm`
|
|
206
|
+
(crypto usage), `certificate` (X.509), `related-crypto-material` (private/public
|
|
207
|
+
key material), and `protocol` (TLS):
|
|
199
208
|
|
|
200
209
|
```bash
|
|
201
210
|
qscan . --cbom -o qscan-cbom.json
|
|
@@ -206,6 +215,25 @@ qscan . --format cbom -o qscan-cbom.json
|
|
|
206
215
|
The output is deterministic (sorted components and occurrences, stable serial
|
|
207
216
|
number), so re-running on an unchanged tree produces byte-identical CBOMs.
|
|
208
217
|
|
|
218
|
+
## VEX (OpenVEX)
|
|
219
|
+
|
|
220
|
+
Emit an **OpenVEX 0.2.0** document so the quantum-readiness posture flows into the
|
|
221
|
+
same supply-chain pipeline that already ingests CVE-based VEX:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
qscan . --format vex -o qscan.openvex.json
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
One statement per rule (a synthetic `QK-<ruleId>` vulnerability), listing every
|
|
228
|
+
affected `file:line` product with `status: "affected"` and the rule's remediation
|
|
229
|
+
as the `action_statement`. PQC findings have no CVE, so qScan mints a stable
|
|
230
|
+
per-rule identifier rather than claiming one. qScan never reports `not_affected`
|
|
231
|
+
— only an operator can attest a mitigation — so downgrading a statement is left to
|
|
232
|
+
you to post-process. When `--triage` is also set, each verdict (exposure score /
|
|
233
|
+
priority / rationale) is carried in the statement's `status_notes`. Output is
|
|
234
|
+
deterministic (statements sorted by vulnerability, products deduped and sorted;
|
|
235
|
+
the `@id` derives from the finding set).
|
|
236
|
+
|
|
209
237
|
## Triage (opt-in, BYOK)
|
|
210
238
|
|
|
211
239
|
`--triage` adds an optional LLM pass that **re-ranks and explains** findings by
|
package/dist/args.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { meetsThreshold, SEVERITY_ORDER, severityRank } from "@quantakrypto/core";
|
|
11
11
|
import type { ContextLevel, ReportFormat, SecurityTier, Severity } from "@quantakrypto/core";
|
|
12
|
+
import type { ColorChoice } from "./color.js";
|
|
12
13
|
/** Valid `--llm-provider` values. */
|
|
13
14
|
declare const LLM_PROVIDERS: readonly ["anthropic", "openai-compatible"];
|
|
14
15
|
export type LlmProvider = (typeof LLM_PROVIDERS)[number];
|
|
@@ -16,9 +17,11 @@ export { meetsThreshold, SEVERITY_ORDER, severityRank };
|
|
|
16
17
|
/**
|
|
17
18
|
* Output formats qScan accepts on the command line. Extends core's
|
|
18
19
|
* {@link ReportFormat} with `"cbom"` (a CycloneDX cryptographic bill of
|
|
19
|
-
* materials),
|
|
20
|
+
* materials), `"evidence"` (ISO A.8.24 readiness report), and `"vex"` (an
|
|
21
|
+
* OpenVEX 0.2.0 document) — all rendered locally via core (`toCbom`,
|
|
22
|
+
* `buildReadinessReport`, `toOpenVex`).
|
|
20
23
|
*/
|
|
21
|
-
export type QscanFormat = ReportFormat | "cbom" | "evidence";
|
|
24
|
+
export type QscanFormat = ReportFormat | "cbom" | "evidence" | "vex";
|
|
22
25
|
/** Fully-resolved options the CLI/programmatic runner operates on. */
|
|
23
26
|
export interface QscanOptions {
|
|
24
27
|
/** Directory or file to scan. */
|
|
@@ -27,6 +30,8 @@ export interface QscanOptions {
|
|
|
27
30
|
format: QscanFormat;
|
|
28
31
|
/** Write the report to this file instead of stdout, when set. */
|
|
29
32
|
output?: string;
|
|
33
|
+
/** External CBOM files to merge into the `--cbom` output (CycloneDX bom-link). */
|
|
34
|
+
mergeCboms?: string[];
|
|
30
35
|
/** Findings at or above this severity cause a non-zero exit. */
|
|
31
36
|
severityThreshold: Severity;
|
|
32
37
|
/** Scan source files for inline crypto usage. */
|
|
@@ -68,6 +73,12 @@ export interface QscanOptions {
|
|
|
68
73
|
writeBaseline?: string;
|
|
69
74
|
/** Suppress the human summary banner (still writes reports/output files). */
|
|
70
75
|
quiet: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* ANSI color policy for the human report (`--color` / `--no-color`). `"auto"`
|
|
78
|
+
* (default) colors only a live terminal and honors `NO_COLOR` / `FORCE_COLOR`;
|
|
79
|
+
* see {@link resolveColor}. Color is decoration only — never the sole signal.
|
|
80
|
+
*/
|
|
81
|
+
colorChoice: ColorChoice;
|
|
71
82
|
/** How many findings the human report lists (`--top N`). Default: 5. */
|
|
72
83
|
topN?: number;
|
|
73
84
|
/** Rule ids to suppress (from `quantakrypto.config.json` `disabledRules`). */
|
|
@@ -82,8 +93,23 @@ export interface QscanOptions {
|
|
|
82
93
|
maxFindings?: number;
|
|
83
94
|
/** CNSA security tier for the migration-targets footer (`--tier`). Default: none. */
|
|
84
95
|
tier?: SecurityTier;
|
|
96
|
+
/**
|
|
97
|
+
* Standards regime the migration guidance is tailored to (`--profile`): one of the
|
|
98
|
+
* built-in ids (nist / cnsa-2.0 / bsi-tr-02102 / anssi / uk-ncsc). Default: none
|
|
99
|
+
* (`--tier` maps to a profile for back-compat). Governs parameter sets, deadlines,
|
|
100
|
+
* and the hybrid stance surfaced in remediation.
|
|
101
|
+
*/
|
|
102
|
+
profile?: string;
|
|
85
103
|
/** Org cryptography policy file (`--policy`) for the evidence report's §4 verdicts. */
|
|
86
104
|
policy?: string;
|
|
105
|
+
/**
|
|
106
|
+
* External signer command for the evidence attestation (`--sign`). The report's
|
|
107
|
+
* contentHash is piped to it on stdin; its stdout is recorded as the detached
|
|
108
|
+
* signature. Only valid with `--format evidence`.
|
|
109
|
+
*/
|
|
110
|
+
sign?: string;
|
|
111
|
+
/** External RFC-3161 timestamper command for the evidence attestation (`--timestamp`). */
|
|
112
|
+
timestamp?: string;
|
|
87
113
|
/** How much source context leaves the machine (`--context`). Default: snippet. */
|
|
88
114
|
contextLevel?: ContextLevel;
|
|
89
115
|
/** Print the exact triage payload and exit without calling the provider (`--dry-run`). */
|
|
@@ -109,6 +135,26 @@ export interface QscanOptions {
|
|
|
109
135
|
* from `--no-config` (which skips config-file *detectors*).
|
|
110
136
|
*/
|
|
111
137
|
noConfigFile: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Compute + emit HNDL (harvest-now-decrypt-later) exposure (`--hndl`). Reads
|
|
140
|
+
* `hndl.yml` at the scan root, scores each finding + a repo summary, and adds
|
|
141
|
+
* the exposure fields to the JSON / SARIF report. Additive: never changes the
|
|
142
|
+
* exit code. See docs/HNDL.md.
|
|
143
|
+
*/
|
|
144
|
+
hndl: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* URL to a posture credential recorded in a crypto-agility manifest
|
|
147
|
+
* (`--attestation`). Only consumed by `crypto-agility emit`; recorded verbatim,
|
|
148
|
+
* never fetched (offline boundary). See docs/CRYPTO-AGILITY-MANIFEST.md.
|
|
149
|
+
*/
|
|
150
|
+
attestation?: string;
|
|
151
|
+
/**
|
|
152
|
+
* Operator assertion of hybrid post-quantum key exchange for a crypto-agility
|
|
153
|
+
* manifest (`--hybrid-kex` → true, `--no-hybrid-kex` → false). Left undefined,
|
|
154
|
+
* the manifest reports `hybridKexInUse: null` (a static scan cannot observe a
|
|
155
|
+
* negotiated TLS group). Only consumed by `crypto-agility emit`.
|
|
156
|
+
*/
|
|
157
|
+
hybridKexInUse?: boolean;
|
|
112
158
|
}
|
|
113
159
|
/**
|
|
114
160
|
* Option keys that a `quantakrypto.config.json` may also set. When such a key was set
|
|
@@ -124,8 +170,28 @@ export interface ParsedRun {
|
|
|
124
170
|
/** The set of {@link ConfigurableKey}s the user set via a flag. */
|
|
125
171
|
explicit: Set<ConfigurableKey>;
|
|
126
172
|
}
|
|
173
|
+
/** The `qscan hndl init` subcommand: scaffold an `hndl.yml`. */
|
|
174
|
+
export interface ParsedHndlInit {
|
|
175
|
+
kind: "hndl-init";
|
|
176
|
+
options: QscanOptions;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Emit a crypto-agility manifest: either `qscan crypto-agility emit [path]` or the
|
|
180
|
+
* `--crypto-agility` flag on a normal scan. Additive: it always exits 0, never
|
|
181
|
+
* consulting the severity threshold.
|
|
182
|
+
*/
|
|
183
|
+
export interface ParsedCryptoAgilityEmit {
|
|
184
|
+
kind: "crypto-agility-emit";
|
|
185
|
+
options: QscanOptions;
|
|
186
|
+
}
|
|
187
|
+
/** Validate a local manifest file: `qscan crypto-agility validate <file>`. */
|
|
188
|
+
export interface ParsedCryptoAgilityValidate {
|
|
189
|
+
kind: "crypto-agility-validate";
|
|
190
|
+
/** Path to the manifest JSON file to check. */
|
|
191
|
+
file: string;
|
|
192
|
+
}
|
|
127
193
|
/** Result of {@link parseArgs}: either resolved options or a meta action. */
|
|
128
|
-
export type ParsedArgs = ParsedRun | {
|
|
194
|
+
export type ParsedArgs = ParsedRun | ParsedHndlInit | ParsedCryptoAgilityEmit | ParsedCryptoAgilityValidate | {
|
|
129
195
|
kind: "help";
|
|
130
196
|
} | {
|
|
131
197
|
kind: "version";
|
|
@@ -146,12 +212,6 @@ export declare const DEFAULT_CACHE_FILE = ".quantakrypto-cache.json";
|
|
|
146
212
|
export declare function parseArgs(argv: readonly string[]): ParsedArgs;
|
|
147
213
|
/** Validate/normalize a `--format` value. */
|
|
148
214
|
export declare function asFormat(value: string): QscanFormat;
|
|
149
|
-
/** Validate/normalize a `--context` level. */
|
|
150
|
-
export declare function asContextLevel(value: string): ContextLevel;
|
|
151
|
-
/** Validate/normalize a `--tier` value. */
|
|
152
|
-
export declare function asTier(value: string): SecurityTier;
|
|
153
|
-
/** Validate/normalize a `--llm-provider` value. */
|
|
154
|
-
export declare function asProvider(value: string): LlmProvider;
|
|
155
215
|
/** Validate/normalize a non-negative integer flag value. */
|
|
156
216
|
export declare function asInt(value: string, flag: string): number;
|
|
157
217
|
/** Validate/normalize a severity value. */
|
package/dist/args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|
package/dist/args.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* (`-o`, `-v`, `-h`), repeatable `--ignore`, and a single optional positional
|
|
8
8
|
* path. Unknown flags are a usage error.
|
|
9
9
|
*/
|
|
10
|
-
import { meetsThreshold, SEVERITY_ORDER, severityRank } from "@quantakrypto/core";
|
|
10
|
+
import { meetsThreshold, SEVERITY_ORDER, severityRank, standardsProfileIds, } from "@quantakrypto/core";
|
|
11
11
|
/** Valid context levels for `--context` (how much source triage/remediate sends). */
|
|
12
12
|
const CONTEXT_LEVELS = ["metadata", "snippet", "function", "file"];
|
|
13
13
|
/** Valid CNSA security tiers for `--tier` (report migration-target guidance). */
|
|
@@ -19,7 +19,7 @@ const LLM_PROVIDERS = ["anthropic", "openai-compatible"];
|
|
|
19
19
|
// `@quantakrypto/qscan` callers (and tests) keep importing them from `./args.js`
|
|
20
20
|
// without qScan maintaining a second, drift-prone copy.
|
|
21
21
|
export { meetsThreshold, SEVERITY_ORDER, severityRank };
|
|
22
|
-
const FORMATS = ["human", "json", "sarif", "cbom", "evidence"];
|
|
22
|
+
const FORMATS = ["human", "json", "sarif", "cbom", "evidence", "vex"];
|
|
23
23
|
/** Thrown on malformed input; the CLI maps this to exit code 2. */
|
|
24
24
|
export class ArgError extends Error {
|
|
25
25
|
name = "ArgError";
|
|
@@ -40,10 +40,12 @@ export function defaultOptions() {
|
|
|
40
40
|
changed: false,
|
|
41
41
|
parallel: false,
|
|
42
42
|
quiet: false,
|
|
43
|
+
colorChoice: "auto",
|
|
43
44
|
noSnippets: false,
|
|
44
45
|
noConfigFile: false,
|
|
45
46
|
triage: false,
|
|
46
47
|
dryRun: false,
|
|
48
|
+
hndl: false,
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
@@ -54,9 +56,72 @@ export function defaultOptions() {
|
|
|
54
56
|
/** Default scan-cache file when `--cache` is given without a path. */
|
|
55
57
|
export const DEFAULT_CACHE_FILE = ".quantakrypto-cache.json";
|
|
56
58
|
export function parseArgs(argv) {
|
|
59
|
+
// Subcommand dispatch: `qscan hndl <sub> …`. Only `init` exists today. `--help`
|
|
60
|
+
// / `--version` anywhere still short-circuit to the meta actions (handled by
|
|
61
|
+
// the shared loop below), so `qscan hndl init --help` shows help.
|
|
62
|
+
if (argv[0] === "hndl") {
|
|
63
|
+
const sub = argv[1];
|
|
64
|
+
if (sub === undefined || sub.startsWith("-")) {
|
|
65
|
+
if (sub === "--help" || sub === "-h")
|
|
66
|
+
return { kind: "help" };
|
|
67
|
+
if (sub === "--version" || sub === "-v")
|
|
68
|
+
return { kind: "version" };
|
|
69
|
+
throw new ArgError(`"hndl" requires a subcommand (expected: init)`);
|
|
70
|
+
}
|
|
71
|
+
if (sub !== "init") {
|
|
72
|
+
throw new ArgError(`unknown hndl subcommand "${sub}" (expected: init)`);
|
|
73
|
+
}
|
|
74
|
+
const parsed = parseRunArgs(argv.slice(2));
|
|
75
|
+
if (parsed.kind !== "run")
|
|
76
|
+
return parsed; // --help / --version passthrough
|
|
77
|
+
return { kind: "hndl-init", options: parsed.options };
|
|
78
|
+
}
|
|
79
|
+
// Subcommand dispatch: `qscan crypto-agility <sub> …`.
|
|
80
|
+
// emit [path] derive + write a manifest (always exits 0)
|
|
81
|
+
// validate <file> check a local manifest against the schema
|
|
82
|
+
if (argv[0] === "crypto-agility") {
|
|
83
|
+
const sub = argv[1];
|
|
84
|
+
if (sub === undefined || sub.startsWith("-")) {
|
|
85
|
+
if (sub === "--help" || sub === "-h")
|
|
86
|
+
return { kind: "help" };
|
|
87
|
+
if (sub === "--version" || sub === "-v")
|
|
88
|
+
return { kind: "version" };
|
|
89
|
+
throw new ArgError(`"crypto-agility" requires a subcommand (expected: emit, validate)`);
|
|
90
|
+
}
|
|
91
|
+
if (sub === "emit") {
|
|
92
|
+
const parsed = parseRunArgs(argv.slice(2));
|
|
93
|
+
// `--help`/`--version` short-circuit; a redundant `--crypto-agility` flag on
|
|
94
|
+
// the emit subcommand already yields the emit kind (returned as-is).
|
|
95
|
+
if (parsed.kind !== "run")
|
|
96
|
+
return parsed;
|
|
97
|
+
return { kind: "crypto-agility-emit", options: parsed.options };
|
|
98
|
+
}
|
|
99
|
+
if (sub === "validate") {
|
|
100
|
+
const rest = argv.slice(2);
|
|
101
|
+
if (rest.includes("--help") || rest.includes("-h"))
|
|
102
|
+
return { kind: "help" };
|
|
103
|
+
if (rest.includes("--version") || rest.includes("-v"))
|
|
104
|
+
return { kind: "version" };
|
|
105
|
+
const positionals = rest.filter((a) => !(a.startsWith("-") && a !== "-"));
|
|
106
|
+
if (positionals.length === 0) {
|
|
107
|
+
throw new ArgError(`"crypto-agility validate" requires a manifest file path`);
|
|
108
|
+
}
|
|
109
|
+
if (positionals.length > 1) {
|
|
110
|
+
throw new ArgError(`"crypto-agility validate" takes exactly one file (got ${positionals.length})`);
|
|
111
|
+
}
|
|
112
|
+
return { kind: "crypto-agility-validate", file: positionals[0] };
|
|
113
|
+
}
|
|
114
|
+
throw new ArgError(`unknown crypto-agility subcommand "${sub}" (expected: emit, validate)`);
|
|
115
|
+
}
|
|
116
|
+
return parseRunArgs(argv);
|
|
117
|
+
}
|
|
118
|
+
/** Parse the run-mode grammar (flags + a single optional positional path). */
|
|
119
|
+
function parseRunArgs(argv) {
|
|
57
120
|
const options = defaultOptions();
|
|
58
121
|
const explicit = new Set();
|
|
59
122
|
let positional;
|
|
123
|
+
// Set by `--crypto-agility`: the whole run becomes a manifest emit (exit 0).
|
|
124
|
+
let emitManifest = false;
|
|
60
125
|
// Manual index walk so flags can consume the following token as a value.
|
|
61
126
|
for (let i = 0; i < argv.length; i++) {
|
|
62
127
|
const arg = argv[i];
|
|
@@ -103,6 +168,11 @@ export function parseArgs(argv) {
|
|
|
103
168
|
rejectInlineValue();
|
|
104
169
|
options.format = "cbom";
|
|
105
170
|
break;
|
|
171
|
+
case "--merge":
|
|
172
|
+
// Merge an external CBOM (e.g. a qprobe endpoint CBOM) into the --cbom
|
|
173
|
+
// output via CycloneDX bom-link. Repeatable.
|
|
174
|
+
(options.mergeCboms ??= []).push(takeValue());
|
|
175
|
+
break;
|
|
106
176
|
case "-o":
|
|
107
177
|
case "--output":
|
|
108
178
|
options.output = takeValue();
|
|
@@ -154,6 +224,9 @@ export function parseArgs(argv) {
|
|
|
154
224
|
case "--tier":
|
|
155
225
|
options.tier = asTier(takeValue());
|
|
156
226
|
break;
|
|
227
|
+
case "--profile":
|
|
228
|
+
options.profile = asProfile(takeValue());
|
|
229
|
+
break;
|
|
157
230
|
case "--context":
|
|
158
231
|
options.contextLevel = asContextLevel(takeValue());
|
|
159
232
|
break;
|
|
@@ -232,6 +305,12 @@ export function parseArgs(argv) {
|
|
|
232
305
|
case "--policy":
|
|
233
306
|
options.policy = takeValue();
|
|
234
307
|
break;
|
|
308
|
+
case "--sign":
|
|
309
|
+
options.sign = takeValue();
|
|
310
|
+
break;
|
|
311
|
+
case "--timestamp":
|
|
312
|
+
options.timestamp = takeValue();
|
|
313
|
+
break;
|
|
235
314
|
case "--write-baseline":
|
|
236
315
|
options.writeBaseline = takeValue();
|
|
237
316
|
break;
|
|
@@ -239,10 +318,38 @@ export function parseArgs(argv) {
|
|
|
239
318
|
rejectInlineValue();
|
|
240
319
|
options.quiet = true;
|
|
241
320
|
break;
|
|
321
|
+
case "--color":
|
|
322
|
+
rejectInlineValue();
|
|
323
|
+
options.colorChoice = "always";
|
|
324
|
+
break;
|
|
325
|
+
case "--no-color":
|
|
326
|
+
rejectInlineValue();
|
|
327
|
+
options.colorChoice = "never";
|
|
328
|
+
break;
|
|
242
329
|
case "--no-snippets":
|
|
243
330
|
rejectInlineValue();
|
|
244
331
|
options.noSnippets = true;
|
|
245
332
|
break;
|
|
333
|
+
case "--hndl":
|
|
334
|
+
rejectInlineValue();
|
|
335
|
+
options.hndl = true;
|
|
336
|
+
break;
|
|
337
|
+
// Crypto-agility manifest controls (see `crypto-agility emit`).
|
|
338
|
+
case "--crypto-agility":
|
|
339
|
+
rejectInlineValue();
|
|
340
|
+
emitManifest = true;
|
|
341
|
+
break;
|
|
342
|
+
case "--attestation":
|
|
343
|
+
options.attestation = takeValue();
|
|
344
|
+
break;
|
|
345
|
+
case "--hybrid-kex":
|
|
346
|
+
rejectInlineValue();
|
|
347
|
+
options.hybridKexInUse = true;
|
|
348
|
+
break;
|
|
349
|
+
case "--no-hybrid-kex":
|
|
350
|
+
rejectInlineValue();
|
|
351
|
+
options.hybridKexInUse = false;
|
|
352
|
+
break;
|
|
246
353
|
default:
|
|
247
354
|
if (flag.startsWith("-") && flag !== "-") {
|
|
248
355
|
throw new ArgError(`unknown option "${flag}"`);
|
|
@@ -256,6 +363,10 @@ export function parseArgs(argv) {
|
|
|
256
363
|
}
|
|
257
364
|
if (positional !== undefined)
|
|
258
365
|
options.path = positional;
|
|
366
|
+
// `--crypto-agility` turns the whole run into a manifest emit, taking it off the
|
|
367
|
+
// findings-threshold exit path entirely (the emit always exits 0).
|
|
368
|
+
if (emitManifest)
|
|
369
|
+
return { kind: "crypto-agility-emit", options };
|
|
259
370
|
return { kind: "run", options, explicit };
|
|
260
371
|
}
|
|
261
372
|
/** Validate/normalize a `--format` value. */
|
|
@@ -265,19 +376,26 @@ export function asFormat(value) {
|
|
|
265
376
|
throw new ArgError(`invalid --format "${value}" (expected one of: ${FORMATS.join(", ")})`);
|
|
266
377
|
}
|
|
267
378
|
/** Validate/normalize a `--context` level. */
|
|
268
|
-
|
|
379
|
+
function asContextLevel(value) {
|
|
269
380
|
if (CONTEXT_LEVELS.includes(value))
|
|
270
381
|
return value;
|
|
271
382
|
throw new ArgError(`invalid --context "${value}" (expected one of: ${CONTEXT_LEVELS.join(", ")})`);
|
|
272
383
|
}
|
|
273
384
|
/** Validate/normalize a `--tier` value. */
|
|
274
|
-
|
|
385
|
+
function asTier(value) {
|
|
275
386
|
if (SECURITY_TIERS.includes(value))
|
|
276
387
|
return value;
|
|
277
388
|
throw new ArgError(`invalid --tier "${value}" (expected one of: ${SECURITY_TIERS.join(", ")})`);
|
|
278
389
|
}
|
|
390
|
+
/** Validate a `--profile` value against the built-in standards regimes. */
|
|
391
|
+
function asProfile(value) {
|
|
392
|
+
const ids = standardsProfileIds();
|
|
393
|
+
if (ids.includes(value))
|
|
394
|
+
return value;
|
|
395
|
+
throw new ArgError(`invalid --profile "${value}" (expected one of: ${ids.join(", ")})`);
|
|
396
|
+
}
|
|
279
397
|
/** Validate/normalize a `--llm-provider` value. */
|
|
280
|
-
|
|
398
|
+
function asProvider(value) {
|
|
281
399
|
if (LLM_PROVIDERS.includes(value))
|
|
282
400
|
return value;
|
|
283
401
|
throw new ArgError(`invalid --llm-provider "${value}" (expected one of: ${LLM_PROVIDERS.join(", ")})`);
|
package/dist/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Zero-dependency command-line argument parsing for qScan.\n *\n * Hand-rolled rather than pulled from a library to keep the package free of\n * runtime dependencies. The grammar is deliberately small: long flags\n * (`--flag`, `--flag value`, `--flag=value`), a couple of short aliases\n * (`-o`, `-v`, `-h`), repeatable `--ignore`, and a single optional positional\n * path. Unknown flags are a usage error.\n */\n\nimport { meetsThreshold, SEVERITY_ORDER, severityRank } from \"@quantakrypto/core\";\nimport type { ContextLevel, ReportFormat, SecurityTier, Severity } from \"@quantakrypto/core\";\n\n/** Valid context levels for `--context` (how much source triage/remediate sends). */\nconst CONTEXT_LEVELS: readonly ContextLevel[] = [\"metadata\", \"snippet\", \"function\", \"file\"];\n/** Valid CNSA security tiers for `--tier` (report migration-target guidance). */\nconst SECURITY_TIERS: readonly SecurityTier[] = [\"category-3\", \"category-5\"];\n/** Valid `--llm-provider` values. */\nconst LLM_PROVIDERS = [\"anthropic\", \"openai-compatible\"] as const;\nexport type LlmProvider = (typeof LLM_PROVIDERS)[number];\n\n// Severity ordering, ranking, and threshold logic are the monorepo's single\n// source of truth in `@quantakrypto/core`. Re-export them here so existing\n// `@quantakrypto/qscan` callers (and tests) keep importing them from `./args.js`\n// without qScan maintaining a second, drift-prone copy.\nexport { meetsThreshold, SEVERITY_ORDER, severityRank };\n\n/**\n * Output formats qScan accepts on the command line. Extends core's\n * {@link ReportFormat} with `\"cbom\"` (a CycloneDX cryptographic bill of\n * materials), which qScan renders locally via core's `toCbom`.\n */\nexport type QscanFormat = ReportFormat | \"cbom\" | \"evidence\";\n\nconst FORMATS: readonly QscanFormat[] = [\"human\", \"json\", \"sarif\", \"cbom\", \"evidence\"];\n\n/** Fully-resolved options the CLI/programmatic runner operates on. */\nexport interface QscanOptions {\n /** Directory or file to scan. */\n path: string;\n /** Report format. */\n format: QscanFormat;\n /** Write the report to this file instead of stdout, when set. */\n output?: string;\n /** Findings at or above this severity cause a non-zero exit. */\n severityThreshold: Severity;\n /** Scan source files for inline crypto usage. */\n source: boolean;\n /** Scan dependency manifests for vulnerable libraries. */\n dependencies: boolean;\n /** Scan config files (TLS/certificates). */\n config: boolean;\n /** Extra exclude patterns (repeatable `--ignore`). */\n ignore: string[];\n /**\n * Restrict the walk to paths matching one of these include patterns\n * (repeatable `--include`). When empty, every non-excluded file is scanned.\n */\n include: string[];\n /** Max file size to read, in bytes (`--max-file-size`). */\n maxFileSize?: number;\n /** Disable the built-in ignore list (`--no-default-ignores`). */\n noDefaultIgnores: boolean;\n /** Scan minified/generated/bundled files instead of skipping them. */\n scanMinified: boolean;\n /**\n * Incremental mode: scan only the files git reports as changed\n * (`--changed`), optionally relative to {@link since}.\n */\n changed: boolean;\n /** Git ref/range the `--changed` diff is taken against (`--since`). */\n since?: string;\n /** Route the scan through core's worker-thread pool (`--parallel`). */\n parallel: boolean;\n /**\n * Worker count for parallel scanning (`--concurrency`). Implies parallel.\n * A value of 0 or 1 forces the in-process serial path.\n */\n concurrency?: number;\n /** Suppress findings whose fingerprint is in this baseline file. */\n baseline?: string;\n /** Write current findings as a baseline to this file, then exit 0. */\n writeBaseline?: string;\n /** Suppress the human summary banner (still writes reports/output files). */\n quiet: boolean;\n /** How many findings the human report lists (`--top N`). Default: 5. */\n topN?: number;\n /** Rule ids to suppress (from `quantakrypto.config.json` `disabledRules`). */\n disabledRules?: string[];\n /** Content-hash scan cache path (`--cache [path]`); reuse unchanged files. */\n cacheFile?: string;\n /** Run the BYOK LLM triage pass (`--triage`): annotate + re-sort, never suppress. */\n triage: boolean;\n /** Only triage findings at/above this seriousness (`--triage-floor`). Default: medium. */\n triageFloor?: Severity;\n /** Cap findings sent to the LLM during triage (`--max-findings`; spend guard). */\n maxFindings?: number;\n /** CNSA security tier for the migration-targets footer (`--tier`). Default: none. */\n tier?: SecurityTier;\n /** Org cryptography policy file (`--policy`) for the evidence report's §4 verdicts. */\n policy?: string;\n /** How much source context leaves the machine (`--context`). Default: snippet. */\n contextLevel?: ContextLevel;\n /** Print the exact triage payload and exit without calling the provider (`--dry-run`). */\n dryRun: boolean;\n /** BYOK provider (`--llm-provider`). Default: anthropic. */\n llmProvider?: LlmProvider;\n /** BYOK model id (`--llm-model`). */\n llmModel?: string;\n /**\n * Omit code snippets from the JSON/SARIF report (`--no-snippets`). Passed to\n * core's reporters as `{ redactSnippets: true }`. Snippets of `sensitive`\n * findings are always omitted regardless of this flag.\n */\n noSnippets: boolean;\n /**\n * Explicit path to a `quantakrypto.config.json` (`--config <path>`). Overrides\n * auto-discovery at the scan root. Distinct from `--no-config`, which toggles\n * config/TLS *detector* scanning — this names the config FILE.\n */\n configFile?: string;\n /**\n * Disable `quantakrypto.config.json` auto-discovery (`--no-config-file`). Distinct\n * from `--no-config` (which skips config-file *detectors*).\n */\n noConfigFile: boolean;\n}\n\n/**\n * Option keys that a `quantakrypto.config.json` may also set. When such a key was set\n * by a CLI flag, the flag wins (precedence: flags > config > defaults); when it\n * was left at its default, config may fill it. {@link parseArgs} records which\n * of these keys came from an explicit flag in {@link ParsedRun.explicit}.\n */\nexport type ConfigurableKey =\n | \"severityThreshold\"\n | \"source\"\n | \"dependencies\"\n | \"config\"\n | \"include\"\n | \"ignore\"\n | \"maxFileSize\"\n | \"noDefaultIgnores\"\n | \"scanMinified\"\n | \"baseline\";\n\n/** A successful parse: resolved options plus which configurable keys were explicit. */\nexport interface ParsedRun {\n kind: \"run\";\n options: QscanOptions;\n /** The set of {@link ConfigurableKey}s the user set via a flag. */\n explicit: Set<ConfigurableKey>;\n}\n\n/** Result of {@link parseArgs}: either resolved options or a meta action. */\nexport type ParsedArgs = ParsedRun | { kind: \"help\" } | { kind: \"version\" };\n\n/** Thrown on malformed input; the CLI maps this to exit code 2. */\nexport class ArgError extends Error {\n override readonly name = \"ArgError\";\n}\n\n/** Default options, before any flags are applied. */\nexport function defaultOptions(): QscanOptions {\n return {\n path: \".\",\n format: \"human\",\n severityThreshold: \"high\",\n source: true,\n dependencies: true,\n config: true,\n ignore: [],\n include: [],\n noDefaultIgnores: false,\n scanMinified: false,\n changed: false,\n parallel: false,\n quiet: false,\n noSnippets: false,\n noConfigFile: false,\n triage: false,\n dryRun: false,\n };\n}\n\n/**\n * Parse a raw argv slice (i.e. without `node` and the script path).\n *\n * @throws {ArgError} On unknown flags, missing values, or invalid enum values.\n */\n/** Default scan-cache file when `--cache` is given without a path. */\nexport const DEFAULT_CACHE_FILE = \".quantakrypto-cache.json\";\n\nexport function parseArgs(argv: readonly string[]): ParsedArgs {\n const options = defaultOptions();\n const explicit = new Set<ConfigurableKey>();\n let positional: string | undefined;\n\n // Manual index walk so flags can consume the following token as a value.\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i] as string;\n\n // `--flag=value` → split into flag + inline value.\n let inlineValue: string | undefined;\n let flag = arg;\n if (arg.startsWith(\"--\") && arg.includes(\"=\")) {\n const eq = arg.indexOf(\"=\");\n flag = arg.slice(0, eq);\n inlineValue = arg.slice(eq + 1);\n }\n\n /** Consume a value for `flag`: prefer the inline `=value`, else the next token. */\n const takeValue = (): string => {\n if (inlineValue !== undefined) return inlineValue;\n const next = argv[i + 1];\n if (next === undefined || (next.startsWith(\"-\") && next !== \"-\")) {\n throw new ArgError(`option \"${flag}\" requires a value`);\n }\n i++;\n return next;\n };\n\n /**\n * Reject an inline `=value` on a boolean flag. Without this, `--quiet=false`\n * would silently ignore the value and turn the flag ON — the opposite of the\n * caller's intent. Boolean flags take no value, so any `=value` is an error.\n */\n const rejectInlineValue = (): void => {\n if (inlineValue !== undefined) {\n throw new ArgError(`option \"${flag}\" is a boolean flag and takes no value`);\n }\n };\n\n switch (flag) {\n case \"-h\":\n case \"--help\":\n return { kind: \"help\" };\n case \"-v\":\n case \"--version\":\n return { kind: \"version\" };\n\n case \"--format\":\n options.format = asFormat(takeValue());\n break;\n case \"--cbom\":\n rejectInlineValue();\n options.format = \"cbom\";\n break;\n case \"-o\":\n case \"--output\":\n options.output = takeValue();\n break;\n case \"--severity-threshold\":\n options.severityThreshold = asSeverity(takeValue());\n explicit.add(\"severityThreshold\");\n break;\n\n case \"--no-source\":\n rejectInlineValue();\n options.source = false;\n explicit.add(\"source\");\n break;\n case \"--no-deps\":\n rejectInlineValue();\n options.dependencies = false;\n explicit.add(\"dependencies\");\n break;\n case \"--no-config\":\n rejectInlineValue();\n options.config = false;\n explicit.add(\"config\");\n break;\n\n case \"--ignore\":\n options.ignore.push(takeValue());\n explicit.add(\"ignore\");\n break;\n case \"--include\":\n options.include.push(takeValue());\n explicit.add(\"include\");\n break;\n case \"--max-file-size\":\n options.maxFileSize = asInt(takeValue(), \"--max-file-size\");\n explicit.add(\"maxFileSize\");\n break;\n case \"--top\":\n options.topN = asInt(takeValue(), \"--top\");\n break;\n case \"--triage\":\n rejectInlineValue();\n options.triage = true;\n break;\n case \"--triage-floor\":\n options.triageFloor = asSeverity(takeValue());\n break;\n case \"--max-findings\":\n options.maxFindings = asInt(takeValue(), \"--max-findings\");\n break;\n case \"--tier\":\n options.tier = asTier(takeValue());\n break;\n case \"--context\":\n options.contextLevel = asContextLevel(takeValue());\n break;\n case \"--dry-run\":\n rejectInlineValue();\n options.dryRun = true;\n break;\n case \"--llm-provider\":\n options.llmProvider = asProvider(takeValue());\n break;\n case \"--llm-model\":\n options.llmModel = takeValue();\n break;\n case \"--cache\": {\n // `--cache` alone uses the default file; `--cache <path>` names it.\n if (inlineValue !== undefined) {\n options.cacheFile = inlineValue;\n } else {\n const next = argv[i + 1];\n if (next !== undefined && !(next.startsWith(\"-\") && next !== \"-\")) {\n options.cacheFile = next;\n i++;\n } else {\n options.cacheFile = DEFAULT_CACHE_FILE;\n }\n }\n break;\n }\n case \"--no-default-ignores\":\n rejectInlineValue();\n options.noDefaultIgnores = true;\n explicit.add(\"noDefaultIgnores\");\n break;\n case \"--scan-minified\":\n rejectInlineValue();\n options.scanMinified = true;\n explicit.add(\"scanMinified\");\n break;\n\n // `quantakrypto.config.json` FILE controls (distinct from `--no-config`, which\n // toggles config/TLS *detector* scanning above).\n case \"--config\":\n options.configFile = takeValue();\n break;\n case \"--no-config-file\":\n rejectInlineValue();\n options.noConfigFile = true;\n break;\n\n case \"--changed\":\n rejectInlineValue();\n options.changed = true;\n break;\n case \"--since\":\n options.since = takeValue();\n options.changed = true; // --since implies incremental mode\n break;\n\n case \"--parallel\":\n rejectInlineValue();\n options.parallel = true;\n break;\n case \"--concurrency\": {\n const n = asInt(takeValue(), \"--concurrency\");\n options.concurrency = n;\n // `--concurrency 0` documents \"serial\": core treats <1 as \"auto\" (full\n // parallelism), so without this special-case 0 would do the OPPOSITE of\n // what's documented. 0 forces the in-process serial path; any value >= 1\n // implies parallel.\n options.parallel = n >= 1;\n break;\n }\n\n case \"--baseline\":\n options.baseline = takeValue();\n explicit.add(\"baseline\");\n break;\n case \"--policy\":\n options.policy = takeValue();\n break;\n case \"--write-baseline\":\n options.writeBaseline = takeValue();\n break;\n case \"--quiet\":\n rejectInlineValue();\n options.quiet = true;\n break;\n case \"--no-snippets\":\n rejectInlineValue();\n options.noSnippets = true;\n break;\n\n default:\n if (flag.startsWith(\"-\") && flag !== \"-\") {\n throw new ArgError(`unknown option \"${flag}\"`);\n }\n if (positional !== undefined) {\n throw new ArgError(\n `unexpected extra argument \"${arg}\" (path already set to \"${positional}\")`,\n );\n }\n positional = arg;\n break;\n }\n }\n\n if (positional !== undefined) options.path = positional;\n return { kind: \"run\", options, explicit };\n}\n\n/** Validate/normalize a `--format` value. */\nexport function asFormat(value: string): QscanFormat {\n if ((FORMATS as readonly string[]).includes(value)) return value as QscanFormat;\n throw new ArgError(`invalid --format \"${value}\" (expected one of: ${FORMATS.join(\", \")})`);\n}\n\n/** Validate/normalize a `--context` level. */\nexport function asContextLevel(value: string): ContextLevel {\n if ((CONTEXT_LEVELS as readonly string[]).includes(value)) return value as ContextLevel;\n throw new ArgError(\n `invalid --context \"${value}\" (expected one of: ${CONTEXT_LEVELS.join(\", \")})`,\n );\n}\n\n/** Validate/normalize a `--tier` value. */\nexport function asTier(value: string): SecurityTier {\n if ((SECURITY_TIERS as readonly string[]).includes(value)) return value as SecurityTier;\n throw new ArgError(`invalid --tier \"${value}\" (expected one of: ${SECURITY_TIERS.join(\", \")})`);\n}\n\n/** Validate/normalize a `--llm-provider` value. */\nexport function asProvider(value: string): LlmProvider {\n if ((LLM_PROVIDERS as readonly string[]).includes(value)) return value as LlmProvider;\n throw new ArgError(\n `invalid --llm-provider \"${value}\" (expected one of: ${LLM_PROVIDERS.join(\", \")})`,\n );\n}\n\n/** Validate/normalize a non-negative integer flag value. */\nexport function asInt(value: string, flag: string): number {\n if (!/^\\d+$/.test(value)) {\n throw new ArgError(`invalid ${flag} \"${value}\" (expected a non-negative integer)`);\n }\n return Number.parseInt(value, 10);\n}\n\n/** Validate/normalize a severity value. */\nexport function asSeverity(value: string): Severity {\n if ((SEVERITY_ORDER as readonly string[]).includes(value)) return value as Severity;\n throw new ArgError(`invalid severity \"${value}\" (expected one of: ${SEVERITY_ORDER.join(\", \")})`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Zero-dependency command-line argument parsing for qScan.\n *\n * Hand-rolled rather than pulled from a library to keep the package free of\n * runtime dependencies. The grammar is deliberately small: long flags\n * (`--flag`, `--flag value`, `--flag=value`), a couple of short aliases\n * (`-o`, `-v`, `-h`), repeatable `--ignore`, and a single optional positional\n * path. Unknown flags are a usage error.\n */\n\nimport {\n meetsThreshold,\n SEVERITY_ORDER,\n severityRank,\n standardsProfileIds,\n} from \"@quantakrypto/core\";\nimport type { ContextLevel, ReportFormat, SecurityTier, Severity } from \"@quantakrypto/core\";\nimport type { ColorChoice } from \"./color.js\";\n\n/** Valid context levels for `--context` (how much source triage/remediate sends). */\nconst CONTEXT_LEVELS: readonly ContextLevel[] = [\"metadata\", \"snippet\", \"function\", \"file\"];\n/** Valid CNSA security tiers for `--tier` (report migration-target guidance). */\nconst SECURITY_TIERS: readonly SecurityTier[] = [\"category-3\", \"category-5\"];\n/** Valid `--llm-provider` values. */\nconst LLM_PROVIDERS = [\"anthropic\", \"openai-compatible\"] as const;\nexport type LlmProvider = (typeof LLM_PROVIDERS)[number];\n\n// Severity ordering, ranking, and threshold logic are the monorepo's single\n// source of truth in `@quantakrypto/core`. Re-export them here so existing\n// `@quantakrypto/qscan` callers (and tests) keep importing them from `./args.js`\n// without qScan maintaining a second, drift-prone copy.\nexport { meetsThreshold, SEVERITY_ORDER, severityRank };\n\n/**\n * Output formats qScan accepts on the command line. Extends core's\n * {@link ReportFormat} with `\"cbom\"` (a CycloneDX cryptographic bill of\n * materials), `\"evidence\"` (ISO A.8.24 readiness report), and `\"vex\"` (an\n * OpenVEX 0.2.0 document) — all rendered locally via core (`toCbom`,\n * `buildReadinessReport`, `toOpenVex`).\n */\nexport type QscanFormat = ReportFormat | \"cbom\" | \"evidence\" | \"vex\";\n\nconst FORMATS: readonly QscanFormat[] = [\"human\", \"json\", \"sarif\", \"cbom\", \"evidence\", \"vex\"];\n\n/** Fully-resolved options the CLI/programmatic runner operates on. */\nexport interface QscanOptions {\n /** Directory or file to scan. */\n path: string;\n /** Report format. */\n format: QscanFormat;\n /** Write the report to this file instead of stdout, when set. */\n output?: string;\n /** External CBOM files to merge into the `--cbom` output (CycloneDX bom-link). */\n mergeCboms?: string[];\n /** Findings at or above this severity cause a non-zero exit. */\n severityThreshold: Severity;\n /** Scan source files for inline crypto usage. */\n source: boolean;\n /** Scan dependency manifests for vulnerable libraries. */\n dependencies: boolean;\n /** Scan config files (TLS/certificates). */\n config: boolean;\n /** Extra exclude patterns (repeatable `--ignore`). */\n ignore: string[];\n /**\n * Restrict the walk to paths matching one of these include patterns\n * (repeatable `--include`). When empty, every non-excluded file is scanned.\n */\n include: string[];\n /** Max file size to read, in bytes (`--max-file-size`). */\n maxFileSize?: number;\n /** Disable the built-in ignore list (`--no-default-ignores`). */\n noDefaultIgnores: boolean;\n /** Scan minified/generated/bundled files instead of skipping them. */\n scanMinified: boolean;\n /**\n * Incremental mode: scan only the files git reports as changed\n * (`--changed`), optionally relative to {@link since}.\n */\n changed: boolean;\n /** Git ref/range the `--changed` diff is taken against (`--since`). */\n since?: string;\n /** Route the scan through core's worker-thread pool (`--parallel`). */\n parallel: boolean;\n /**\n * Worker count for parallel scanning (`--concurrency`). Implies parallel.\n * A value of 0 or 1 forces the in-process serial path.\n */\n concurrency?: number;\n /** Suppress findings whose fingerprint is in this baseline file. */\n baseline?: string;\n /** Write current findings as a baseline to this file, then exit 0. */\n writeBaseline?: string;\n /** Suppress the human summary banner (still writes reports/output files). */\n quiet: boolean;\n /**\n * ANSI color policy for the human report (`--color` / `--no-color`). `\"auto\"`\n * (default) colors only a live terminal and honors `NO_COLOR` / `FORCE_COLOR`;\n * see {@link resolveColor}. Color is decoration only — never the sole signal.\n */\n colorChoice: ColorChoice;\n /** How many findings the human report lists (`--top N`). Default: 5. */\n topN?: number;\n /** Rule ids to suppress (from `quantakrypto.config.json` `disabledRules`). */\n disabledRules?: string[];\n /** Content-hash scan cache path (`--cache [path]`); reuse unchanged files. */\n cacheFile?: string;\n /** Run the BYOK LLM triage pass (`--triage`): annotate + re-sort, never suppress. */\n triage: boolean;\n /** Only triage findings at/above this seriousness (`--triage-floor`). Default: medium. */\n triageFloor?: Severity;\n /** Cap findings sent to the LLM during triage (`--max-findings`; spend guard). */\n maxFindings?: number;\n /** CNSA security tier for the migration-targets footer (`--tier`). Default: none. */\n tier?: SecurityTier;\n /**\n * Standards regime the migration guidance is tailored to (`--profile`): one of the\n * built-in ids (nist / cnsa-2.0 / bsi-tr-02102 / anssi / uk-ncsc). Default: none\n * (`--tier` maps to a profile for back-compat). Governs parameter sets, deadlines,\n * and the hybrid stance surfaced in remediation.\n */\n profile?: string;\n /** Org cryptography policy file (`--policy`) for the evidence report's §4 verdicts. */\n policy?: string;\n /**\n * External signer command for the evidence attestation (`--sign`). The report's\n * contentHash is piped to it on stdin; its stdout is recorded as the detached\n * signature. Only valid with `--format evidence`.\n */\n sign?: string;\n /** External RFC-3161 timestamper command for the evidence attestation (`--timestamp`). */\n timestamp?: string;\n /** How much source context leaves the machine (`--context`). Default: snippet. */\n contextLevel?: ContextLevel;\n /** Print the exact triage payload and exit without calling the provider (`--dry-run`). */\n dryRun: boolean;\n /** BYOK provider (`--llm-provider`). Default: anthropic. */\n llmProvider?: LlmProvider;\n /** BYOK model id (`--llm-model`). */\n llmModel?: string;\n /**\n * Omit code snippets from the JSON/SARIF report (`--no-snippets`). Passed to\n * core's reporters as `{ redactSnippets: true }`. Snippets of `sensitive`\n * findings are always omitted regardless of this flag.\n */\n noSnippets: boolean;\n /**\n * Explicit path to a `quantakrypto.config.json` (`--config <path>`). Overrides\n * auto-discovery at the scan root. Distinct from `--no-config`, which toggles\n * config/TLS *detector* scanning — this names the config FILE.\n */\n configFile?: string;\n /**\n * Disable `quantakrypto.config.json` auto-discovery (`--no-config-file`). Distinct\n * from `--no-config` (which skips config-file *detectors*).\n */\n noConfigFile: boolean;\n /**\n * Compute + emit HNDL (harvest-now-decrypt-later) exposure (`--hndl`). Reads\n * `hndl.yml` at the scan root, scores each finding + a repo summary, and adds\n * the exposure fields to the JSON / SARIF report. Additive: never changes the\n * exit code. See docs/HNDL.md.\n */\n hndl: boolean;\n /**\n * URL to a posture credential recorded in a crypto-agility manifest\n * (`--attestation`). Only consumed by `crypto-agility emit`; recorded verbatim,\n * never fetched (offline boundary). See docs/CRYPTO-AGILITY-MANIFEST.md.\n */\n attestation?: string;\n /**\n * Operator assertion of hybrid post-quantum key exchange for a crypto-agility\n * manifest (`--hybrid-kex` → true, `--no-hybrid-kex` → false). Left undefined,\n * the manifest reports `hybridKexInUse: null` (a static scan cannot observe a\n * negotiated TLS group). Only consumed by `crypto-agility emit`.\n */\n hybridKexInUse?: boolean;\n}\n\n/**\n * Option keys that a `quantakrypto.config.json` may also set. When such a key was set\n * by a CLI flag, the flag wins (precedence: flags > config > defaults); when it\n * was left at its default, config may fill it. {@link parseArgs} records which\n * of these keys came from an explicit flag in {@link ParsedRun.explicit}.\n */\nexport type ConfigurableKey =\n | \"severityThreshold\"\n | \"source\"\n | \"dependencies\"\n | \"config\"\n | \"include\"\n | \"ignore\"\n | \"maxFileSize\"\n | \"noDefaultIgnores\"\n | \"scanMinified\"\n | \"baseline\";\n\n/** A successful parse: resolved options plus which configurable keys were explicit. */\nexport interface ParsedRun {\n kind: \"run\";\n options: QscanOptions;\n /** The set of {@link ConfigurableKey}s the user set via a flag. */\n explicit: Set<ConfigurableKey>;\n}\n\n/** The `qscan hndl init` subcommand: scaffold an `hndl.yml`. */\nexport interface ParsedHndlInit {\n kind: \"hndl-init\";\n options: QscanOptions;\n}\n\n/**\n * Emit a crypto-agility manifest: either `qscan crypto-agility emit [path]` or the\n * `--crypto-agility` flag on a normal scan. Additive: it always exits 0, never\n * consulting the severity threshold.\n */\nexport interface ParsedCryptoAgilityEmit {\n kind: \"crypto-agility-emit\";\n options: QscanOptions;\n}\n\n/** Validate a local manifest file: `qscan crypto-agility validate <file>`. */\nexport interface ParsedCryptoAgilityValidate {\n kind: \"crypto-agility-validate\";\n /** Path to the manifest JSON file to check. */\n file: string;\n}\n\n/** Result of {@link parseArgs}: either resolved options or a meta action. */\nexport type ParsedArgs =\n | ParsedRun\n | ParsedHndlInit\n | ParsedCryptoAgilityEmit\n | ParsedCryptoAgilityValidate\n | { kind: \"help\" }\n | { kind: \"version\" };\n\n/** Thrown on malformed input; the CLI maps this to exit code 2. */\nexport class ArgError extends Error {\n override readonly name = \"ArgError\";\n}\n\n/** Default options, before any flags are applied. */\nexport function defaultOptions(): QscanOptions {\n return {\n path: \".\",\n format: \"human\",\n severityThreshold: \"high\",\n source: true,\n dependencies: true,\n config: true,\n ignore: [],\n include: [],\n noDefaultIgnores: false,\n scanMinified: false,\n changed: false,\n parallel: false,\n quiet: false,\n colorChoice: \"auto\",\n noSnippets: false,\n noConfigFile: false,\n triage: false,\n dryRun: false,\n hndl: false,\n };\n}\n\n/**\n * Parse a raw argv slice (i.e. without `node` and the script path).\n *\n * @throws {ArgError} On unknown flags, missing values, or invalid enum values.\n */\n/** Default scan-cache file when `--cache` is given without a path. */\nexport const DEFAULT_CACHE_FILE = \".quantakrypto-cache.json\";\n\nexport function parseArgs(argv: readonly string[]): ParsedArgs {\n // Subcommand dispatch: `qscan hndl <sub> …`. Only `init` exists today. `--help`\n // / `--version` anywhere still short-circuit to the meta actions (handled by\n // the shared loop below), so `qscan hndl init --help` shows help.\n if (argv[0] === \"hndl\") {\n const sub = argv[1];\n if (sub === undefined || sub.startsWith(\"-\")) {\n if (sub === \"--help\" || sub === \"-h\") return { kind: \"help\" };\n if (sub === \"--version\" || sub === \"-v\") return { kind: \"version\" };\n throw new ArgError(`\"hndl\" requires a subcommand (expected: init)`);\n }\n if (sub !== \"init\") {\n throw new ArgError(`unknown hndl subcommand \"${sub}\" (expected: init)`);\n }\n const parsed = parseRunArgs(argv.slice(2));\n if (parsed.kind !== \"run\") return parsed; // --help / --version passthrough\n return { kind: \"hndl-init\", options: parsed.options };\n }\n\n // Subcommand dispatch: `qscan crypto-agility <sub> …`.\n // emit [path] derive + write a manifest (always exits 0)\n // validate <file> check a local manifest against the schema\n if (argv[0] === \"crypto-agility\") {\n const sub = argv[1];\n if (sub === undefined || sub.startsWith(\"-\")) {\n if (sub === \"--help\" || sub === \"-h\") return { kind: \"help\" };\n if (sub === \"--version\" || sub === \"-v\") return { kind: \"version\" };\n throw new ArgError(`\"crypto-agility\" requires a subcommand (expected: emit, validate)`);\n }\n if (sub === \"emit\") {\n const parsed = parseRunArgs(argv.slice(2));\n // `--help`/`--version` short-circuit; a redundant `--crypto-agility` flag on\n // the emit subcommand already yields the emit kind (returned as-is).\n if (parsed.kind !== \"run\") return parsed;\n return { kind: \"crypto-agility-emit\", options: parsed.options };\n }\n if (sub === \"validate\") {\n const rest = argv.slice(2);\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) return { kind: \"help\" };\n if (rest.includes(\"--version\") || rest.includes(\"-v\")) return { kind: \"version\" };\n const positionals = rest.filter((a) => !(a.startsWith(\"-\") && a !== \"-\"));\n if (positionals.length === 0) {\n throw new ArgError(`\"crypto-agility validate\" requires a manifest file path`);\n }\n if (positionals.length > 1) {\n throw new ArgError(\n `\"crypto-agility validate\" takes exactly one file (got ${positionals.length})`,\n );\n }\n return { kind: \"crypto-agility-validate\", file: positionals[0] as string };\n }\n throw new ArgError(`unknown crypto-agility subcommand \"${sub}\" (expected: emit, validate)`);\n }\n return parseRunArgs(argv);\n}\n\n/** Parse the run-mode grammar (flags + a single optional positional path). */\nfunction parseRunArgs(argv: readonly string[]): ParsedArgs {\n const options = defaultOptions();\n const explicit = new Set<ConfigurableKey>();\n let positional: string | undefined;\n // Set by `--crypto-agility`: the whole run becomes a manifest emit (exit 0).\n let emitManifest = false;\n\n // Manual index walk so flags can consume the following token as a value.\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i] as string;\n\n // `--flag=value` → split into flag + inline value.\n let inlineValue: string | undefined;\n let flag = arg;\n if (arg.startsWith(\"--\") && arg.includes(\"=\")) {\n const eq = arg.indexOf(\"=\");\n flag = arg.slice(0, eq);\n inlineValue = arg.slice(eq + 1);\n }\n\n /** Consume a value for `flag`: prefer the inline `=value`, else the next token. */\n const takeValue = (): string => {\n if (inlineValue !== undefined) return inlineValue;\n const next = argv[i + 1];\n if (next === undefined || (next.startsWith(\"-\") && next !== \"-\")) {\n throw new ArgError(`option \"${flag}\" requires a value`);\n }\n i++;\n return next;\n };\n\n /**\n * Reject an inline `=value` on a boolean flag. Without this, `--quiet=false`\n * would silently ignore the value and turn the flag ON — the opposite of the\n * caller's intent. Boolean flags take no value, so any `=value` is an error.\n */\n const rejectInlineValue = (): void => {\n if (inlineValue !== undefined) {\n throw new ArgError(`option \"${flag}\" is a boolean flag and takes no value`);\n }\n };\n\n switch (flag) {\n case \"-h\":\n case \"--help\":\n return { kind: \"help\" };\n case \"-v\":\n case \"--version\":\n return { kind: \"version\" };\n\n case \"--format\":\n options.format = asFormat(takeValue());\n break;\n case \"--cbom\":\n rejectInlineValue();\n options.format = \"cbom\";\n break;\n case \"--merge\":\n // Merge an external CBOM (e.g. a qprobe endpoint CBOM) into the --cbom\n // output via CycloneDX bom-link. Repeatable.\n (options.mergeCboms ??= []).push(takeValue());\n break;\n case \"-o\":\n case \"--output\":\n options.output = takeValue();\n break;\n case \"--severity-threshold\":\n options.severityThreshold = asSeverity(takeValue());\n explicit.add(\"severityThreshold\");\n break;\n\n case \"--no-source\":\n rejectInlineValue();\n options.source = false;\n explicit.add(\"source\");\n break;\n case \"--no-deps\":\n rejectInlineValue();\n options.dependencies = false;\n explicit.add(\"dependencies\");\n break;\n case \"--no-config\":\n rejectInlineValue();\n options.config = false;\n explicit.add(\"config\");\n break;\n\n case \"--ignore\":\n options.ignore.push(takeValue());\n explicit.add(\"ignore\");\n break;\n case \"--include\":\n options.include.push(takeValue());\n explicit.add(\"include\");\n break;\n case \"--max-file-size\":\n options.maxFileSize = asInt(takeValue(), \"--max-file-size\");\n explicit.add(\"maxFileSize\");\n break;\n case \"--top\":\n options.topN = asInt(takeValue(), \"--top\");\n break;\n case \"--triage\":\n rejectInlineValue();\n options.triage = true;\n break;\n case \"--triage-floor\":\n options.triageFloor = asSeverity(takeValue());\n break;\n case \"--max-findings\":\n options.maxFindings = asInt(takeValue(), \"--max-findings\");\n break;\n case \"--tier\":\n options.tier = asTier(takeValue());\n break;\n case \"--profile\":\n options.profile = asProfile(takeValue());\n break;\n case \"--context\":\n options.contextLevel = asContextLevel(takeValue());\n break;\n case \"--dry-run\":\n rejectInlineValue();\n options.dryRun = true;\n break;\n case \"--llm-provider\":\n options.llmProvider = asProvider(takeValue());\n break;\n case \"--llm-model\":\n options.llmModel = takeValue();\n break;\n case \"--cache\": {\n // `--cache` alone uses the default file; `--cache <path>` names it.\n if (inlineValue !== undefined) {\n options.cacheFile = inlineValue;\n } else {\n const next = argv[i + 1];\n if (next !== undefined && !(next.startsWith(\"-\") && next !== \"-\")) {\n options.cacheFile = next;\n i++;\n } else {\n options.cacheFile = DEFAULT_CACHE_FILE;\n }\n }\n break;\n }\n case \"--no-default-ignores\":\n rejectInlineValue();\n options.noDefaultIgnores = true;\n explicit.add(\"noDefaultIgnores\");\n break;\n case \"--scan-minified\":\n rejectInlineValue();\n options.scanMinified = true;\n explicit.add(\"scanMinified\");\n break;\n\n // `quantakrypto.config.json` FILE controls (distinct from `--no-config`, which\n // toggles config/TLS *detector* scanning above).\n case \"--config\":\n options.configFile = takeValue();\n break;\n case \"--no-config-file\":\n rejectInlineValue();\n options.noConfigFile = true;\n break;\n\n case \"--changed\":\n rejectInlineValue();\n options.changed = true;\n break;\n case \"--since\":\n options.since = takeValue();\n options.changed = true; // --since implies incremental mode\n break;\n\n case \"--parallel\":\n rejectInlineValue();\n options.parallel = true;\n break;\n case \"--concurrency\": {\n const n = asInt(takeValue(), \"--concurrency\");\n options.concurrency = n;\n // `--concurrency 0` documents \"serial\": core treats <1 as \"auto\" (full\n // parallelism), so without this special-case 0 would do the OPPOSITE of\n // what's documented. 0 forces the in-process serial path; any value >= 1\n // implies parallel.\n options.parallel = n >= 1;\n break;\n }\n\n case \"--baseline\":\n options.baseline = takeValue();\n explicit.add(\"baseline\");\n break;\n case \"--policy\":\n options.policy = takeValue();\n break;\n case \"--sign\":\n options.sign = takeValue();\n break;\n case \"--timestamp\":\n options.timestamp = takeValue();\n break;\n case \"--write-baseline\":\n options.writeBaseline = takeValue();\n break;\n case \"--quiet\":\n rejectInlineValue();\n options.quiet = true;\n break;\n case \"--color\":\n rejectInlineValue();\n options.colorChoice = \"always\";\n break;\n case \"--no-color\":\n rejectInlineValue();\n options.colorChoice = \"never\";\n break;\n case \"--no-snippets\":\n rejectInlineValue();\n options.noSnippets = true;\n break;\n case \"--hndl\":\n rejectInlineValue();\n options.hndl = true;\n break;\n\n // Crypto-agility manifest controls (see `crypto-agility emit`).\n case \"--crypto-agility\":\n rejectInlineValue();\n emitManifest = true;\n break;\n case \"--attestation\":\n options.attestation = takeValue();\n break;\n case \"--hybrid-kex\":\n rejectInlineValue();\n options.hybridKexInUse = true;\n break;\n case \"--no-hybrid-kex\":\n rejectInlineValue();\n options.hybridKexInUse = false;\n break;\n\n default:\n if (flag.startsWith(\"-\") && flag !== \"-\") {\n throw new ArgError(`unknown option \"${flag}\"`);\n }\n if (positional !== undefined) {\n throw new ArgError(\n `unexpected extra argument \"${arg}\" (path already set to \"${positional}\")`,\n );\n }\n positional = arg;\n break;\n }\n }\n\n if (positional !== undefined) options.path = positional;\n // `--crypto-agility` turns the whole run into a manifest emit, taking it off the\n // findings-threshold exit path entirely (the emit always exits 0).\n if (emitManifest) return { kind: \"crypto-agility-emit\", options };\n return { kind: \"run\", options, explicit };\n}\n\n/** Validate/normalize a `--format` value. */\nexport function asFormat(value: string): QscanFormat {\n if ((FORMATS as readonly string[]).includes(value)) return value as QscanFormat;\n throw new ArgError(`invalid --format \"${value}\" (expected one of: ${FORMATS.join(\", \")})`);\n}\n\n/** Validate/normalize a `--context` level. */\nfunction asContextLevel(value: string): ContextLevel {\n if ((CONTEXT_LEVELS as readonly string[]).includes(value)) return value as ContextLevel;\n throw new ArgError(\n `invalid --context \"${value}\" (expected one of: ${CONTEXT_LEVELS.join(\", \")})`,\n );\n}\n\n/** Validate/normalize a `--tier` value. */\nfunction asTier(value: string): SecurityTier {\n if ((SECURITY_TIERS as readonly string[]).includes(value)) return value as SecurityTier;\n throw new ArgError(`invalid --tier \"${value}\" (expected one of: ${SECURITY_TIERS.join(\", \")})`);\n}\n\n/** Validate a `--profile` value against the built-in standards regimes. */\nfunction asProfile(value: string): string {\n const ids = standardsProfileIds();\n if (ids.includes(value)) return value;\n throw new ArgError(`invalid --profile \"${value}\" (expected one of: ${ids.join(\", \")})`);\n}\n\n/** Validate/normalize a `--llm-provider` value. */\nfunction asProvider(value: string): LlmProvider {\n if ((LLM_PROVIDERS as readonly string[]).includes(value)) return value as LlmProvider;\n throw new ArgError(\n `invalid --llm-provider \"${value}\" (expected one of: ${LLM_PROVIDERS.join(\", \")})`,\n );\n}\n\n/** Validate/normalize a non-negative integer flag value. */\nexport function asInt(value: string, flag: string): number {\n if (!/^\\d+$/.test(value)) {\n throw new ArgError(`invalid ${flag} \"${value}\" (expected a non-negative integer)`);\n }\n return Number.parseInt(value, 10);\n}\n\n/** Validate/normalize a severity value. */\nexport function asSeverity(value: string): Severity {\n if ((SEVERITY_ORDER as readonly string[]).includes(value)) return value as Severity;\n throw new ArgError(`invalid severity \"${value}\" (expected one of: ${SEVERITY_ORDER.join(\", \")})`);\n}\n"]}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAuBH,2EAA2E;AAC3E,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmMnE"}
|