@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
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
|
|
4
|
+
import { HOST_SCOPE_PROJECT_TYPES } from "./env.js";
|
|
5
|
+
import { boundUntrustedGlobPatterns } from "./globPatterns.js";
|
|
3
6
|
import {
|
|
4
7
|
isReservedMetadataPropertyName,
|
|
5
8
|
METADATA_PROPERTY_CONFIG_KEYS,
|
|
@@ -17,10 +20,162 @@ export const PROJECT_CONFIG_FILENAMES = [
|
|
|
17
20
|
".cdxgen.yaml",
|
|
18
21
|
];
|
|
19
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Options a config file may set, by their kebab-case name. A config file may
|
|
25
|
+
* also use the camelCase spelling of each, or one of the aliases in
|
|
26
|
+
* PROJECT_CONFIG_OPTION_ALIASES. Every other key is ignored: options that
|
|
27
|
+
* only library callers pass (such as `dosaiCommand` or `traceCmd`), yargs'
|
|
28
|
+
* own `extends`, and anything cdxgen does not know.
|
|
29
|
+
*
|
|
30
|
+
* Every option bin/cdxgen.js declares is either here or in
|
|
31
|
+
* OPERATOR_ONLY_OPTIONS, which projectConfig.poku.js checks.
|
|
32
|
+
*/
|
|
33
|
+
export const PROJECT_CONFIG_OPTIONS = new Set([
|
|
34
|
+
"activity-report",
|
|
35
|
+
"api-key",
|
|
36
|
+
"author",
|
|
37
|
+
"auto-compositions",
|
|
38
|
+
"auto-create",
|
|
39
|
+
"bom-audit",
|
|
40
|
+
"bom-audit-categories",
|
|
41
|
+
"bom-audit-fail-severity",
|
|
42
|
+
"bom-audit-include-trusted",
|
|
43
|
+
"bom-audit-max-targets",
|
|
44
|
+
"bom-audit-min-severity",
|
|
45
|
+
"bom-audit-only-trusted",
|
|
46
|
+
"bom-audit-rules-dir",
|
|
47
|
+
"bom-audit-scope",
|
|
48
|
+
"cache",
|
|
49
|
+
"cache-ttl",
|
|
50
|
+
"callsites-slices-file",
|
|
51
|
+
"caxa-app-dir",
|
|
52
|
+
"cmake-cache",
|
|
53
|
+
"color",
|
|
54
|
+
"compile-commands",
|
|
55
|
+
"component-type",
|
|
56
|
+
"data-flow-slices-file",
|
|
57
|
+
"deep",
|
|
58
|
+
"deps-slices-file",
|
|
59
|
+
"dry-run",
|
|
60
|
+
"env-audit",
|
|
61
|
+
"evidence",
|
|
62
|
+
"evinse-output",
|
|
63
|
+
"exclude",
|
|
64
|
+
"exclude-type",
|
|
65
|
+
"experimental-mcp-pinning",
|
|
66
|
+
"export-proto",
|
|
67
|
+
"fail-on-error",
|
|
68
|
+
"filter",
|
|
69
|
+
"format",
|
|
70
|
+
"generate-key-and-sign",
|
|
71
|
+
"git-branch",
|
|
72
|
+
"include-crypto",
|
|
73
|
+
"include-formulation",
|
|
74
|
+
"include-regex",
|
|
75
|
+
"include-release-notes",
|
|
76
|
+
"include-runtime",
|
|
77
|
+
"install-deps",
|
|
78
|
+
"introspect",
|
|
79
|
+
"introspect-annotate",
|
|
80
|
+
"introspect-fail-below",
|
|
81
|
+
"introspect-json",
|
|
82
|
+
"introspect-report",
|
|
83
|
+
"is-latest",
|
|
84
|
+
"json-pretty",
|
|
85
|
+
"license-policy",
|
|
86
|
+
"license-ref",
|
|
87
|
+
"lifecycle",
|
|
88
|
+
"log-format",
|
|
89
|
+
"metadata-property",
|
|
90
|
+
"min-confidence",
|
|
91
|
+
"no-babel",
|
|
92
|
+
"no-banner",
|
|
93
|
+
"no-ignore",
|
|
94
|
+
"only",
|
|
95
|
+
"openapi-spec-file",
|
|
96
|
+
"output",
|
|
97
|
+
"package-extensions",
|
|
98
|
+
"parent-project-id",
|
|
99
|
+
"parent-project-name",
|
|
100
|
+
"parent-project-version",
|
|
101
|
+
"print",
|
|
102
|
+
"profile",
|
|
103
|
+
"progress",
|
|
104
|
+
"project-group",
|
|
105
|
+
"project-id",
|
|
106
|
+
"project-name",
|
|
107
|
+
"project-tag",
|
|
108
|
+
"project-version",
|
|
109
|
+
"proto-bin-file",
|
|
110
|
+
"quiet",
|
|
111
|
+
"reachables-slices-file",
|
|
112
|
+
"recurse",
|
|
113
|
+
"release-notes-current-tag",
|
|
114
|
+
"release-notes-previous-tag",
|
|
115
|
+
"required-only",
|
|
116
|
+
"resolve-class",
|
|
117
|
+
"rust",
|
|
118
|
+
"scalasem",
|
|
119
|
+
"scalasem-include-tests",
|
|
120
|
+
"semantics-slices-file",
|
|
121
|
+
"server-url",
|
|
122
|
+
"spec-version",
|
|
123
|
+
"standard",
|
|
124
|
+
"tea-artifact-url",
|
|
125
|
+
"tea-author-email",
|
|
126
|
+
"tea-author-name",
|
|
127
|
+
"tea-collection-name",
|
|
128
|
+
"tea-fetch",
|
|
129
|
+
"tea-leaf-identifier",
|
|
130
|
+
"tea-publish",
|
|
131
|
+
"tea-reason",
|
|
132
|
+
"tea-token",
|
|
133
|
+
"technique",
|
|
134
|
+
"tlp-classification",
|
|
135
|
+
"tui",
|
|
136
|
+
"type",
|
|
137
|
+
"usages-slices-file",
|
|
138
|
+
"validate",
|
|
139
|
+
"verbose",
|
|
140
|
+
]);
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Options only the operator may set, on the command line or through a
|
|
144
|
+
* CDXGEN_* environment variable. They choose an executable, start a listener,
|
|
145
|
+
* turn off certificate checks on the operator's own upload, opt into
|
|
146
|
+
* experimental tool installation, or end the run without a BOM. A config file
|
|
147
|
+
* that sets one is told so and ignored.
|
|
148
|
+
*/
|
|
149
|
+
export const OPERATOR_ONLY_OPTIONS = new Set([
|
|
150
|
+
"feature-flags",
|
|
151
|
+
"help",
|
|
152
|
+
"scalasem-command",
|
|
153
|
+
"server",
|
|
154
|
+
"server-host",
|
|
155
|
+
"server-port",
|
|
156
|
+
"skip-dt-tls-check",
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Alternate option names a config file may use, with the option each one
|
|
161
|
+
* stands for. yargs applies its aliases to config keys too, so each is
|
|
162
|
+
* checked as the option it names.
|
|
163
|
+
*/
|
|
164
|
+
export const PROJECT_CONFIG_OPTION_ALIASES = new Map([
|
|
165
|
+
["c", "resolve-class"],
|
|
166
|
+
["exclude-regex", "exclude"],
|
|
167
|
+
["h", "help"],
|
|
168
|
+
["o", "output"],
|
|
169
|
+
["p", "print"],
|
|
170
|
+
["q", "quiet"],
|
|
171
|
+
["r", "recurse"],
|
|
172
|
+
["t", "type"],
|
|
173
|
+
]);
|
|
174
|
+
|
|
20
175
|
/**
|
|
21
176
|
* Options whose values name a file or directory cdxgen writes to or reads
|
|
22
177
|
* from. A config file may set these, but only to a location inside its own
|
|
23
|
-
* directory.
|
|
178
|
+
* directory, after symbolic links are resolved.
|
|
24
179
|
*/
|
|
25
180
|
const PATH_OPTIONS = new Set([
|
|
26
181
|
"output",
|
|
@@ -28,14 +183,26 @@ const PATH_OPTIONS = new Set([
|
|
|
28
183
|
"proto-bin-file",
|
|
29
184
|
"deps-slices-file",
|
|
30
185
|
"usages-slices-file",
|
|
186
|
+
"callsites-slices-file",
|
|
31
187
|
"data-flow-slices-file",
|
|
32
188
|
"reachables-slices-file",
|
|
33
189
|
"semantics-slices-file",
|
|
34
190
|
"openapi-spec-file",
|
|
35
191
|
"license-policy",
|
|
36
192
|
"bom-audit-rules-dir",
|
|
193
|
+
"introspect-report",
|
|
194
|
+
"introspect-json",
|
|
195
|
+
"cmake-cache",
|
|
196
|
+
"compile-commands",
|
|
197
|
+
"caxa-app-dir",
|
|
37
198
|
]);
|
|
38
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Options whose values are glob patterns matched against every file a scan
|
|
202
|
+
* walks, in the order they draw on the shared expansion budget.
|
|
203
|
+
*/
|
|
204
|
+
const PATTERN_OPTIONS = ["exclude", "include-regex"];
|
|
205
|
+
|
|
39
206
|
/**
|
|
40
207
|
* Options that change where cdxgen sends data or how much of the host it
|
|
41
208
|
* touches. These stay usable, but never silently.
|
|
@@ -64,9 +231,53 @@ function optionSpellings(option) {
|
|
|
64
231
|
return camel === option ? [option] : [option, camel];
|
|
65
232
|
}
|
|
66
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Find the option a config key names.
|
|
236
|
+
*
|
|
237
|
+
* @param {string} key config file key
|
|
238
|
+
* @returns {string|undefined} kebab-case option name, or undefined when the
|
|
239
|
+
* key is not the kebab-case spelling, the camelCase spelling or an alias of
|
|
240
|
+
* an option cdxgen declares
|
|
241
|
+
*/
|
|
242
|
+
function configKeyOption(key) {
|
|
243
|
+
if (PROJECT_CONFIG_OPTION_ALIASES.has(key)) {
|
|
244
|
+
return PROJECT_CONFIG_OPTION_ALIASES.get(key);
|
|
245
|
+
}
|
|
246
|
+
const kebab = key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
247
|
+
if (!PROJECT_CONFIG_OPTIONS.has(kebab) && !OPERATOR_ONLY_OPTIONS.has(kebab)) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
return optionSpellings(kebab).includes(key) ? kebab : undefined;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Resolve a path through the symbolic links of its longest existing prefix.
|
|
255
|
+
* The part that does not exist yet is appended unchanged.
|
|
256
|
+
*
|
|
257
|
+
* @param {string} absolutePath absolute path to resolve
|
|
258
|
+
* @returns {string} the path with every existing component resolved
|
|
259
|
+
*/
|
|
260
|
+
function resolveExistingPrefix(absolutePath) {
|
|
261
|
+
const missing = [];
|
|
262
|
+
let current = absolutePath;
|
|
263
|
+
for (;;) {
|
|
264
|
+
try {
|
|
265
|
+
return path.join(realpathSync(current), ...missing.reverse());
|
|
266
|
+
} catch {
|
|
267
|
+
const parent = path.dirname(current);
|
|
268
|
+
if (parent === current) {
|
|
269
|
+
return absolutePath;
|
|
270
|
+
}
|
|
271
|
+
missing.push(path.basename(current));
|
|
272
|
+
current = parent;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
67
277
|
/**
|
|
68
278
|
* Determine whether a config-supplied path stays inside the config's own
|
|
69
|
-
* directory
|
|
279
|
+
* directory once symbolic links are resolved, so a link committed to the
|
|
280
|
+
* scanned tree cannot carry a path option outside it.
|
|
70
281
|
*
|
|
71
282
|
* @param {string} configDir directory the config file was read from
|
|
72
283
|
* @param {unknown} value config-supplied path value
|
|
@@ -76,40 +287,95 @@ function isContainedPath(configDir, value) {
|
|
|
76
287
|
if (typeof value !== "string" || !value.length) {
|
|
77
288
|
return false;
|
|
78
289
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
);
|
|
290
|
+
const root = resolveExistingPrefix(path.resolve(configDir));
|
|
291
|
+
const target = resolveExistingPrefix(path.resolve(configDir, value));
|
|
292
|
+
const relativePath = path.relative(root, target);
|
|
83
293
|
return (
|
|
84
294
|
relativePath === "" ||
|
|
85
|
-
(
|
|
295
|
+
(relativePath !== ".." &&
|
|
296
|
+
!relativePath.startsWith(`..${path.sep}`) &&
|
|
297
|
+
!path.isAbsolute(relativePath))
|
|
86
298
|
);
|
|
87
299
|
}
|
|
88
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Split a config-supplied project type value into the individual types.
|
|
303
|
+
*
|
|
304
|
+
* @param {unknown} value `type` value from a config file
|
|
305
|
+
* @returns {string[]} trimmed, non-empty project types
|
|
306
|
+
*/
|
|
307
|
+
function projectTypeList(value) {
|
|
308
|
+
return (Array.isArray(value) ? value : [value])
|
|
309
|
+
.flatMap((entry) => `${entry ?? ""}`.split(","))
|
|
310
|
+
.map((entry) => entry.trim())
|
|
311
|
+
.filter(Boolean);
|
|
312
|
+
}
|
|
313
|
+
|
|
89
314
|
/**
|
|
90
315
|
* Apply the trust boundary between cdxgen and the directory it is scanning.
|
|
91
316
|
*
|
|
92
317
|
* A config file lives in the tree under analysis, so it is attacker-controlled
|
|
93
|
-
* whenever that tree is.
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
318
|
+
* whenever that tree is. It may therefore only set the options listed in
|
|
319
|
+
* PROJECT_CONFIG_OPTIONS: options that choose an executable, start a listener
|
|
320
|
+
* or weaken the operator's own checks, and every key cdxgen does not declare
|
|
321
|
+
* as an option, are dropped. Path options are confined to the config's own
|
|
322
|
+
* directory - a scanned project may choose where in itself the BOM lands, but
|
|
323
|
+
* not write outside it - and project types that inventory the host rather
|
|
324
|
+
* than the scan path are dropped. Exclude and include patterns are kept
|
|
325
|
+
* within the bounds of boundUntrustedGlobPatterns, so a project cannot make
|
|
326
|
+
* every file match against thousands of brace-expanded patterns. Options that
|
|
327
|
+
* redirect data off the host or widen what cdxgen does are announced on the
|
|
328
|
+
* console. A project may describe itself with custom metadata properties, but
|
|
329
|
+
* not in the namespaces cdxgen reserves for the facts it establishes, so a
|
|
330
|
+
* scanned tree cannot pass its own claims off as cdxgen's.
|
|
100
331
|
*
|
|
101
332
|
* @param {Object} config parsed config file contents
|
|
102
333
|
* @param {string} configDir directory the config file was read from
|
|
103
|
-
* @returns {{config: Object, rejected: string[], announced: string[], reservedProperties: string[]}} sanitized config and what it did
|
|
334
|
+
* @returns {{config: Object, rejected: string[], announced: string[], reservedProperties: string[], ignored: string[], operatorOnly: string[], hostScopeTypes: string[], refusedPatterns: {key: string, pattern: string, reason: string}[]}} sanitized config and what it did
|
|
104
335
|
*/
|
|
105
336
|
export function sanitizeProjectConfig(config, configDir) {
|
|
106
|
-
|
|
107
|
-
|
|
337
|
+
const result = {
|
|
338
|
+
announced: [],
|
|
339
|
+
config: {},
|
|
340
|
+
hostScopeTypes: [],
|
|
341
|
+
ignored: [],
|
|
342
|
+
operatorOnly: [],
|
|
343
|
+
refusedPatterns: [],
|
|
344
|
+
rejected: [],
|
|
345
|
+
reservedProperties: [],
|
|
346
|
+
};
|
|
347
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
const sanitized = result.config;
|
|
351
|
+
const aliasEntries = [];
|
|
352
|
+
for (const [key, value] of Object.entries(config)) {
|
|
353
|
+
if (METADATA_PROPERTY_CONFIG_KEYS.includes(key)) {
|
|
354
|
+
sanitized[key] = value;
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
const option = configKeyOption(key);
|
|
358
|
+
if (!option) {
|
|
359
|
+
result.ignored.push(key);
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (OPERATOR_ONLY_OPTIONS.has(option)) {
|
|
363
|
+
result.operatorOnly.push(key);
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
if (PROJECT_CONFIG_OPTION_ALIASES.has(key)) {
|
|
367
|
+
aliasEntries.push([option, value]);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
sanitized[key] = value;
|
|
371
|
+
}
|
|
372
|
+
// An alias is stored under the option it names, so the checks below see
|
|
373
|
+
// it. A spelled-out option in the same file takes precedence.
|
|
374
|
+
for (const [option, value] of aliasEntries) {
|
|
375
|
+
if (optionSpellings(option).every((key) => sanitized[key] === undefined)) {
|
|
376
|
+
sanitized[option] = value;
|
|
377
|
+
}
|
|
108
378
|
}
|
|
109
|
-
const sanitized = { ...config };
|
|
110
|
-
const rejected = [];
|
|
111
|
-
const announced = [];
|
|
112
|
-
const reservedProperties = [];
|
|
113
379
|
for (const key of METADATA_PROPERTY_CONFIG_KEYS) {
|
|
114
380
|
if (sanitized[key] === undefined) {
|
|
115
381
|
continue;
|
|
@@ -117,7 +383,7 @@ export function sanitizeProjectConfig(config, configDir) {
|
|
|
117
383
|
const properties = [];
|
|
118
384
|
for (const aprop of parseMetadataProperties(sanitized[key])) {
|
|
119
385
|
if (isReservedMetadataPropertyName(aprop.name)) {
|
|
120
|
-
reservedProperties.push(aprop.name);
|
|
386
|
+
result.reservedProperties.push(aprop.name);
|
|
121
387
|
} else {
|
|
122
388
|
properties.push(aprop);
|
|
123
389
|
}
|
|
@@ -134,17 +400,58 @@ export function sanitizeProjectConfig(config, configDir) {
|
|
|
134
400
|
continue;
|
|
135
401
|
}
|
|
136
402
|
if (!isContainedPath(configDir, sanitized[key])) {
|
|
137
|
-
rejected.push(`${key}=${sanitized[key]}`);
|
|
403
|
+
result.rejected.push(`${key}=${sanitized[key]}`);
|
|
138
404
|
delete sanitized[key];
|
|
139
405
|
}
|
|
140
406
|
}
|
|
141
407
|
}
|
|
408
|
+
if (sanitized.type !== undefined) {
|
|
409
|
+
const types = projectTypeList(sanitized.type);
|
|
410
|
+
const projectTypes = types.filter(
|
|
411
|
+
(type) => !HOST_SCOPE_PROJECT_TYPES.has(type.toLowerCase()),
|
|
412
|
+
);
|
|
413
|
+
result.hostScopeTypes = types.filter(
|
|
414
|
+
(type) => !projectTypes.includes(type),
|
|
415
|
+
);
|
|
416
|
+
if (result.hostScopeTypes.length) {
|
|
417
|
+
if (projectTypes.length) {
|
|
418
|
+
sanitized.type = projectTypes;
|
|
419
|
+
} else {
|
|
420
|
+
delete sanitized.type;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// Exclude patterns, then include patterns, share one expansion budget.
|
|
425
|
+
let patternsUsed = 0;
|
|
426
|
+
for (const option of PATTERN_OPTIONS) {
|
|
427
|
+
for (const key of optionSpellings(option)) {
|
|
428
|
+
if (sanitized[key] === undefined) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
const { accepted, expansions, refused } = boundUntrustedGlobPatterns(
|
|
432
|
+
sanitized[key],
|
|
433
|
+
{ used: patternsUsed },
|
|
434
|
+
);
|
|
435
|
+
patternsUsed += expansions;
|
|
436
|
+
for (const entry of refused) {
|
|
437
|
+
result.refusedPatterns.push({ key, ...entry });
|
|
438
|
+
}
|
|
439
|
+
if (!refused.length) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
if (!accepted.length) {
|
|
443
|
+
delete sanitized[key];
|
|
444
|
+
} else {
|
|
445
|
+
sanitized[key] = Array.isArray(sanitized[key]) ? accepted : accepted[0];
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
142
449
|
for (const option of ANNOUNCED_OPTIONS) {
|
|
143
450
|
for (const key of optionSpellings(option)) {
|
|
144
451
|
if (sanitized[key] !== undefined) {
|
|
145
|
-
announced.push(key);
|
|
452
|
+
result.announced.push(key);
|
|
146
453
|
}
|
|
147
454
|
}
|
|
148
455
|
}
|
|
149
|
-
return
|
|
456
|
+
return result;
|
|
150
457
|
}
|
package/lib/core/toolRegistry.js
CHANGED
|
@@ -48,6 +48,16 @@ const WRAPPER_BASENAMES = new Set([
|
|
|
48
48
|
"zsh",
|
|
49
49
|
]);
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Commands cdxgen runs to learn about the machine it runs on rather than the
|
|
53
|
+
* project, such as `ldd --version` choosing between the glibc and musl
|
|
54
|
+
* plugin binaries. They did not help generate the BOM, so they are not tools
|
|
55
|
+
* of it.
|
|
56
|
+
*
|
|
57
|
+
* @type {Set<string>}
|
|
58
|
+
*/
|
|
59
|
+
const HOST_PROBE_BASENAMES = new Set(["ldd"]);
|
|
60
|
+
|
|
51
61
|
/**
|
|
52
62
|
* Strip a trailing Windows executable suffix from a binary name.
|
|
53
63
|
*
|
|
@@ -97,7 +107,11 @@ export function recordExecutedTool(name, version) {
|
|
|
97
107
|
return;
|
|
98
108
|
}
|
|
99
109
|
const toolName = toolNameOf(name);
|
|
100
|
-
if (
|
|
110
|
+
if (
|
|
111
|
+
!toolName ||
|
|
112
|
+
WRAPPER_BASENAMES.has(toolName) ||
|
|
113
|
+
HOST_PROBE_BASENAMES.has(toolName)
|
|
114
|
+
) {
|
|
101
115
|
return;
|
|
102
116
|
}
|
|
103
117
|
const key = toolName.toLowerCase();
|
|
@@ -721,7 +721,7 @@ export async function parseDenoLock(lockFile, options = {}) {
|
|
|
721
721
|
// Deterministic canonical jsr page for the original specifier, e.g.
|
|
722
722
|
// `https://jsr.io/@std/assert@1.0.19`. The npm-mirror tarball URL is only
|
|
723
723
|
// available after a registry lookup, so this gives every jsr component a
|
|
724
|
-
// stable reference even
|
|
724
|
+
// stable reference even when FETCH_LICENSE is not set.
|
|
725
725
|
const jsrHomepage = `https://jsr.io/${group ? `${group}/` : ""}${name}@${version}`;
|
|
726
726
|
const pkgObj = {
|
|
727
727
|
group: JSR_NPM_SCOPE,
|
|
@@ -1056,7 +1056,7 @@ export async function parseDenoLock(lockFile, options = {}) {
|
|
|
1056
1056
|
|
|
1057
1057
|
// Offline enrichment first: mine license/description/repository from a
|
|
1058
1058
|
// project's node_modules and the global deno npm cache. This needs no
|
|
1059
|
-
// network and runs even
|
|
1059
|
+
// network and runs even when FETCH_LICENSE is not set.
|
|
1060
1060
|
mineInstalledMetadata(
|
|
1061
1061
|
pkgList,
|
|
1062
1062
|
options.projectRoot || dirname(lockFile),
|
package/lib/ecosystems/golem.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
hasInlineCredential,
|
|
21
21
|
sanitizeBomUrl,
|
|
22
22
|
} from "../core/propertySanitizer.js";
|
|
23
|
+
import { occurrenceLocationKey } from "../inventory/occurrenceKey.js";
|
|
23
24
|
import { resolvePluginBinary } from "../inventory/plugins.js";
|
|
24
25
|
import { canonicalPurlFromLooseString } from "../inventory/purl.js";
|
|
25
26
|
|
|
@@ -93,20 +94,14 @@ function rangeLocation(range) {
|
|
|
93
94
|
if (!start?.filename) {
|
|
94
95
|
return undefined;
|
|
95
96
|
}
|
|
96
|
-
|
|
97
|
-
return `${start.filename}#${start.line}`;
|
|
98
|
-
}
|
|
99
|
-
return start.filename;
|
|
97
|
+
return occurrenceLocationKey(start.filename, start.line);
|
|
100
98
|
}
|
|
101
99
|
|
|
102
100
|
function positionLocation(position) {
|
|
103
101
|
if (!position?.filename) {
|
|
104
102
|
return undefined;
|
|
105
103
|
}
|
|
106
|
-
|
|
107
|
-
return `${position.filename}#${position.line}`;
|
|
108
|
-
}
|
|
109
|
-
return position.filename;
|
|
104
|
+
return occurrenceLocationKey(position.filename, position.line);
|
|
110
105
|
}
|
|
111
106
|
|
|
112
107
|
function purlWithoutVersion(purl) {
|