@cdxgen/cdxgen 13.6.0 → 13.7.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 +15 -8
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +256 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +25 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +18 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +52 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +80 -1
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +609 -898
- package/lib/cli/jsBom.js +3 -0
- package/lib/cli/jvmBom.js +365 -40
- package/lib/cli/managedBom.js +19 -3
- package/lib/cli/nativeBom.js +10 -0
- package/lib/core/env.js +26 -0
- package/lib/core/fs.js +126 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/processTree.js +99 -12
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +15 -1
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1082 -6
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-python.js +89 -28
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalasem.js +2 -1
- package/lib/evinser/evinser.js +196 -34
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +112 -1
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +106 -13
- package/lib/inventory/dosai.js +236 -1
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +164 -14
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +132 -38
- package/lib/inventory/evidenceUtils.js +2 -1
- package/lib/inventory/formulationParsers.js +95 -13
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/source.js +65 -6
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/server/server.js +36 -34
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/validator/bomValidator.js +8 -1
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +48 -7
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +9 -9
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +16 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +2 -1
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +30 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -1
- package/types/lib/core/env.d.ts +10 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +16 -5
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts.map +1 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +248 -8
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +61 -9
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +19 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +51 -4
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -1
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +22 -6
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +15 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summarize Kiro CLI V3 permission documents into policy-safe posture facts.
|
|
3
|
+
*
|
|
4
|
+
* Kiro V3 describes what an agent may do with `capability`/`effect` rules that
|
|
5
|
+
* live in an agent definition's `permissions` object, in the user-scope
|
|
6
|
+
* `~/.kiro/settings/permissions.yaml`, and in the per-workspace
|
|
7
|
+
* `~/.kiro/workspace-roots/<hash>/permissions.yaml`. The rules carry `match`
|
|
8
|
+
* pattern lists, free-text reasons, and paths, none of which belong in a BOM.
|
|
9
|
+
* This module reduces a document to counts, allowlisted effect counts,
|
|
10
|
+
* validated capability names, and booleans, and never returns the patterns or
|
|
11
|
+
* any other free text.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Effects documented at kiro.dev/docs/permissions. An unknown effect is
|
|
15
|
+
// counted by `ruleCount` alone and by no per-effect counter.
|
|
16
|
+
const KIRO_EFFECTS = new Set(["allow", "deny", "ask", "evaluate"]);
|
|
17
|
+
|
|
18
|
+
// Policy presets that may be listed under the top-level `policies` key.
|
|
19
|
+
// kiro.dev documents `approve-for-me`; other preset names are dropped rather
|
|
20
|
+
// than copied, because the full set is not documented.
|
|
21
|
+
const KIRO_POLICY_PRESET_ALLOWLIST = new Set(["approve-for-me"]);
|
|
22
|
+
|
|
23
|
+
// A capability is a short lowercase token such as `fs_read`, `shell`, or the
|
|
24
|
+
// meta-capability `all`. Anything outside this shape is dropped instead of
|
|
25
|
+
// being copied into the BOM.
|
|
26
|
+
const KIRO_CAPABILITY_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/u;
|
|
27
|
+
|
|
28
|
+
const isPlainEntry = (value) =>
|
|
29
|
+
value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30
|
+
|
|
31
|
+
const sortedUnique = (values) => [...new Set(values)].sort();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Decide whether a rule's `match` list holds at least one non-empty pattern.
|
|
35
|
+
*
|
|
36
|
+
* @param {unknown} match The rule's match value
|
|
37
|
+
* @returns {boolean} True when a non-empty string pattern is present
|
|
38
|
+
*/
|
|
39
|
+
const hasNonEmptyMatch = (match) =>
|
|
40
|
+
Array.isArray(match) &&
|
|
41
|
+
match.some((entry) => typeof entry === "string" && entry.trim() !== "");
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Summarize a Kiro V3 permission document.
|
|
45
|
+
*
|
|
46
|
+
* Accepts the parsed `permissions` object of an agent definition or a parsed
|
|
47
|
+
* `permissions.yaml` document. A bare rules array is accepted as well. The
|
|
48
|
+
* result carries only counts, booleans, and validated token lists; `match`
|
|
49
|
+
* patterns, `exclude` lists, reasons, and paths are never returned.
|
|
50
|
+
*
|
|
51
|
+
* @param {Object|Array|undefined} rulesOrDoc Parsed permissions object, YAML
|
|
52
|
+
* document, or rules array
|
|
53
|
+
* @returns {{
|
|
54
|
+
* ruleCount: number,
|
|
55
|
+
* allowRuleCount: number,
|
|
56
|
+
* denyRuleCount: number,
|
|
57
|
+
* askRuleCount: number,
|
|
58
|
+
* evaluateRuleCount: number,
|
|
59
|
+
* capabilities: string[],
|
|
60
|
+
* allowsAllCapabilities: boolean,
|
|
61
|
+
* unrestrictedAllowCapabilities: string[],
|
|
62
|
+
* workspaceTrusted: boolean|undefined,
|
|
63
|
+
* policyPresets: string[],
|
|
64
|
+
* unknownPolicyPresetCount: number,
|
|
65
|
+
* }} Permission posture summary
|
|
66
|
+
*/
|
|
67
|
+
export function summarizeKiroPermissions(rulesOrDoc) {
|
|
68
|
+
const doc = Array.isArray(rulesOrDoc) ? { rules: rulesOrDoc } : rulesOrDoc;
|
|
69
|
+
const rules = Array.isArray(doc?.rules) ? doc.rules : [];
|
|
70
|
+
let ruleCount = 0;
|
|
71
|
+
const effectCounts = { allow: 0, deny: 0, ask: 0, evaluate: 0 };
|
|
72
|
+
const capabilities = [];
|
|
73
|
+
const unrestrictedAllowCapabilities = [];
|
|
74
|
+
let allowsAllCapabilities = false;
|
|
75
|
+
for (const rule of rules) {
|
|
76
|
+
if (!isPlainEntry(rule)) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
ruleCount += 1;
|
|
80
|
+
if (typeof rule.effect === "string" && KIRO_EFFECTS.has(rule.effect)) {
|
|
81
|
+
effectCounts[rule.effect] += 1;
|
|
82
|
+
}
|
|
83
|
+
if (typeof rule.capability === "string") {
|
|
84
|
+
const capability = rule.capability;
|
|
85
|
+
if (KIRO_CAPABILITY_PATTERN.test(capability)) {
|
|
86
|
+
capabilities.push(capability);
|
|
87
|
+
if (rule.effect === "allow" && !hasNonEmptyMatch(rule.match)) {
|
|
88
|
+
unrestrictedAllowCapabilities.push(capability);
|
|
89
|
+
if (capability === "all") {
|
|
90
|
+
allowsAllCapabilities = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const listedPresets = Array.isArray(doc?.policies)
|
|
97
|
+
? doc.policies.filter((entry) => typeof entry === "string")
|
|
98
|
+
: [];
|
|
99
|
+
// Preset names outside the allowlist are counted, never copied, so a
|
|
100
|
+
// reviewer still learns that an unrecognised preset is active.
|
|
101
|
+
const policyPresets = listedPresets.filter((entry) =>
|
|
102
|
+
KIRO_POLICY_PRESET_ALLOWLIST.has(entry),
|
|
103
|
+
);
|
|
104
|
+
const unknownPolicyPresetCount = new Set(
|
|
105
|
+
listedPresets.filter((entry) => !KIRO_POLICY_PRESET_ALLOWLIST.has(entry)),
|
|
106
|
+
).size;
|
|
107
|
+
return {
|
|
108
|
+
allowRuleCount: effectCounts.allow,
|
|
109
|
+
allowsAllCapabilities,
|
|
110
|
+
askRuleCount: effectCounts.ask,
|
|
111
|
+
capabilities: sortedUnique(capabilities),
|
|
112
|
+
denyRuleCount: effectCounts.deny,
|
|
113
|
+
evaluateRuleCount: effectCounts.evaluate,
|
|
114
|
+
policyPresets: sortedUnique(policyPresets),
|
|
115
|
+
ruleCount,
|
|
116
|
+
unknownPolicyPresetCount,
|
|
117
|
+
unrestrictedAllowCapabilities: sortedUnique(unrestrictedAllowCapabilities),
|
|
118
|
+
...(typeof doc?.workspaceTrusted === "boolean"
|
|
119
|
+
? { workspaceTrusted: doc.workspaceTrusted }
|
|
120
|
+
: {}),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Flatten a permission summary into property suffix/value pairs.
|
|
126
|
+
*
|
|
127
|
+
* Both scans that consume Kiro permission documents emit the same suffixes;
|
|
128
|
+
* the host scan prefixes them with `cdx:agentic:` and the project scan with
|
|
129
|
+
* `cdx:agent:`. Values are numbers, booleans, or comma-separated validated
|
|
130
|
+
* tokens, so no free text reaches a BOM through this mapping.
|
|
131
|
+
*
|
|
132
|
+
* @param {ReturnType<summarizeKiroPermissions>} summary Permission posture summary
|
|
133
|
+
* @returns {Record<string, number|boolean|string>} Property suffix mapped to its value
|
|
134
|
+
*/
|
|
135
|
+
export function kiroPermissionSummaryEntries(summary) {
|
|
136
|
+
const entries = {
|
|
137
|
+
permissionAllowRuleCount: summary.allowRuleCount,
|
|
138
|
+
permissionAllowsAll: Boolean(summary.allowsAllCapabilities),
|
|
139
|
+
permissionAskRuleCount: summary.askRuleCount,
|
|
140
|
+
permissionDenyRuleCount: summary.denyRuleCount,
|
|
141
|
+
permissionEvaluateRuleCount: summary.evaluateRuleCount,
|
|
142
|
+
permissionRuleCount: summary.ruleCount,
|
|
143
|
+
};
|
|
144
|
+
// An empty list carries no information, so the property is omitted instead
|
|
145
|
+
// of being emitted with an empty value.
|
|
146
|
+
for (const [suffix, list] of [
|
|
147
|
+
["permissionCapabilities", summary.capabilities],
|
|
148
|
+
[
|
|
149
|
+
"permissionUnrestrictedAllowCapabilities",
|
|
150
|
+
summary.unrestrictedAllowCapabilities,
|
|
151
|
+
],
|
|
152
|
+
["permissionPolicyPresets", summary.policyPresets],
|
|
153
|
+
]) {
|
|
154
|
+
if (list?.length) {
|
|
155
|
+
entries[suffix] = list.join(",");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (summary.unknownPolicyPresetCount) {
|
|
159
|
+
entries.permissionUnknownPolicyPresetCount =
|
|
160
|
+
summary.unknownPolicyPresetCount;
|
|
161
|
+
}
|
|
162
|
+
if (typeof summary.workspaceTrusted === "boolean") {
|
|
163
|
+
entries.permissionWorkspaceTrusted = summary.workspaceTrusted;
|
|
164
|
+
}
|
|
165
|
+
return entries;
|
|
166
|
+
}
|
package/lib/server/server.js
CHANGED
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
isSecureMode,
|
|
15
15
|
readEnvironmentVariable,
|
|
16
16
|
} from "../core/activity.js";
|
|
17
|
-
import {
|
|
17
|
+
import { HOST_SCOPE_PROJECT_TYPES } from "../core/env.js";
|
|
18
|
+
import {
|
|
19
|
+
boundUntrustedGlobPatterns,
|
|
20
|
+
UNTRUSTED_GLOB_EXPANSION_BUDGET,
|
|
21
|
+
UNTRUSTED_GLOB_PATTERN_MAX_LENGTH,
|
|
22
|
+
} from "../core/globPatterns.js";
|
|
18
23
|
import { isWin } from "../core/paths.js";
|
|
19
24
|
import { isSecureModeActive } from "../core/projectTooling.js";
|
|
20
25
|
import { resetRunState } from "../core/runState.js";
|
|
@@ -22,7 +27,11 @@ import { CDXGEN_VERSION } from "../core/state.js";
|
|
|
22
27
|
import { installConsoleShim, ui } from "../core/ui.js";
|
|
23
28
|
import { fetchPomXmlAsJson } from "../ecosystems/ecosystems.js";
|
|
24
29
|
import { normalizeOutputFormats } from "../helpers/exportUtils.js";
|
|
25
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
isCycloneDx20SpecVersion,
|
|
32
|
+
isCycloneDxBom,
|
|
33
|
+
} from "../inventory/bomUtils.js";
|
|
34
|
+
import { DEPENDENCY_TRACK_CDX20_ERROR } from "../inventory/cyclonedx20.js";
|
|
26
35
|
import {
|
|
27
36
|
cleanupSourceDir,
|
|
28
37
|
findGitRefForPurlVersion,
|
|
@@ -227,27 +236,6 @@ function restrictRequestOptions(options, operatorOptions) {
|
|
|
227
236
|
}
|
|
228
237
|
}
|
|
229
238
|
|
|
230
|
-
// Project types that inventory the host the server runs on, such as installed
|
|
231
|
-
// packages, users, shell history, IDE and browser extensions, or the Maven,
|
|
232
|
-
// Gradle, sbt, Cargo and Helm caches in the server user's home directory.
|
|
233
|
-
// They ignore the scan path, so the path allowlist does not limit them.
|
|
234
|
-
const HOST_SCOPE_PROJECT_TYPES = new Set(
|
|
235
|
-
[
|
|
236
|
-
"os",
|
|
237
|
-
"hbom",
|
|
238
|
-
"cargo-cache",
|
|
239
|
-
"helm-index",
|
|
240
|
-
"gradle-index",
|
|
241
|
-
"sbt-index",
|
|
242
|
-
"maven-index",
|
|
243
|
-
"vscode-extension",
|
|
244
|
-
"chrome-extension",
|
|
245
|
-
"agentic",
|
|
246
|
-
]
|
|
247
|
-
.flatMap((key) => PROJECT_TYPE_ALIASES[key] || [key])
|
|
248
|
-
.concat(["maven-repo"]),
|
|
249
|
-
);
|
|
250
|
-
|
|
251
239
|
/**
|
|
252
240
|
* Check request options that the server must refuse outright.
|
|
253
241
|
*
|
|
@@ -270,22 +258,18 @@ export function validateRequestOptions(reqOptions, operatorOptions = {}) {
|
|
|
270
258
|
details: `The '${hostScopeType}' project type scans the server host. Start the server with this type to allow it.`,
|
|
271
259
|
};
|
|
272
260
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
// Brace patterns expand before matching, so one short pattern such as
|
|
277
|
-
// {1..100000} can keep the server busy for minutes.
|
|
261
|
+
// Every exclude pattern is matched against every file the scan walks, and
|
|
262
|
+
// brace patterns expand before matching, so one short pattern such as
|
|
263
|
+
// {1..100000}, or a long enough list, can keep the server busy for minutes.
|
|
278
264
|
if (
|
|
279
265
|
reqOptions.exclude !== operatorOptions.exclude &&
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
)
|
|
266
|
+
boundUntrustedGlobPatterns(reqOptions.exclude, { allowBraces: false })
|
|
267
|
+
.refused.length
|
|
283
268
|
) {
|
|
284
269
|
return {
|
|
285
270
|
status: 400,
|
|
286
271
|
error: "Invalid Exclude Pattern",
|
|
287
|
-
details:
|
|
288
|
-
"Exclude patterns sent to the server cannot use braces or exceed 512 characters.",
|
|
272
|
+
details: `Exclude patterns sent to the server cannot use braces, exceed ${UNTRUSTED_GLOB_PATTERN_MAX_LENGTH} characters, or number more than ${UNTRUSTED_GLOB_EXPANSION_BUDGET}.`,
|
|
289
273
|
};
|
|
290
274
|
}
|
|
291
275
|
if (
|
|
@@ -333,6 +317,19 @@ export function validateRequestOptions(reqOptions, operatorOptions = {}) {
|
|
|
333
317
|
"Formulation data may contain secrets and is not submitted to Dependency-Track in secure mode.",
|
|
334
318
|
};
|
|
335
319
|
}
|
|
320
|
+
// Dependency-Track ingests CycloneDX 1.x only, so a request that would
|
|
321
|
+
// upload (server URL plus API key) cannot ask for the 2.0 draft.
|
|
322
|
+
if (
|
|
323
|
+
reqOptions.serverUrl &&
|
|
324
|
+
reqOptions.apiKey &&
|
|
325
|
+
isCycloneDx20SpecVersion(reqOptions.specVersion)
|
|
326
|
+
) {
|
|
327
|
+
return {
|
|
328
|
+
status: 400,
|
|
329
|
+
error: "Unsupported Spec Version For Dependency-Track",
|
|
330
|
+
details: DEPENDENCY_TRACK_CDX20_ERROR,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
336
333
|
return null;
|
|
337
334
|
}
|
|
338
335
|
|
|
@@ -749,7 +746,12 @@ const start = (options) => {
|
|
|
749
746
|
requestedFormats.includes("spdx") &&
|
|
750
747
|
isCycloneDxBom(bomNSData?.bomJson)
|
|
751
748
|
) {
|
|
752
|
-
|
|
749
|
+
// The SPDX converter reads the 1.x shape; at 2.0 that is the
|
|
750
|
+
// internal model rather than the rendered document.
|
|
751
|
+
responseBomJson = convertCycloneDxToSpdx(
|
|
752
|
+
bomNSData.internalBomJson ?? bomNSData.bomJson,
|
|
753
|
+
reqOptions,
|
|
754
|
+
);
|
|
753
755
|
}
|
|
754
756
|
if (reqOptions.serverUrl && reqOptions.apiKey) {
|
|
755
757
|
let serverHostname;
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "../../inventory/aiInventory.js";
|
|
32
32
|
import {
|
|
33
33
|
DEFAULT_CDX_SPEC_VERSION,
|
|
34
|
+
isCycloneDx20SpecVersion,
|
|
34
35
|
normalizeCycloneDxComponentTypeFilter,
|
|
35
36
|
normalizeCycloneDxSpecVersion,
|
|
36
37
|
} from "../../inventory/bomUtils.js";
|
|
@@ -40,8 +41,13 @@ import {
|
|
|
40
41
|
createCitation,
|
|
41
42
|
findCdxgenToolBomRef,
|
|
42
43
|
} from "../../inventory/citations.js";
|
|
44
|
+
import {
|
|
45
|
+
CDX20_INTERNAL_SECTIONS_KEY,
|
|
46
|
+
renderCycloneDx20,
|
|
47
|
+
} from "../../inventory/cyclonedx20.js";
|
|
43
48
|
import { mergeDependencies, mergeServices } from "../../inventory/depsUtils.js";
|
|
44
49
|
import { addFormulationSection } from "../../inventory/formulationParsers.js";
|
|
50
|
+
import { hardwareRenderContext } from "../../inventory/hbomLoader.js";
|
|
45
51
|
import { getContainerFileInventoryStats } from "../../inventory/inventoryStats.js";
|
|
46
52
|
import { enhanceBom } from "../../inventory/licenseEnhancer.js";
|
|
47
53
|
import { applyMcpPinningState } from "../../inventory/mcpPinning.js";
|
|
@@ -546,6 +552,13 @@ async function applyIntrospection(bomNSData, options, filePath) {
|
|
|
546
552
|
/**
|
|
547
553
|
* Filter and enhance BOM post generation.
|
|
548
554
|
*
|
|
555
|
+
* At CycloneDX 2.0 the returned `bomNSData` carries two documents:
|
|
556
|
+
* `bomJson` is the rendered 2.0 document (what library users, the server and
|
|
557
|
+
* the writer see), and `internalBomJson` is the 1.x-shaped model the audit,
|
|
558
|
+
* evinse, display and SPDX-export readers use. `internalBomJson` is never
|
|
559
|
+
* serialized; `refreshRenderedBom` re-renders `bomJson` from it after any
|
|
560
|
+
* later mutation. At 1.x `internalBomJson` is unset.
|
|
561
|
+
*
|
|
549
562
|
* @param {Object} bomNSData BOM with namespaces object
|
|
550
563
|
* @param {Object} options CLI options
|
|
551
564
|
* @param {string} [filePath] Source path used for formulation and metadata context
|
|
@@ -615,10 +628,37 @@ export async function postProcess(bomNSData, options, filePath) {
|
|
|
615
628
|
]);
|
|
616
629
|
cleanupEnv(options);
|
|
617
630
|
cleanupTmpDir();
|
|
618
|
-
|
|
631
|
+
// A model read from another 2.0 document keeps that document's originals,
|
|
632
|
+
// keyed by the exact 1.x form of each object, so an unchanged object
|
|
633
|
+
// renders back as it was. Sorting would change those forms, so such a
|
|
634
|
+
// model keeps its order; cdxgen's own BOMs are sorted for determinism.
|
|
635
|
+
if (!bomNSData.bomJson?.[CDX20_INTERNAL_SECTIONS_KEY]?.shadows) {
|
|
636
|
+
sortBomCollections(bomNSData.bomJson);
|
|
637
|
+
}
|
|
619
638
|
// Reflection reads the finished BOM, so it runs after sorting; it returns
|
|
620
639
|
// its verdict alongside the BOM instead of mutating it.
|
|
621
640
|
await applyIntrospection(bomNSData, options, filePath);
|
|
641
|
+
// CycloneDX 2.0: everything above produced the 1.x-shaped model. Keep it on
|
|
642
|
+
// `internalBomJson` for the readers that run after postProcess (audit,
|
|
643
|
+
// evinse, display, SPDX export) and render the 2.0 document once, here.
|
|
644
|
+
// `refreshRenderedBom` re-renders after any later mutation of the model,
|
|
645
|
+
// with the same render context (the optional cdx-hbom hardware mapper,
|
|
646
|
+
// loaded only when the model has hardware components).
|
|
647
|
+
// At 1.x both stay untouched, so those outputs are byte-identical. The
|
|
648
|
+
// document's own specVersion decides when the caller passed none, which is
|
|
649
|
+
// how an evinse run over a 2.0 input stays at 2.0.
|
|
650
|
+
if (
|
|
651
|
+
isCycloneDx20SpecVersion(
|
|
652
|
+
options.specVersion ?? bomNSData.bomJson?.specVersion,
|
|
653
|
+
)
|
|
654
|
+
) {
|
|
655
|
+
bomNSData.renderContext = await hardwareRenderContext(bomNSData.bomJson);
|
|
656
|
+
bomNSData.internalBomJson = bomNSData.bomJson;
|
|
657
|
+
bomNSData.bomJson = renderCycloneDx20(
|
|
658
|
+
bomNSData.bomJson,
|
|
659
|
+
bomNSData.renderContext,
|
|
660
|
+
);
|
|
661
|
+
}
|
|
622
662
|
return bomNSData;
|
|
623
663
|
}
|
|
624
664
|
|
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
setCycloneDxFormat,
|
|
28
28
|
toCycloneDxSpecVersionString,
|
|
29
29
|
} from "../../inventory/bomUtils.js";
|
|
30
|
+
import { CDX20_INTERNAL_SECTIONS_KEY } from "../../inventory/cyclonedx20.js";
|
|
31
|
+
import { markInternalModel } from "../../inventory/cyclonedx20ReadContext.js";
|
|
30
32
|
|
|
31
33
|
const COMPONENT_1_6_ONLY_FIELDS = new Set([
|
|
32
34
|
"authors",
|
|
@@ -115,9 +117,17 @@ function normalizeMetadataForSpecVersion(subject, specVersion) {
|
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
function normalizeBomForSpecVersion(subject, specVersion) {
|
|
120
|
+
if (!subject) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
118
123
|
if (specVersion < 1.7) {
|
|
119
124
|
deleteFields(subject, BOM_1_7_ONLY_FIELDS);
|
|
120
125
|
}
|
|
126
|
+
if (specVersion < 2) {
|
|
127
|
+
// 2.0-only sections ride through the internal model under this key
|
|
128
|
+
// (see lib/inventory/cyclonedx20.js); a 1.x document never serializes it.
|
|
129
|
+
delete subject[CDX20_INTERNAL_SECTIONS_KEY];
|
|
130
|
+
}
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
function normalizeDependencyForSpecVersion(subject, specVersion) {
|
|
@@ -713,6 +723,9 @@ export function applySpecVersionCompatibility(bomJson, options) {
|
|
|
713
723
|
downgradeSubjectForSpecVersion(bomJson, specVersion);
|
|
714
724
|
} else if (isCycloneDx20SpecVersion(specVersion)) {
|
|
715
725
|
upgradeSubjectForSpecVersion(bomJson, specVersion);
|
|
726
|
+
// The result is the 1.x-shaped model labelled 2.0, not a 2.0 document;
|
|
727
|
+
// the mark tells loadBomForAnalysis not to read it as one.
|
|
728
|
+
markInternalModel(bomJson);
|
|
716
729
|
}
|
|
717
730
|
return setCycloneDxFormat(bomJson, normalizedSpecVersion);
|
|
718
731
|
}
|
|
@@ -763,3 +776,66 @@ export function diffRemovedFieldPaths(sourceBomJson, normalizedBomJson) {
|
|
|
763
776
|
.filter((path) => !retainedPaths.has(path))
|
|
764
777
|
.sort();
|
|
765
778
|
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Count the leaf values of a JSON document as `path=value` strings, using
|
|
782
|
+
* the dotted, index-free paths of collectFieldPaths. Array order is ignored,
|
|
783
|
+
* so two documents that differ only in member order give the same counts,
|
|
784
|
+
* but a repeated entry counts once per occurrence. Empty arrays and objects
|
|
785
|
+
* count as leaves.
|
|
786
|
+
*
|
|
787
|
+
* @param {*} subject JSON value
|
|
788
|
+
* @param {string} [prefix] Path so far
|
|
789
|
+
* @param {Map<string, number>} [leaves] Accumulator
|
|
790
|
+
* @returns {Map<string, number>} Occurrences of each `path=value` string
|
|
791
|
+
*/
|
|
792
|
+
export function collectLeafValues(subject, prefix = "", leaves = new Map()) {
|
|
793
|
+
const add = (leaf) => {
|
|
794
|
+
leaves.set(leaf, (leaves.get(leaf) || 0) + 1);
|
|
795
|
+
};
|
|
796
|
+
if (Array.isArray(subject)) {
|
|
797
|
+
if (!subject.length) {
|
|
798
|
+
add(`${prefix}=[]`);
|
|
799
|
+
}
|
|
800
|
+
for (const entry of subject) {
|
|
801
|
+
collectLeafValues(entry, prefix, leaves);
|
|
802
|
+
}
|
|
803
|
+
return leaves;
|
|
804
|
+
}
|
|
805
|
+
if (isObjectRecord(subject)) {
|
|
806
|
+
const entries = Object.entries(subject);
|
|
807
|
+
if (!entries.length) {
|
|
808
|
+
add(`${prefix}={}`);
|
|
809
|
+
}
|
|
810
|
+
for (const [key, value] of entries) {
|
|
811
|
+
collectLeafValues(value, prefix ? `${prefix}.${key}` : key, leaves);
|
|
812
|
+
}
|
|
813
|
+
return leaves;
|
|
814
|
+
}
|
|
815
|
+
if (subject !== undefined) {
|
|
816
|
+
add(`${prefix}=${JSON.stringify(subject)}`);
|
|
817
|
+
}
|
|
818
|
+
return leaves;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Report the leaf values of `sourceBomJson` that `convertedBomJson` lacks,
|
|
823
|
+
* ignoring member order (see collectLeafValues). A value the source holds
|
|
824
|
+
* more often than the output is reported once for every missing occurrence,
|
|
825
|
+
* so dropping one of two identical entries counts.
|
|
826
|
+
*
|
|
827
|
+
* @param {Object} sourceBomJson BOM before conversion
|
|
828
|
+
* @param {Object} convertedBomJson BOM after conversion
|
|
829
|
+
* @returns {string[]} Sorted `path=value` strings missing from the output,
|
|
830
|
+
* repeated per missing occurrence
|
|
831
|
+
*/
|
|
832
|
+
export function diffMissingLeafValues(sourceBomJson, convertedBomJson) {
|
|
833
|
+
const retained = collectLeafValues(convertedBomJson);
|
|
834
|
+
const missing = [];
|
|
835
|
+
for (const [leaf, count] of collectLeafValues(sourceBomJson)) {
|
|
836
|
+
for (let i = retained.get(leaf) || 0; i < count; i++) {
|
|
837
|
+
missing.push(leaf);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return missing.sort();
|
|
841
|
+
}
|
|
@@ -55,11 +55,18 @@ const compileSchemaValidator = (specVersion) => {
|
|
|
55
55
|
const ajv = new Ajv2020(AJV_OPTIONS);
|
|
56
56
|
useLinearUniqueItems(ajv);
|
|
57
57
|
addCycloneDxFormats(ajv);
|
|
58
|
+
// The 2.0 draft pins its own cryptography definitions; the 1.7 schema
|
|
59
|
+
// keeps reading data/cryptography-defs.schema.json below.
|
|
58
60
|
addDraft2020BundledSchema(
|
|
59
61
|
ajv,
|
|
60
|
-
readJsonSchema("cryptography-defs.schema.json"),
|
|
62
|
+
readJsonSchema("cyclonedx-2.0-cryptography-defs.schema.json"),
|
|
61
63
|
"https://cyclonedx.org/schema/cryptography-defs.schema.json",
|
|
62
64
|
);
|
|
65
|
+
addDraft2020BundledSchema(
|
|
66
|
+
ajv,
|
|
67
|
+
readJsonSchema("behavior-taxonomy.schema.json"),
|
|
68
|
+
"https://cyclonedx.org/schema/behavior-taxonomy.schema.json",
|
|
69
|
+
);
|
|
63
70
|
addDraft2020BundledSchema(
|
|
64
71
|
ajv,
|
|
65
72
|
readJsonSchema("jsf-0.82.schema.json"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Orchestrates evaluation of internal compliance rule packs (SCVS + CRA)
|
|
3
|
-
* aggregates results into per-benchmark scorecards.
|
|
2
|
+
* Orchestrates evaluation of internal compliance rule packs (SCVS + CRA + CISA)
|
|
3
|
+
* and aggregates results into per-benchmark scorecards.
|
|
4
4
|
*
|
|
5
5
|
* This module is deliberately independent of the CycloneDX BOM audit engine
|
|
6
6
|
* (lib/stages/postgen/auditBom.js). The two engines share similar *Finding*
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
getAllComplianceRules,
|
|
12
|
+
getCisaAiRules,
|
|
13
|
+
getCisaRules,
|
|
12
14
|
getCraRules,
|
|
13
15
|
getScvsRules,
|
|
14
16
|
} from "./complianceRules.js";
|
|
@@ -63,6 +65,25 @@ const BENCHMARKS = {
|
|
|
63
65
|
filter: (rules) => rules.filter((r) => r.standard === "CRA"),
|
|
64
66
|
levelPredicate: () => true,
|
|
65
67
|
},
|
|
68
|
+
cisa: {
|
|
69
|
+
id: "cisa",
|
|
70
|
+
name: "CISA 2026 minimum elements for an SBOM",
|
|
71
|
+
standard: "CISA",
|
|
72
|
+
// The AI element rules share the CISA standard key but form their own
|
|
73
|
+
// benchmark, so both filters select by category.
|
|
74
|
+
filter: (rules) =>
|
|
75
|
+
rules.filter(
|
|
76
|
+
(r) => r.standard === "CISA" && r.category === "compliance-cisa",
|
|
77
|
+
),
|
|
78
|
+
levelPredicate: () => true,
|
|
79
|
+
},
|
|
80
|
+
"cisa-ai": {
|
|
81
|
+
id: "cisa-ai",
|
|
82
|
+
name: "CISA and G7 minimum elements for an AI SBOM",
|
|
83
|
+
standard: "CISA",
|
|
84
|
+
filter: (rules) => rules.filter((r) => r.category === "compliance-cisa-ai"),
|
|
85
|
+
levelPredicate: () => true,
|
|
86
|
+
},
|
|
66
87
|
};
|
|
67
88
|
|
|
68
89
|
/**
|
|
@@ -238,4 +259,10 @@ export function buildBenchmarkReports(findings, requestedAliases) {
|
|
|
238
259
|
return aliases.map((b) => scoreBenchmark(b, findings));
|
|
239
260
|
}
|
|
240
261
|
|
|
241
|
-
export {
|
|
262
|
+
export {
|
|
263
|
+
getAllComplianceRules,
|
|
264
|
+
getCisaAiRules,
|
|
265
|
+
getCisaRules,
|
|
266
|
+
getCraRules,
|
|
267
|
+
getScvsRules,
|
|
268
|
+
};
|