@cyclonedx/cdxgen 12.3.2 → 12.3.3
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 +6 -0
- package/data/rules/ci-permissions.yaml +132 -0
- package/data/rules/dependency-sources.yaml +65 -5
- package/data/rules/package-integrity.yaml +22 -0
- package/lib/cli/index.js +141 -39
- package/lib/cli/index.poku.js +579 -1
- package/lib/helpers/agentFormulationParser.js +6 -2
- package/lib/helpers/agentFormulationParser.poku.js +42 -0
- package/lib/helpers/analyzer.js +38 -9
- package/lib/helpers/analyzer.poku.js +67 -0
- package/lib/helpers/chromextutils.js +25 -3
- package/lib/helpers/chromextutils.poku.js +68 -0
- package/lib/helpers/ciParsers/githubActions.js +79 -0
- package/lib/helpers/ciParsers/githubActions.poku.js +103 -0
- package/lib/helpers/communityAiConfigParser.js +15 -5
- package/lib/helpers/communityAiConfigParser.poku.js +71 -0
- package/lib/helpers/depsUtils.js +5 -0
- package/lib/helpers/depsUtils.poku.js +55 -0
- package/lib/helpers/display.js +45 -22
- package/lib/helpers/display.poku.js +47 -60
- package/lib/helpers/mcpConfigParser.js +21 -5
- package/lib/helpers/mcpConfigParser.poku.js +39 -2
- package/lib/helpers/propertySanitizer.js +121 -0
- package/lib/helpers/utils.js +951 -40
- package/lib/helpers/utils.poku.js +882 -0
- package/lib/managers/binary.js +16 -0
- package/lib/managers/binary.poku.js +1 -0
- package/lib/managers/docker.js +240 -16
- package/lib/managers/docker.poku.js +1142 -2
- package/lib/server/server.js +7 -4
- package/lib/server/server.poku.js +36 -1
- package/lib/stages/postgen/auditBom.poku.js +644 -2
- package/package.json +2 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/chromextutils.d.ts.map +1 -1
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
- package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +1 -0
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/mcpConfigParser.d.ts +1 -1
- package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/helpers/propertySanitizer.d.ts +3 -0
- package/types/lib/helpers/propertySanitizer.d.ts.map +1 -0
- package/types/lib/helpers/utils.d.ts +29 -0
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +3 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
|
@@ -190,7 +190,7 @@ describe("evaluateRule", () => {
|
|
|
190
190
|
);
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
-
it("should detect npm install script from
|
|
193
|
+
it("should detect npm install script from direct manifest source (PKG-001)", async () => {
|
|
194
194
|
const rules = await loadRules(RULES_DIR);
|
|
195
195
|
const rule = rules.find((r) => r.id === "PKG-001");
|
|
196
196
|
assert.ok(rule, "PKG-001 rule should exist");
|
|
@@ -198,7 +198,11 @@ describe("evaluateRule", () => {
|
|
|
198
198
|
const bom = makeBom([
|
|
199
199
|
makeComponent("sketchy-pkg", "1.0.0", [
|
|
200
200
|
["cdx:npm:hasInstallScript", "true"],
|
|
201
|
-
["cdx:npm:
|
|
201
|
+
["cdx:npm:manifestSourceType", "git"],
|
|
202
|
+
[
|
|
203
|
+
"cdx:npm:manifestSource",
|
|
204
|
+
"git+https://github.com/acme/sketchy-pkg.git",
|
|
205
|
+
],
|
|
202
206
|
]),
|
|
203
207
|
]);
|
|
204
208
|
|
|
@@ -207,6 +211,122 @@ describe("evaluateRule", () => {
|
|
|
207
211
|
assert.strictEqual(findings[0].severity, "high");
|
|
208
212
|
});
|
|
209
213
|
|
|
214
|
+
it("should detect npm install scripts from url and path manifest sources for PKG-001", async () => {
|
|
215
|
+
const rules = await loadRules(RULES_DIR);
|
|
216
|
+
const rule = rules.find((r) => r.id === "PKG-001");
|
|
217
|
+
assert.ok(rule, "PKG-001 rule should exist");
|
|
218
|
+
|
|
219
|
+
for (const manifestSourceType of ["url", "path"]) {
|
|
220
|
+
const bom = makeBom([
|
|
221
|
+
makeComponent(`sketchy-${manifestSourceType}`, "1.0.0", [
|
|
222
|
+
["cdx:npm:hasInstallScript", "true"],
|
|
223
|
+
["cdx:npm:manifestSourceType", manifestSourceType],
|
|
224
|
+
["cdx:npm:manifestSource", `${manifestSourceType}:example`],
|
|
225
|
+
]),
|
|
226
|
+
]);
|
|
227
|
+
|
|
228
|
+
const findings = await evaluateRule(rule, bom);
|
|
229
|
+
assert.ok(findings.length > 0);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("should not detect npm install script without manifest source evidence for PKG-001", async () => {
|
|
234
|
+
const rules = await loadRules(RULES_DIR);
|
|
235
|
+
const rule = rules.find((r) => r.id === "PKG-001");
|
|
236
|
+
assert.ok(rule, "PKG-001 rule should exist");
|
|
237
|
+
|
|
238
|
+
const bom = makeBom([
|
|
239
|
+
makeComponent("registry-pkg", "1.0.0", [
|
|
240
|
+
["cdx:npm:hasInstallScript", "true"],
|
|
241
|
+
["cdx:npm:isRegistryDependency", "false"],
|
|
242
|
+
]),
|
|
243
|
+
]);
|
|
244
|
+
|
|
245
|
+
const findings = await evaluateRule(rule, bom);
|
|
246
|
+
assert.strictEqual(findings.length, 0);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("should detect Collider packages from insecure HTTP origins (PKG-009)", async () => {
|
|
250
|
+
const rules = await loadRules(RULES_DIR);
|
|
251
|
+
const rule = rules.find((r) => r.id === "PKG-009");
|
|
252
|
+
assert.ok(rule, "PKG-009 rule should exist");
|
|
253
|
+
|
|
254
|
+
const bom = makeBom([
|
|
255
|
+
makeComponent("fmt", "11.0.2", [
|
|
256
|
+
["cdx:collider:dependencyKind", "direct"],
|
|
257
|
+
["cdx:collider:origin", "http://mirror.example.com/collider/v2/"],
|
|
258
|
+
["cdx:collider:originScheme", "http"],
|
|
259
|
+
["cdx:collider:originHost", "mirror.example.com"],
|
|
260
|
+
]),
|
|
261
|
+
]);
|
|
262
|
+
|
|
263
|
+
const findings = await evaluateRule(rule, bom);
|
|
264
|
+
assert.ok(findings.length > 0, "Should detect insecure Collider origin");
|
|
265
|
+
assert.strictEqual(findings[0].ruleId, "PKG-009");
|
|
266
|
+
assert.strictEqual(findings[0].severity, "medium");
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("should detect Collider origins that required sanitization (PKG-010)", async () => {
|
|
270
|
+
const rules = await loadRules(RULES_DIR);
|
|
271
|
+
const rule = rules.find((r) => r.id === "PKG-010");
|
|
272
|
+
assert.ok(rule, "PKG-010 rule should exist");
|
|
273
|
+
|
|
274
|
+
const bom = makeBom([
|
|
275
|
+
makeComponent("spdlog", "1.15.0", [
|
|
276
|
+
["cdx:collider:dependencyKind", "direct"],
|
|
277
|
+
["cdx:collider:origin", "https://example.com/collider/v2/"],
|
|
278
|
+
["cdx:collider:originScheme", "https"],
|
|
279
|
+
["cdx:collider:originSanitized", "true"],
|
|
280
|
+
]),
|
|
281
|
+
]);
|
|
282
|
+
|
|
283
|
+
const findings = await evaluateRule(rule, bom);
|
|
284
|
+
assert.ok(findings.length > 0, "Should detect sanitized Collider origin");
|
|
285
|
+
assert.strictEqual(findings[0].ruleId, "PKG-010");
|
|
286
|
+
assert.strictEqual(findings[0].severity, "low");
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("should detect python dependency from direct manifest source (PKG-011)", async () => {
|
|
290
|
+
const rules = await loadRules(RULES_DIR);
|
|
291
|
+
const rule = rules.find((r) => r.id === "PKG-011");
|
|
292
|
+
assert.ok(rule, "PKG-011 rule should exist");
|
|
293
|
+
|
|
294
|
+
const bom = makeBom([
|
|
295
|
+
makeComponent("suspicious-python-pkg", "1.0.0", [
|
|
296
|
+
["cdx:pypi:manifestSourceType", "url"],
|
|
297
|
+
[
|
|
298
|
+
"cdx:pypi:manifestSource",
|
|
299
|
+
"https://example.com/suspicious-python-pkg.whl",
|
|
300
|
+
],
|
|
301
|
+
]),
|
|
302
|
+
]);
|
|
303
|
+
|
|
304
|
+
const findings = await evaluateRule(rule, bom);
|
|
305
|
+
assert.ok(findings.length > 0, "Should detect python direct source risk");
|
|
306
|
+
assert.strictEqual(findings[0].ruleId, "PKG-011");
|
|
307
|
+
assert.strictEqual(findings[0].severity, "high");
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("should detect Collider packages missing valid wrap hashes (INT-014)", async () => {
|
|
311
|
+
const rules = await loadRules(RULES_DIR);
|
|
312
|
+
const rule = rules.find((r) => r.id === "INT-014");
|
|
313
|
+
assert.ok(rule, "INT-014 rule should exist");
|
|
314
|
+
|
|
315
|
+
const bom = makeBom([
|
|
316
|
+
makeComponent("fast_float", "8.0.2", [
|
|
317
|
+
["cdx:collider:dependencyKind", "transitive"],
|
|
318
|
+
["cdx:collider:hasWrapHash", "false"],
|
|
319
|
+
["cdx:collider:wrapHash", "not-a-sha256"],
|
|
320
|
+
["cdx:collider:wrapHashInvalid", "true"],
|
|
321
|
+
]),
|
|
322
|
+
]);
|
|
323
|
+
|
|
324
|
+
const findings = await evaluateRule(rule, bom);
|
|
325
|
+
assert.ok(findings.length > 0, "Should detect missing Collider wrap hash");
|
|
326
|
+
assert.strictEqual(findings[0].ruleId, "INT-014");
|
|
327
|
+
assert.strictEqual(findings[0].severity, "high");
|
|
328
|
+
});
|
|
329
|
+
|
|
210
330
|
it("should detect OIDC token issuance to a non-official action (CI-002)", async () => {
|
|
211
331
|
const rules = await loadRules(RULES_DIR);
|
|
212
332
|
const rule = rules.find((r) => r.id === "CI-002");
|
|
@@ -1434,6 +1554,528 @@ describe("evaluateRule", () => {
|
|
|
1434
1554
|
assert.match(findings[0].message, /Heuristic review/);
|
|
1435
1555
|
});
|
|
1436
1556
|
|
|
1557
|
+
it("should detect disabled npm cache when npm distributions are resolved remotely (CI-022)", async () => {
|
|
1558
|
+
const rules = await loadRules(RULES_DIR);
|
|
1559
|
+
const rule = rules.find((r) => r.id === "CI-022");
|
|
1560
|
+
assert.ok(rule, "CI-022 rule should exist");
|
|
1561
|
+
|
|
1562
|
+
const bom = makeBom(
|
|
1563
|
+
[
|
|
1564
|
+
{
|
|
1565
|
+
type: "library",
|
|
1566
|
+
name: "left-pad",
|
|
1567
|
+
version: "1.3.0",
|
|
1568
|
+
purl: "pkg:npm/left-pad@1.3.0",
|
|
1569
|
+
"bom-ref": "pkg:npm/left-pad@1.3.0",
|
|
1570
|
+
externalReferences: [
|
|
1571
|
+
{
|
|
1572
|
+
type: "distribution",
|
|
1573
|
+
url: "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
|
|
1574
|
+
},
|
|
1575
|
+
],
|
|
1576
|
+
properties: [
|
|
1577
|
+
{
|
|
1578
|
+
name: "cdx:npm:manifestSourceType",
|
|
1579
|
+
value: "url",
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
name: "cdx:npm:manifestSource",
|
|
1583
|
+
value: "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
|
|
1584
|
+
},
|
|
1585
|
+
],
|
|
1586
|
+
},
|
|
1587
|
+
],
|
|
1588
|
+
[],
|
|
1589
|
+
[
|
|
1590
|
+
{
|
|
1591
|
+
type: "application",
|
|
1592
|
+
name: "setup-node",
|
|
1593
|
+
version: "v4",
|
|
1594
|
+
purl: "pkg:github/actions/setup-node@v4",
|
|
1595
|
+
"bom-ref": "pkg:github/actions/setup-node@v4",
|
|
1596
|
+
properties: [
|
|
1597
|
+
{
|
|
1598
|
+
name: "cdx:github:action:uses",
|
|
1599
|
+
value: "actions/setup-node@v4",
|
|
1600
|
+
},
|
|
1601
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1602
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "npm" },
|
|
1603
|
+
{
|
|
1604
|
+
name: "cdx:github:action:buildCacheDisableInput",
|
|
1605
|
+
value: "package-manager-cache",
|
|
1606
|
+
},
|
|
1607
|
+
{
|
|
1608
|
+
name: "cdx:github:action:buildCacheDisableValue",
|
|
1609
|
+
value: "false",
|
|
1610
|
+
},
|
|
1611
|
+
{
|
|
1612
|
+
name: "cdx:github:workflow:file",
|
|
1613
|
+
value: ".github/workflows/ci.yml",
|
|
1614
|
+
},
|
|
1615
|
+
],
|
|
1616
|
+
},
|
|
1617
|
+
],
|
|
1618
|
+
);
|
|
1619
|
+
|
|
1620
|
+
const findings = await evaluateRule(rule, bom);
|
|
1621
|
+
assert.ok(findings.length > 0, "Should detect disabled npm cache");
|
|
1622
|
+
assert.strictEqual(findings[0].severity, "medium");
|
|
1623
|
+
});
|
|
1624
|
+
|
|
1625
|
+
it("should detect disabled npm cache for git manifest sources (CI-022)", async () => {
|
|
1626
|
+
const rules = await loadRules(RULES_DIR);
|
|
1627
|
+
const rule = rules.find((r) => r.id === "CI-022");
|
|
1628
|
+
assert.ok(rule, "CI-022 rule should exist");
|
|
1629
|
+
|
|
1630
|
+
const bom = makeBom(
|
|
1631
|
+
[
|
|
1632
|
+
{
|
|
1633
|
+
type: "library",
|
|
1634
|
+
name: "git-dep",
|
|
1635
|
+
version: "2.0.0",
|
|
1636
|
+
purl: "pkg:npm/git-dep@2.0.0",
|
|
1637
|
+
"bom-ref": "pkg:npm/git-dep@2.0.0",
|
|
1638
|
+
externalReferences: [
|
|
1639
|
+
{
|
|
1640
|
+
type: "distribution",
|
|
1641
|
+
url: "git+https://github.com/acme/git-dep.git",
|
|
1642
|
+
},
|
|
1643
|
+
],
|
|
1644
|
+
properties: [
|
|
1645
|
+
{
|
|
1646
|
+
name: "cdx:npm:manifestSourceType",
|
|
1647
|
+
value: "git",
|
|
1648
|
+
},
|
|
1649
|
+
{
|
|
1650
|
+
name: "cdx:npm:manifestSource",
|
|
1651
|
+
value: "git+https://github.com/acme/git-dep.git",
|
|
1652
|
+
},
|
|
1653
|
+
],
|
|
1654
|
+
},
|
|
1655
|
+
],
|
|
1656
|
+
[],
|
|
1657
|
+
[
|
|
1658
|
+
{
|
|
1659
|
+
type: "application",
|
|
1660
|
+
name: "setup-node",
|
|
1661
|
+
version: "v4",
|
|
1662
|
+
purl: "pkg:github/actions/setup-node@v4",
|
|
1663
|
+
"bom-ref": "pkg:github/actions/setup-node@v4",
|
|
1664
|
+
properties: [
|
|
1665
|
+
{
|
|
1666
|
+
name: "cdx:github:action:uses",
|
|
1667
|
+
value: "actions/setup-node@v4",
|
|
1668
|
+
},
|
|
1669
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1670
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "npm" },
|
|
1671
|
+
],
|
|
1672
|
+
},
|
|
1673
|
+
],
|
|
1674
|
+
);
|
|
1675
|
+
|
|
1676
|
+
const findings = await evaluateRule(rule, bom);
|
|
1677
|
+
assert.ok(findings.length > 0, "Should detect disabled npm cache");
|
|
1678
|
+
});
|
|
1679
|
+
|
|
1680
|
+
it("should not detect disabled npm cache for registry-only npm dependencies (CI-022)", async () => {
|
|
1681
|
+
const rules = await loadRules(RULES_DIR);
|
|
1682
|
+
const rule = rules.find((r) => r.id === "CI-022");
|
|
1683
|
+
assert.ok(rule, "CI-022 rule should exist");
|
|
1684
|
+
|
|
1685
|
+
const bom = makeBom(
|
|
1686
|
+
[
|
|
1687
|
+
{
|
|
1688
|
+
type: "library",
|
|
1689
|
+
name: "left-pad",
|
|
1690
|
+
version: "1.3.0",
|
|
1691
|
+
purl: "pkg:npm/left-pad@1.3.0",
|
|
1692
|
+
"bom-ref": "pkg:npm/left-pad@1.3.0",
|
|
1693
|
+
externalReferences: [
|
|
1694
|
+
{
|
|
1695
|
+
type: "distribution",
|
|
1696
|
+
url: "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
|
|
1697
|
+
},
|
|
1698
|
+
],
|
|
1699
|
+
},
|
|
1700
|
+
],
|
|
1701
|
+
[],
|
|
1702
|
+
[
|
|
1703
|
+
{
|
|
1704
|
+
type: "application",
|
|
1705
|
+
name: "setup-node",
|
|
1706
|
+
version: "v4",
|
|
1707
|
+
purl: "pkg:github/actions/setup-node@v4",
|
|
1708
|
+
"bom-ref": "pkg:github/actions/setup-node@v4",
|
|
1709
|
+
properties: [
|
|
1710
|
+
{
|
|
1711
|
+
name: "cdx:github:action:uses",
|
|
1712
|
+
value: "actions/setup-node@v4",
|
|
1713
|
+
},
|
|
1714
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1715
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "npm" },
|
|
1716
|
+
],
|
|
1717
|
+
},
|
|
1718
|
+
],
|
|
1719
|
+
);
|
|
1720
|
+
|
|
1721
|
+
const findings = await evaluateRule(rule, bom);
|
|
1722
|
+
assert.strictEqual(findings.length, 0);
|
|
1723
|
+
});
|
|
1724
|
+
|
|
1725
|
+
it("should not detect disabled npm cache for local path manifest sources (CI-022)", async () => {
|
|
1726
|
+
const rules = await loadRules(RULES_DIR);
|
|
1727
|
+
const rule = rules.find((r) => r.id === "CI-022");
|
|
1728
|
+
assert.ok(rule, "CI-022 rule should exist");
|
|
1729
|
+
|
|
1730
|
+
const bom = makeBom(
|
|
1731
|
+
[
|
|
1732
|
+
{
|
|
1733
|
+
type: "library",
|
|
1734
|
+
name: "local-dep",
|
|
1735
|
+
version: "1.0.0",
|
|
1736
|
+
purl: "pkg:npm/local-dep@1.0.0",
|
|
1737
|
+
"bom-ref": "pkg:npm/local-dep@1.0.0",
|
|
1738
|
+
externalReferences: [
|
|
1739
|
+
{
|
|
1740
|
+
type: "distribution",
|
|
1741
|
+
url: "file:../libs/local-dep",
|
|
1742
|
+
},
|
|
1743
|
+
],
|
|
1744
|
+
properties: [
|
|
1745
|
+
{
|
|
1746
|
+
name: "cdx:npm:manifestSourceType",
|
|
1747
|
+
value: "path",
|
|
1748
|
+
},
|
|
1749
|
+
{
|
|
1750
|
+
name: "cdx:npm:manifestSource",
|
|
1751
|
+
value: "file:../libs/local-dep",
|
|
1752
|
+
},
|
|
1753
|
+
],
|
|
1754
|
+
},
|
|
1755
|
+
],
|
|
1756
|
+
[],
|
|
1757
|
+
[
|
|
1758
|
+
{
|
|
1759
|
+
type: "application",
|
|
1760
|
+
name: "setup-node",
|
|
1761
|
+
version: "v4",
|
|
1762
|
+
purl: "pkg:github/actions/setup-node@v4",
|
|
1763
|
+
"bom-ref": "pkg:github/actions/setup-node@v4",
|
|
1764
|
+
properties: [
|
|
1765
|
+
{
|
|
1766
|
+
name: "cdx:github:action:uses",
|
|
1767
|
+
value: "actions/setup-node@v4",
|
|
1768
|
+
},
|
|
1769
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1770
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "npm" },
|
|
1771
|
+
],
|
|
1772
|
+
},
|
|
1773
|
+
],
|
|
1774
|
+
);
|
|
1775
|
+
|
|
1776
|
+
const findings = await evaluateRule(rule, bom);
|
|
1777
|
+
assert.strictEqual(findings.length, 0);
|
|
1778
|
+
});
|
|
1779
|
+
|
|
1780
|
+
it("should detect disabled Python cache when pylock sources use remote artifacts (CI-023)", async () => {
|
|
1781
|
+
const rules = await loadRules(RULES_DIR);
|
|
1782
|
+
const rule = rules.find((r) => r.id === "CI-023");
|
|
1783
|
+
assert.ok(rule, "CI-023 rule should exist");
|
|
1784
|
+
|
|
1785
|
+
const bom = makeBom(
|
|
1786
|
+
[
|
|
1787
|
+
{
|
|
1788
|
+
type: "library",
|
|
1789
|
+
name: "requests",
|
|
1790
|
+
version: "2.32.0",
|
|
1791
|
+
purl: "pkg:pypi/requests@2.32.0",
|
|
1792
|
+
"bom-ref": "pkg:pypi/requests@2.32.0",
|
|
1793
|
+
properties: [
|
|
1794
|
+
{
|
|
1795
|
+
name: "cdx:pypi:manifestSourceType",
|
|
1796
|
+
value: "url",
|
|
1797
|
+
},
|
|
1798
|
+
{
|
|
1799
|
+
name: "cdx:pypi:manifestSource",
|
|
1800
|
+
value:
|
|
1801
|
+
"https://files.pythonhosted.org/packages/requests-2.32.0.tar.gz",
|
|
1802
|
+
},
|
|
1803
|
+
],
|
|
1804
|
+
},
|
|
1805
|
+
],
|
|
1806
|
+
[],
|
|
1807
|
+
[
|
|
1808
|
+
{
|
|
1809
|
+
type: "application",
|
|
1810
|
+
name: "setup-python",
|
|
1811
|
+
version: "v5",
|
|
1812
|
+
purl: "pkg:github/actions/setup-python@v5",
|
|
1813
|
+
"bom-ref": "pkg:github/actions/setup-python@v5",
|
|
1814
|
+
properties: [
|
|
1815
|
+
{
|
|
1816
|
+
name: "cdx:github:action:uses",
|
|
1817
|
+
value: "actions/setup-python@v5",
|
|
1818
|
+
},
|
|
1819
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1820
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "pypi" },
|
|
1821
|
+
{
|
|
1822
|
+
name: "cdx:github:action:buildCacheDisableInput",
|
|
1823
|
+
value: "cache",
|
|
1824
|
+
},
|
|
1825
|
+
{
|
|
1826
|
+
name: "cdx:github:action:buildCacheDisableValue",
|
|
1827
|
+
value: "false",
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
name: "cdx:github:workflow:file",
|
|
1831
|
+
value: ".github/workflows/ci.yml",
|
|
1832
|
+
},
|
|
1833
|
+
],
|
|
1834
|
+
},
|
|
1835
|
+
],
|
|
1836
|
+
);
|
|
1837
|
+
|
|
1838
|
+
const findings = await evaluateRule(rule, bom);
|
|
1839
|
+
assert.ok(findings.length > 0, "Should detect disabled Python cache");
|
|
1840
|
+
assert.strictEqual(findings[0].severity, "medium");
|
|
1841
|
+
});
|
|
1842
|
+
|
|
1843
|
+
it("should detect disabled Python cache for git manifest sources (CI-023)", async () => {
|
|
1844
|
+
const rules = await loadRules(RULES_DIR);
|
|
1845
|
+
const rule = rules.find((r) => r.id === "CI-023");
|
|
1846
|
+
assert.ok(rule, "CI-023 rule should exist");
|
|
1847
|
+
|
|
1848
|
+
const bom = makeBom(
|
|
1849
|
+
[
|
|
1850
|
+
{
|
|
1851
|
+
type: "library",
|
|
1852
|
+
name: "private-lib",
|
|
1853
|
+
version: "1.0.0",
|
|
1854
|
+
purl: "pkg:pypi/private-lib@1.0.0",
|
|
1855
|
+
"bom-ref": "pkg:pypi/private-lib@1.0.0",
|
|
1856
|
+
properties: [
|
|
1857
|
+
{
|
|
1858
|
+
name: "cdx:pypi:manifestSourceType",
|
|
1859
|
+
value: "git",
|
|
1860
|
+
},
|
|
1861
|
+
{
|
|
1862
|
+
name: "cdx:pypi:manifestSource",
|
|
1863
|
+
value: "git+https://github.com/acme/private-lib.git",
|
|
1864
|
+
},
|
|
1865
|
+
],
|
|
1866
|
+
},
|
|
1867
|
+
],
|
|
1868
|
+
[],
|
|
1869
|
+
[
|
|
1870
|
+
{
|
|
1871
|
+
type: "application",
|
|
1872
|
+
name: "setup-python",
|
|
1873
|
+
version: "v5",
|
|
1874
|
+
purl: "pkg:github/actions/setup-python@v5",
|
|
1875
|
+
"bom-ref": "pkg:github/actions/setup-python@v5",
|
|
1876
|
+
properties: [
|
|
1877
|
+
{
|
|
1878
|
+
name: "cdx:github:action:uses",
|
|
1879
|
+
value: "actions/setup-python@v5",
|
|
1880
|
+
},
|
|
1881
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1882
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "pypi" },
|
|
1883
|
+
],
|
|
1884
|
+
},
|
|
1885
|
+
],
|
|
1886
|
+
);
|
|
1887
|
+
|
|
1888
|
+
const findings = await evaluateRule(rule, bom);
|
|
1889
|
+
assert.ok(findings.length > 0, "Should detect disabled Python cache");
|
|
1890
|
+
});
|
|
1891
|
+
|
|
1892
|
+
it("should not detect disabled Python cache for registry-only lockfile sources (CI-023)", async () => {
|
|
1893
|
+
const rules = await loadRules(RULES_DIR);
|
|
1894
|
+
const rule = rules.find((r) => r.id === "CI-023");
|
|
1895
|
+
assert.ok(rule, "CI-023 rule should exist");
|
|
1896
|
+
|
|
1897
|
+
const bom = makeBom(
|
|
1898
|
+
[
|
|
1899
|
+
{
|
|
1900
|
+
type: "library",
|
|
1901
|
+
name: "requests",
|
|
1902
|
+
version: "2.32.0",
|
|
1903
|
+
purl: "pkg:pypi/requests@2.32.0",
|
|
1904
|
+
"bom-ref": "pkg:pypi/requests@2.32.0",
|
|
1905
|
+
properties: [
|
|
1906
|
+
{
|
|
1907
|
+
name: "cdx:pylock:archive",
|
|
1908
|
+
value:
|
|
1909
|
+
'{"url":"https://files.pythonhosted.org/packages/requests-2.32.0.tar.gz"}',
|
|
1910
|
+
},
|
|
1911
|
+
],
|
|
1912
|
+
},
|
|
1913
|
+
],
|
|
1914
|
+
[],
|
|
1915
|
+
[
|
|
1916
|
+
{
|
|
1917
|
+
type: "application",
|
|
1918
|
+
name: "setup-python",
|
|
1919
|
+
version: "v5",
|
|
1920
|
+
purl: "pkg:github/actions/setup-python@v5",
|
|
1921
|
+
"bom-ref": "pkg:github/actions/setup-python@v5",
|
|
1922
|
+
properties: [
|
|
1923
|
+
{
|
|
1924
|
+
name: "cdx:github:action:uses",
|
|
1925
|
+
value: "actions/setup-python@v5",
|
|
1926
|
+
},
|
|
1927
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1928
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "pypi" },
|
|
1929
|
+
],
|
|
1930
|
+
},
|
|
1931
|
+
],
|
|
1932
|
+
);
|
|
1933
|
+
|
|
1934
|
+
const findings = await evaluateRule(rule, bom);
|
|
1935
|
+
assert.strictEqual(findings.length, 0);
|
|
1936
|
+
});
|
|
1937
|
+
|
|
1938
|
+
it("should not detect disabled Python cache for local path manifest sources (CI-023)", async () => {
|
|
1939
|
+
const rules = await loadRules(RULES_DIR);
|
|
1940
|
+
const rule = rules.find((r) => r.id === "CI-023");
|
|
1941
|
+
assert.ok(rule, "CI-023 rule should exist");
|
|
1942
|
+
|
|
1943
|
+
const bom = makeBom(
|
|
1944
|
+
[
|
|
1945
|
+
{
|
|
1946
|
+
type: "library",
|
|
1947
|
+
name: "local-lib",
|
|
1948
|
+
version: "1.0.0",
|
|
1949
|
+
purl: "pkg:pypi/local-lib@1.0.0",
|
|
1950
|
+
"bom-ref": "pkg:pypi/local-lib@1.0.0",
|
|
1951
|
+
properties: [
|
|
1952
|
+
{
|
|
1953
|
+
name: "cdx:pypi:manifestSourceType",
|
|
1954
|
+
value: "path",
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
name: "cdx:pypi:manifestSource",
|
|
1958
|
+
value: "../libs/local-lib",
|
|
1959
|
+
},
|
|
1960
|
+
],
|
|
1961
|
+
},
|
|
1962
|
+
],
|
|
1963
|
+
[],
|
|
1964
|
+
[
|
|
1965
|
+
{
|
|
1966
|
+
type: "application",
|
|
1967
|
+
name: "setup-python",
|
|
1968
|
+
version: "v5",
|
|
1969
|
+
purl: "pkg:github/actions/setup-python@v5",
|
|
1970
|
+
"bom-ref": "pkg:github/actions/setup-python@v5",
|
|
1971
|
+
properties: [
|
|
1972
|
+
{
|
|
1973
|
+
name: "cdx:github:action:uses",
|
|
1974
|
+
value: "actions/setup-python@v5",
|
|
1975
|
+
},
|
|
1976
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
1977
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "pypi" },
|
|
1978
|
+
],
|
|
1979
|
+
},
|
|
1980
|
+
],
|
|
1981
|
+
);
|
|
1982
|
+
|
|
1983
|
+
const findings = await evaluateRule(rule, bom);
|
|
1984
|
+
assert.strictEqual(findings.length, 0);
|
|
1985
|
+
});
|
|
1986
|
+
|
|
1987
|
+
it("should detect disabled Cargo cache for git manifest sources (CI-024)", async () => {
|
|
1988
|
+
const rules = await loadRules(RULES_DIR);
|
|
1989
|
+
const rule = rules.find((r) => r.id === "CI-024");
|
|
1990
|
+
assert.ok(rule, "CI-024 rule should exist");
|
|
1991
|
+
|
|
1992
|
+
const bom = makeBom(
|
|
1993
|
+
[
|
|
1994
|
+
{
|
|
1995
|
+
type: "library",
|
|
1996
|
+
name: "git-crate",
|
|
1997
|
+
version: "git+https://github.com/acme/git-crate.git",
|
|
1998
|
+
purl: "pkg:cargo/git-crate@git+https://github.com/acme/git-crate.git",
|
|
1999
|
+
"bom-ref":
|
|
2000
|
+
"pkg:cargo/git-crate@git+https://github.com/acme/git-crate.git",
|
|
2001
|
+
properties: [
|
|
2002
|
+
{
|
|
2003
|
+
name: "cdx:cargo:git",
|
|
2004
|
+
value: "https://github.com/acme/git-crate.git",
|
|
2005
|
+
},
|
|
2006
|
+
],
|
|
2007
|
+
},
|
|
2008
|
+
],
|
|
2009
|
+
[],
|
|
2010
|
+
[
|
|
2011
|
+
{
|
|
2012
|
+
type: "application",
|
|
2013
|
+
name: "setup-rust",
|
|
2014
|
+
version: "v1",
|
|
2015
|
+
purl: "pkg:github/moonrepo/setup-rust@v1",
|
|
2016
|
+
"bom-ref": "pkg:github/moonrepo/setup-rust@v1",
|
|
2017
|
+
properties: [
|
|
2018
|
+
{
|
|
2019
|
+
name: "cdx:github:action:uses",
|
|
2020
|
+
value: "moonrepo/setup-rust@v1",
|
|
2021
|
+
},
|
|
2022
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
2023
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "cargo" },
|
|
2024
|
+
],
|
|
2025
|
+
},
|
|
2026
|
+
],
|
|
2027
|
+
);
|
|
2028
|
+
|
|
2029
|
+
const findings = await evaluateRule(rule, bom);
|
|
2030
|
+
assert.ok(findings.length > 0, "Should detect disabled Cargo cache");
|
|
2031
|
+
assert.strictEqual(findings[0].severity, "medium");
|
|
2032
|
+
});
|
|
2033
|
+
|
|
2034
|
+
it("should not detect disabled Cargo cache for local path manifest sources (CI-024)", async () => {
|
|
2035
|
+
const rules = await loadRules(RULES_DIR);
|
|
2036
|
+
const rule = rules.find((r) => r.id === "CI-024");
|
|
2037
|
+
assert.ok(rule, "CI-024 rule should exist");
|
|
2038
|
+
|
|
2039
|
+
const bom = makeBom(
|
|
2040
|
+
[
|
|
2041
|
+
{
|
|
2042
|
+
type: "library",
|
|
2043
|
+
name: "path-crate",
|
|
2044
|
+
version: "path+../path-crate",
|
|
2045
|
+
purl: "pkg:cargo/path-crate@path+../path-crate",
|
|
2046
|
+
"bom-ref": "pkg:cargo/path-crate@path+../path-crate",
|
|
2047
|
+
properties: [
|
|
2048
|
+
{
|
|
2049
|
+
name: "cdx:cargo:path",
|
|
2050
|
+
value: "../path-crate",
|
|
2051
|
+
},
|
|
2052
|
+
],
|
|
2053
|
+
},
|
|
2054
|
+
],
|
|
2055
|
+
[],
|
|
2056
|
+
[
|
|
2057
|
+
{
|
|
2058
|
+
type: "application",
|
|
2059
|
+
name: "setup-rust",
|
|
2060
|
+
version: "v1",
|
|
2061
|
+
purl: "pkg:github/moonrepo/setup-rust@v1",
|
|
2062
|
+
"bom-ref": "pkg:github/moonrepo/setup-rust@v1",
|
|
2063
|
+
properties: [
|
|
2064
|
+
{
|
|
2065
|
+
name: "cdx:github:action:uses",
|
|
2066
|
+
value: "moonrepo/setup-rust@v1",
|
|
2067
|
+
},
|
|
2068
|
+
{ name: "cdx:github:action:disablesBuildCache", value: "true" },
|
|
2069
|
+
{ name: "cdx:github:action:buildCacheEcosystem", value: "cargo" },
|
|
2070
|
+
],
|
|
2071
|
+
},
|
|
2072
|
+
],
|
|
2073
|
+
);
|
|
2074
|
+
|
|
2075
|
+
const findings = await evaluateRule(rule, bom);
|
|
2076
|
+
assert.strictEqual(findings.length, 0);
|
|
2077
|
+
});
|
|
2078
|
+
|
|
1437
2079
|
it("should detect root authorized_keys without restrictions (OBOM-LNX-003)", async () => {
|
|
1438
2080
|
const rules = await loadRules(RULES_DIR);
|
|
1439
2081
|
const rule = rules.find((r) => r.id === "OBOM-LNX-003");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyclonedx/cdxgen",
|
|
3
|
-
"version": "12.3.
|
|
3
|
+
"version": "12.3.3",
|
|
4
4
|
"description": "Creates CycloneDX Software Bill of Materials (SBOM) from source or container image",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sbom",
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
"files": [
|
|
99
99
|
"*.js",
|
|
100
100
|
"lib/**",
|
|
101
|
+
"!lib/**/*.poku.js",
|
|
101
102
|
"bin/",
|
|
102
103
|
"data/",
|
|
103
104
|
"types/",
|