@cyclonedx/cdxgen 12.3.3 → 12.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -22
- package/bin/audit.js +21 -7
- package/bin/cdxgen.js +238 -116
- package/bin/convert.js +28 -13
- package/bin/hbom.js +490 -0
- package/bin/repl.js +580 -29
- package/bin/validate.js +34 -4
- package/bin/verify.js +40 -5
- package/data/README.md +298 -25
- package/data/component-tags.json +6 -0
- package/data/crypto-oid.json +16 -0
- package/data/predictive-audit-allowlist.json +11 -0
- package/data/queries-darwin.json +12 -1
- package/data/queries-win.json +7 -1
- package/data/queries.json +39 -2
- package/data/rules/ai-agent-governance.yaml +16 -0
- package/data/rules/asar-archives.yaml +150 -0
- package/data/rules/chrome-extensions.yaml +8 -0
- package/data/rules/ci-permissions.yaml +42 -18
- package/data/rules/container-risk.yaml +14 -7
- package/data/rules/dependency-sources.yaml +11 -0
- package/data/rules/hbom-compliance.yaml +325 -0
- package/data/rules/hbom-performance.yaml +307 -0
- package/data/rules/hbom-security.yaml +248 -0
- package/data/rules/host-topology.yaml +165 -0
- package/data/rules/mcp-servers.yaml +18 -3
- package/data/rules/obom-runtime.yaml +907 -22
- package/data/rules/package-integrity.yaml +14 -0
- package/data/rules/rootfs-hardening.yaml +179 -0
- package/data/rules/vscode-extensions.yaml +9 -0
- package/lib/audit/index.js +209 -8
- package/lib/audit/index.poku.js +332 -0
- package/lib/audit/reporters.js +222 -0
- package/lib/audit/targets.js +146 -1
- package/lib/audit/targets.poku.js +186 -0
- package/lib/cli/asar.poku.js +328 -0
- package/lib/cli/index.js +506 -88
- package/lib/cli/index.poku.js +1352 -212
- package/lib/evinser/evinser.js +14 -9
- package/lib/helpers/analyzer.js +1406 -29
- package/lib/helpers/analyzer.poku.js +342 -0
- package/lib/helpers/analyzerScope.js +712 -0
- package/lib/helpers/asarutils.js +1556 -0
- package/lib/helpers/asarutils.poku.js +443 -0
- package/lib/helpers/auditCategories.js +12 -0
- package/lib/helpers/auditCategories.poku.js +32 -0
- package/lib/helpers/cbomutils.js +271 -1
- package/lib/helpers/cbomutils.poku.js +248 -5
- package/lib/helpers/display.js +291 -1
- package/lib/helpers/display.poku.js +149 -0
- package/lib/helpers/evidenceUtils.js +58 -0
- package/lib/helpers/evidenceUtils.poku.js +54 -0
- package/lib/helpers/exportUtils.js +9 -0
- package/lib/helpers/gtfobins.js +142 -8
- package/lib/helpers/gtfobins.poku.js +24 -1
- package/lib/helpers/hbom.js +710 -0
- package/lib/helpers/hbom.poku.js +496 -0
- package/lib/helpers/hbomAnalysis.js +268 -0
- package/lib/helpers/hbomAnalysis.poku.js +249 -0
- package/lib/helpers/hbomLoader.js +35 -0
- package/lib/helpers/hostTopology.js +803 -0
- package/lib/helpers/hostTopology.poku.js +363 -0
- package/lib/helpers/inventoryStats.js +69 -0
- package/lib/helpers/inventoryStats.poku.js +86 -0
- package/lib/helpers/lolbas.js +19 -1
- package/lib/helpers/lolbas.poku.js +23 -0
- package/lib/helpers/osqueryTransform.js +47 -0
- package/lib/helpers/osqueryTransform.poku.js +47 -0
- package/lib/helpers/plugins.js +349 -0
- package/lib/helpers/plugins.poku.js +57 -0
- package/lib/helpers/protobom.js +156 -45
- package/lib/helpers/protobom.poku.js +140 -5
- package/lib/helpers/remote/dependency-track.js +36 -3
- package/lib/helpers/remote/dependency-track.poku.js +44 -0
- package/lib/helpers/source.js +24 -0
- package/lib/helpers/source.poku.js +32 -0
- package/lib/helpers/utils.js +1438 -93
- package/lib/helpers/utils.poku.js +846 -4
- package/lib/managers/binary.e2e.poku.js +367 -0
- package/lib/managers/binary.js +2293 -353
- package/lib/managers/binary.poku.js +1699 -1
- package/lib/managers/docker.js +201 -79
- package/lib/managers/docker.poku.js +337 -12
- package/lib/server/server.js +2 -27
- package/lib/stages/postgen/annotator.js +38 -0
- package/lib/stages/postgen/annotator.poku.js +107 -1
- package/lib/stages/postgen/auditBom.js +121 -18
- package/lib/stages/postgen/auditBom.poku.js +1366 -31
- package/lib/stages/postgen/hostTopologyAudit.poku.js +186 -0
- package/lib/stages/postgen/postgen.js +192 -1
- package/lib/stages/postgen/postgen.poku.js +321 -0
- package/lib/stages/postgen/ruleEngine.js +116 -0
- package/lib/stages/pregen/envAudit.js +14 -3
- package/package.json +23 -21
- package/types/bin/hbom.d.ts +3 -0
- package/types/bin/hbom.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +44 -0
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/audit/reporters.d.ts +16 -0
- package/types/lib/audit/reporters.d.ts.map +1 -1
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +16 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +4 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts +33 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/analyzerScope.d.ts +11 -0
- package/types/lib/helpers/analyzerScope.d.ts.map +1 -0
- package/types/lib/helpers/asarutils.d.ts +34 -0
- package/types/lib/helpers/asarutils.d.ts.map +1 -0
- package/types/lib/helpers/auditCategories.d.ts +5 -0
- package/types/lib/helpers/auditCategories.d.ts.map +1 -1
- package/types/lib/helpers/cbomutils.d.ts +3 -2
- package/types/lib/helpers/cbomutils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/evidenceUtils.d.ts +8 -0
- package/types/lib/helpers/evidenceUtils.d.ts.map +1 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -1
- package/types/lib/helpers/gtfobins.d.ts +8 -0
- package/types/lib/helpers/gtfobins.d.ts.map +1 -1
- package/types/lib/helpers/hbom.d.ts +49 -0
- package/types/lib/helpers/hbom.d.ts.map +1 -0
- package/types/lib/helpers/hbomAnalysis.d.ts +62 -0
- package/types/lib/helpers/hbomAnalysis.d.ts.map +1 -0
- package/types/lib/helpers/hbomLoader.d.ts +7 -0
- package/types/lib/helpers/hbomLoader.d.ts.map +1 -0
- package/types/lib/helpers/hostTopology.d.ts +12 -0
- package/types/lib/helpers/hostTopology.d.ts.map +1 -0
- package/types/lib/helpers/inventoryStats.d.ts +11 -0
- package/types/lib/helpers/inventoryStats.d.ts.map +1 -0
- package/types/lib/helpers/lolbas.d.ts.map +1 -1
- package/types/lib/helpers/osqueryTransform.d.ts +3 -0
- package/types/lib/helpers/osqueryTransform.d.ts.map +1 -1
- package/types/lib/helpers/plugins.d.ts +58 -0
- package/types/lib/helpers/plugins.d.ts.map +1 -0
- package/types/lib/helpers/protobom.d.ts +3 -4
- package/types/lib/helpers/protobom.d.ts.map +1 -1
- package/types/lib/helpers/remote/dependency-track.d.ts +10 -3
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
- package/types/lib/helpers/source.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +45 -8
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +5 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +2 -1
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts +26 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +2 -1
- 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/pregen/envAudit.d.ts.map +1 -1
- package/data/spdx-model-v3.0.1.jsonld +0 -15999
|
@@ -3,27 +3,46 @@ import { join } from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import { assert, it } from "poku";
|
|
5
5
|
|
|
6
|
-
import { readBinary, writeBinary } from "./protobom.js";
|
|
6
|
+
import { isProtoBomFile, readBinary, writeBinary } from "./protobom.js";
|
|
7
7
|
import { getTmpDir } from "./utils.js";
|
|
8
8
|
|
|
9
|
-
const tempDir = mkdtempSync(join(getTmpDir(), "bin-tests-"));
|
|
10
9
|
const testBom = JSON.parse(
|
|
11
10
|
readFileSync("./test/data/bom-java.json", { encoding: "utf-8" }),
|
|
12
11
|
);
|
|
12
|
+
const cbomFixture = JSON.parse(
|
|
13
|
+
readFileSync("./test/data/bom-cbom-js-fixture.json", { encoding: "utf-8" }),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const createTempDir = () => mkdtempSync(join(getTmpDir(), "bin-tests-"));
|
|
17
|
+
|
|
18
|
+
const cleanupTempDir = (tempDir) => {
|
|
19
|
+
if (tempDir?.startsWith(getTmpDir()) && rmSync) {
|
|
20
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
21
|
+
}
|
|
22
|
+
};
|
|
13
23
|
|
|
14
24
|
it("proto binary tests", () => {
|
|
25
|
+
const tempDir = createTempDir();
|
|
15
26
|
const binFile = join(tempDir, "test.cdx.bin");
|
|
16
27
|
writeBinary({}, binFile);
|
|
17
28
|
assert.deepStrictEqual(existsSync(binFile), true);
|
|
18
29
|
writeBinary(testBom, binFile);
|
|
19
30
|
assert.deepStrictEqual(existsSync(binFile), true);
|
|
31
|
+
assert.equal(isProtoBomFile(binFile), true);
|
|
32
|
+
assert.equal(isProtoBomFile("test.proto"), true);
|
|
33
|
+
assert.equal(isProtoBomFile("bom.json"), false);
|
|
20
34
|
let bomObject = readBinary(binFile);
|
|
21
35
|
assert.ok(bomObject);
|
|
22
36
|
assert.deepStrictEqual(
|
|
23
37
|
bomObject.serialNumber,
|
|
24
38
|
"urn:uuid:cc8b5a04-2698-4375-b04c-cedfa4317fee",
|
|
25
39
|
);
|
|
40
|
+
assert.deepStrictEqual(bomObject.bomFormat, "CycloneDX");
|
|
26
41
|
assert.deepStrictEqual(bomObject.specVersion, "1.5");
|
|
42
|
+
assert.equal(
|
|
43
|
+
bomObject.metadata.component.type.startsWith("CLASSIFICATION_"),
|
|
44
|
+
false,
|
|
45
|
+
);
|
|
27
46
|
bomObject = readBinary(binFile, false, 1.5);
|
|
28
47
|
assert.ok(bomObject);
|
|
29
48
|
assert.deepStrictEqual(
|
|
@@ -31,7 +50,123 @@ it("proto binary tests", () => {
|
|
|
31
50
|
"urn:uuid:cc8b5a04-2698-4375-b04c-cedfa4317fee",
|
|
32
51
|
);
|
|
33
52
|
assert.deepStrictEqual(bomObject.specVersion, "1.5");
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
const modernBinFile = join(tempDir, "test-1.7.cdx");
|
|
54
|
+
writeBinary(
|
|
55
|
+
{
|
|
56
|
+
bomFormat: "CycloneDX",
|
|
57
|
+
metadata: {
|
|
58
|
+
component: {
|
|
59
|
+
name: "cdxgen",
|
|
60
|
+
type: "application",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
serialNumber: "urn:uuid:11111111-1111-1111-1111-111111111111",
|
|
64
|
+
specVersion: "1.7",
|
|
65
|
+
version: 1,
|
|
66
|
+
},
|
|
67
|
+
modernBinFile,
|
|
68
|
+
);
|
|
69
|
+
const modernBomObject = readBinary(modernBinFile);
|
|
70
|
+
assert.ok(modernBomObject);
|
|
71
|
+
assert.deepStrictEqual(modernBomObject.bomFormat, "CycloneDX");
|
|
72
|
+
assert.deepStrictEqual(modernBomObject.specVersion, "1.7");
|
|
73
|
+
assert.deepStrictEqual(
|
|
74
|
+
modernBomObject.metadata.component.type,
|
|
75
|
+
"application",
|
|
76
|
+
);
|
|
77
|
+
assert.deepStrictEqual(modernBomObject.metadata.component.name, "cdxgen");
|
|
78
|
+
cleanupTempDir(tempDir);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("keeps canonical definitions and declarations as objects during proto round-trip", () => {
|
|
82
|
+
const tempDir = createTempDir();
|
|
83
|
+
const binFile = join(tempDir, "standard-sections.cdx");
|
|
84
|
+
writeBinary(
|
|
85
|
+
{
|
|
86
|
+
bomFormat: "CycloneDX",
|
|
87
|
+
declarations: {
|
|
88
|
+
affirmation: {
|
|
89
|
+
statement: "verified",
|
|
90
|
+
},
|
|
91
|
+
claims: [
|
|
92
|
+
{
|
|
93
|
+
predicate: "meets-control",
|
|
94
|
+
target: "pkg:npm/demo-app@1.0.0",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
definitions: {
|
|
99
|
+
standards: [
|
|
100
|
+
{
|
|
101
|
+
name: "ASVS",
|
|
102
|
+
requirements: [
|
|
103
|
+
{
|
|
104
|
+
identifier: "V1.1",
|
|
105
|
+
title: "Authenticate requests",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
version: "5.0",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
metadata: {
|
|
113
|
+
component: {
|
|
114
|
+
name: "demo-app",
|
|
115
|
+
type: "application",
|
|
116
|
+
version: "1.0.0",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
serialNumber: "urn:uuid:22222222-2222-2222-2222-222222222222",
|
|
120
|
+
specVersion: "1.7",
|
|
121
|
+
version: 1,
|
|
122
|
+
},
|
|
123
|
+
binFile,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const bomObject = readBinary(binFile);
|
|
127
|
+
assert.ok(bomObject);
|
|
128
|
+
assert.equal(Array.isArray(bomObject.definitions), false);
|
|
129
|
+
assert.equal(Array.isArray(bomObject.declarations), false);
|
|
130
|
+
assert.equal(bomObject.definitions.standards[0].name, "ASVS");
|
|
131
|
+
assert.equal(
|
|
132
|
+
bomObject.definitions.standards[0].requirements[0].identifier,
|
|
133
|
+
"V1.1",
|
|
134
|
+
);
|
|
135
|
+
assert.equal(bomObject.declarations.claims[0].predicate, "meets-control");
|
|
136
|
+
assert.equal(bomObject.declarations.affirmation.statement, "verified");
|
|
137
|
+
cleanupTempDir(tempDir);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("round-trips real CBOM fixture data with cryptographic assets intact", () => {
|
|
141
|
+
const tempDir = createTempDir();
|
|
142
|
+
const binFile = join(tempDir, "cbom-fixture.cdx");
|
|
143
|
+
writeBinary(cbomFixture, binFile);
|
|
144
|
+
|
|
145
|
+
const bomObject = readBinary(binFile);
|
|
146
|
+
const cryptoComponents = (bomObject.components || []).filter(
|
|
147
|
+
(component) => component.type === "cryptographic-asset",
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
assert.ok(bomObject);
|
|
151
|
+
assert.equal(bomObject.specVersion, "1.7");
|
|
152
|
+
assert.ok(cryptoComponents.length >= 3);
|
|
153
|
+
assert.equal(
|
|
154
|
+
cryptoComponents.some(
|
|
155
|
+
(component) => component.cryptoProperties?.assetType === "algorithm",
|
|
156
|
+
),
|
|
157
|
+
true,
|
|
158
|
+
);
|
|
159
|
+
assert.equal(
|
|
160
|
+
cryptoComponents.some((component) => component.purl !== undefined),
|
|
161
|
+
false,
|
|
162
|
+
);
|
|
163
|
+
assert.equal(
|
|
164
|
+
cryptoComponents.some(
|
|
165
|
+
(component) =>
|
|
166
|
+
component.name === "sha-512" &&
|
|
167
|
+
component.cryptoProperties?.oid === "2.16.840.1.101.3.4.2.3",
|
|
168
|
+
),
|
|
169
|
+
true,
|
|
170
|
+
);
|
|
171
|
+
cleanupTempDir(tempDir);
|
|
37
172
|
});
|
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
|
|
3
|
+
import { hasDangerousUnicode } from "../utils.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the Dependency-Track BOM API URL as a sanitized URL object.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} serverUrl Dependency-Track server URL
|
|
9
|
+
* @returns {URL | undefined} API URL to submit BOM payload
|
|
10
|
+
*/
|
|
11
|
+
export function getDependencyTrackBomApiUrl(serverUrl) {
|
|
12
|
+
const rawServerUrl = `${serverUrl || ""}`.trim();
|
|
13
|
+
if (!rawServerUrl || hasDangerousUnicode(rawServerUrl)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
let parsedUrl;
|
|
17
|
+
try {
|
|
18
|
+
parsedUrl = new URL(rawServerUrl);
|
|
19
|
+
} catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (!["http:", "https:"].includes(parsedUrl.protocol)) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
if (!parsedUrl.hostname || hasDangerousUnicode(parsedUrl.hostname)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
parsedUrl.username = "";
|
|
29
|
+
parsedUrl.password = "";
|
|
30
|
+
parsedUrl.search = "";
|
|
31
|
+
parsedUrl.hash = "";
|
|
32
|
+
parsedUrl.pathname = `${parsedUrl.pathname.replace(/\/+$/, "")}/api/v1/bom`;
|
|
33
|
+
return parsedUrl;
|
|
34
|
+
}
|
|
35
|
+
|
|
3
36
|
/**
|
|
4
|
-
* Returns the Dependency-Track BOM API URL.
|
|
37
|
+
* Returns the Dependency-Track BOM API URL string.
|
|
5
38
|
*
|
|
6
39
|
* @param {string} serverUrl Dependency-Track server URL
|
|
7
|
-
* @returns {string} API URL to submit BOM payload
|
|
40
|
+
* @returns {string | undefined} API URL to submit BOM payload
|
|
8
41
|
*/
|
|
9
42
|
export function getDependencyTrackBomUrl(serverUrl) {
|
|
10
|
-
return
|
|
43
|
+
return getDependencyTrackBomApiUrl(serverUrl)?.toString();
|
|
11
44
|
}
|
|
12
45
|
|
|
13
46
|
/**
|
|
@@ -2,6 +2,7 @@ import { assert, describe, it } from "poku";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildDependencyTrackBomPayload,
|
|
5
|
+
getDependencyTrackBomApiUrl,
|
|
5
6
|
getDependencyTrackBomUrl,
|
|
6
7
|
} from "./dependency-track.js";
|
|
7
8
|
|
|
@@ -17,6 +18,49 @@ describe("Dependency-Track helper tests", () => {
|
|
|
17
18
|
);
|
|
18
19
|
});
|
|
19
20
|
|
|
21
|
+
it("removes credentials, query strings, and fragments from the submission URL", () => {
|
|
22
|
+
assert.strictEqual(
|
|
23
|
+
getDependencyTrackBomUrl(
|
|
24
|
+
"https://user:pass@dtrack.example.com/base/?token=secret#frag",
|
|
25
|
+
),
|
|
26
|
+
"https://dtrack.example.com/base/api/v1/bom",
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("returns a sanitized URL object for Dependency-Track requests", () => {
|
|
31
|
+
const apiUrl = getDependencyTrackBomApiUrl(
|
|
32
|
+
"https://user:pass@dtrack.example.com/base/?token=secret#frag",
|
|
33
|
+
);
|
|
34
|
+
assert.ok(apiUrl instanceof URL);
|
|
35
|
+
assert.strictEqual(apiUrl?.hostname, "dtrack.example.com");
|
|
36
|
+
assert.strictEqual(apiUrl?.pathname, "/base/api/v1/bom");
|
|
37
|
+
assert.strictEqual(apiUrl?.username, "");
|
|
38
|
+
assert.strictEqual(apiUrl?.password, "");
|
|
39
|
+
assert.strictEqual(apiUrl?.search, "");
|
|
40
|
+
assert.strictEqual(apiUrl?.hash, "");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("rejects malformed or unsupported submission URLs", () => {
|
|
44
|
+
assert.strictEqual(
|
|
45
|
+
getDependencyTrackBomUrl("file:///tmp/dtrack"),
|
|
46
|
+
undefined,
|
|
47
|
+
);
|
|
48
|
+
assert.strictEqual(
|
|
49
|
+
getDependencyTrackBomApiUrl("file:///tmp/dtrack"),
|
|
50
|
+
undefined,
|
|
51
|
+
);
|
|
52
|
+
assert.strictEqual(
|
|
53
|
+
getDependencyTrackBomUrl("javascript:alert(1)"),
|
|
54
|
+
undefined,
|
|
55
|
+
);
|
|
56
|
+
assert.strictEqual(
|
|
57
|
+
getDependencyTrackBomApiUrl("javascript:alert(1)"),
|
|
58
|
+
undefined,
|
|
59
|
+
);
|
|
60
|
+
assert.strictEqual(getDependencyTrackBomUrl("not a url"), undefined);
|
|
61
|
+
assert.strictEqual(getDependencyTrackBomApiUrl("not a url"), undefined);
|
|
62
|
+
});
|
|
63
|
+
|
|
20
64
|
it("builds payload with parentUUID and tags", () => {
|
|
21
65
|
const payload = buildDependencyTrackBomPayload(
|
|
22
66
|
{
|
package/lib/helpers/source.js
CHANGED
|
@@ -77,6 +77,21 @@ function isSafeGitRefName(refName) {
|
|
|
77
77
|
return /^[A-Za-z0-9._/@+-]+$/.test(refName);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
function inferGitOperation(args = []) {
|
|
81
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
82
|
+
const arg = args[index];
|
|
83
|
+
if (arg === "-c" || arg === "--config-env") {
|
|
84
|
+
index += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (typeof arg === "string" && arg.startsWith("-")) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
return arg || "command";
|
|
91
|
+
}
|
|
92
|
+
return "command";
|
|
93
|
+
}
|
|
94
|
+
|
|
80
95
|
/**
|
|
81
96
|
* Execute git with hardened defaults.
|
|
82
97
|
*
|
|
@@ -86,6 +101,7 @@ function isSafeGitRefName(refName) {
|
|
|
86
101
|
* @returns {Object} spawn result
|
|
87
102
|
*/
|
|
88
103
|
export function hardenedGitCommand(args, options = {}) {
|
|
104
|
+
const gitOperation = inferGitOperation(args);
|
|
89
105
|
const gitAllowProtocol = getGitAllowProtocol();
|
|
90
106
|
const envConfigs = {
|
|
91
107
|
GIT_CONFIG_COUNT: "2",
|
|
@@ -109,6 +125,14 @@ export function hardenedGitCommand(args, options = {}) {
|
|
|
109
125
|
GIT_ALLOW_PROTOCOL: gitAllowProtocol,
|
|
110
126
|
};
|
|
111
127
|
return safeSpawnSync("git", args, {
|
|
128
|
+
cdxgenActivity: {
|
|
129
|
+
blockedReason: `Dry run mode blocks git ${gitOperation} operations.`,
|
|
130
|
+
gitOperation,
|
|
131
|
+
kind: `git-${gitOperation}`,
|
|
132
|
+
metadata: {
|
|
133
|
+
capability: "git-operation",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
112
136
|
shell: false,
|
|
113
137
|
cwd: options.cwd,
|
|
114
138
|
env,
|
|
@@ -45,6 +45,38 @@ describe("source helper purl resolution", () => {
|
|
|
45
45
|
assert.strictEqual(recordActivity.firstCall.args[0].status, "blocked");
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
it("hardenedGitCommand() tags git operations with the specific subcommand", async () => {
|
|
49
|
+
const safeSpawnSync = sinon
|
|
50
|
+
.stub()
|
|
51
|
+
.returns({ status: 0, stdout: "", stderr: "" });
|
|
52
|
+
const { hardenedGitCommand } = await esmock("./source.js", {
|
|
53
|
+
"./utils.js": {
|
|
54
|
+
cdxgenAgent: { get: sinon.stub() },
|
|
55
|
+
DEBUG_MODE: false,
|
|
56
|
+
fetchPomXmlAsJson: sinon.stub(),
|
|
57
|
+
getTmpDir: sinon.stub().returns(os.tmpdir()),
|
|
58
|
+
hasDangerousUnicode: sinon.stub().returns(false),
|
|
59
|
+
isDryRun: false,
|
|
60
|
+
isSecureMode: false,
|
|
61
|
+
isValidDriveRoot: sinon.stub().returns(true),
|
|
62
|
+
isWin: false,
|
|
63
|
+
safeMkdtempSync: sinon.stub(),
|
|
64
|
+
safeRmSync: sinon.stub(),
|
|
65
|
+
safeSpawnSync,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
hardenedGitCommand(["fetch", "--tags"], { cwd: "/tmp/repo" });
|
|
70
|
+
|
|
71
|
+
sinon.assert.calledWithMatch(safeSpawnSync, "git", ["fetch", "--tags"], {
|
|
72
|
+
cdxgenActivity: sinon.match({
|
|
73
|
+
gitOperation: "fetch",
|
|
74
|
+
kind: "git-fetch",
|
|
75
|
+
}),
|
|
76
|
+
cwd: "/tmp/repo",
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
48
80
|
it("resolves npm purl to repository URL", async () => {
|
|
49
81
|
const getStub = sinon.stub().resolves({
|
|
50
82
|
body: {
|