@cyclonedx/cdxgen 12.4.3 → 12.4.4
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/bin/audit.js +7 -0
- package/bin/cdxgen.js +48 -2
- package/bin/evinse.js +7 -0
- package/lib/audit/index.js +165 -2
- package/lib/audit/index.poku.js +462 -0
- package/lib/cli/index.js +317 -169
- package/lib/evinser/evinser.js +31 -9
- package/lib/helpers/analyzer.js +890 -0
- package/lib/helpers/analyzer.poku.js +341 -0
- package/lib/helpers/atomUtils.js +445 -0
- package/lib/helpers/atomUtils.poku.js +137 -0
- package/lib/helpers/bomUtils.js +71 -0
- package/lib/helpers/bomUtils.poku.js +45 -0
- package/lib/helpers/depsUtils.js +146 -0
- package/lib/helpers/depsUtils.poku.js +183 -0
- package/lib/helpers/utils.js +585 -191
- package/lib/helpers/utils.poku.js +357 -4
- package/lib/managers/binary.js +18 -9
- package/lib/stages/postgen/postgen.js +215 -0
- package/lib/stages/postgen/postgen.poku.js +218 -3
- package/lib/validator/bomValidator.js +11 -2
- package/package.json +8 -8
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/atomUtils.d.ts +18 -0
- package/types/lib/helpers/atomUtils.d.ts.map +1 -0
- package/types/lib/helpers/bomUtils.d.ts +10 -0
- package/types/lib/helpers/bomUtils.d.ts.map +1 -1
- package/types/lib/helpers/depsUtils.d.ts +9 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +19 -0
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +2 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
package/lib/cli/index.js
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
} from "../helpers/asarutils.js";
|
|
43
43
|
import { expandBomAuditCategories } from "../helpers/auditCategories.js";
|
|
44
44
|
import {
|
|
45
|
+
isCycloneDxComponentTypeEnabled,
|
|
45
46
|
setCycloneDxFormat,
|
|
46
47
|
toCycloneDxSpecVersionString,
|
|
47
48
|
} from "../helpers/bomUtils.js";
|
|
@@ -57,8 +58,10 @@ import {
|
|
|
57
58
|
discoverChromiumExtensionDirs,
|
|
58
59
|
} from "../helpers/chromextutils.js";
|
|
59
60
|
import {
|
|
61
|
+
filterInvalidCryptoComponents,
|
|
60
62
|
mergeDependencies,
|
|
61
63
|
mergeServices,
|
|
64
|
+
propagateRequiredScopeFromDependencies,
|
|
62
65
|
trimComponents,
|
|
63
66
|
} from "../helpers/depsUtils.js";
|
|
64
67
|
import {
|
|
@@ -192,7 +195,9 @@ import {
|
|
|
192
195
|
parseLeinDep,
|
|
193
196
|
parseLeiningenData,
|
|
194
197
|
parseMakeDFile,
|
|
198
|
+
parseMavenArgs,
|
|
195
199
|
parseMavenTree,
|
|
200
|
+
parseMavenTreeJson,
|
|
196
201
|
parseMillDependency,
|
|
197
202
|
parseMinJs,
|
|
198
203
|
parseMixLockData,
|
|
@@ -1727,7 +1732,7 @@ export async function createJavaBom(path, options) {
|
|
|
1727
1732
|
}
|
|
1728
1733
|
// Support for passing additional settings and profile to maven
|
|
1729
1734
|
if (process.env.MVN_ARGS) {
|
|
1730
|
-
const addArgs = process.env.MVN_ARGS
|
|
1735
|
+
const addArgs = parseMavenArgs(process.env.MVN_ARGS);
|
|
1731
1736
|
mvnArgs = mvnArgs.concat(addArgs);
|
|
1732
1737
|
}
|
|
1733
1738
|
// specVersion 1.4 doesn't support externalReferences.type=distribution-intake
|
|
@@ -1804,180 +1809,270 @@ export async function createJavaBom(path, options) {
|
|
|
1804
1809
|
result?.status !== 0 ||
|
|
1805
1810
|
result?.error
|
|
1806
1811
|
) {
|
|
1807
|
-
const
|
|
1808
|
-
const
|
|
1809
|
-
|
|
1810
|
-
|
|
1812
|
+
const tempRoot = getTmpDir();
|
|
1813
|
+
const tempDir = safeMkdtempSync(join(tempRoot, "cdxgen-mvn-"));
|
|
1814
|
+
const tempMvnTree = join(tempDir, "cdxgen-mvn-tree.json");
|
|
1815
|
+
const tempMvnTreeText = join(tempDir, "cdxgen-mvn-tree.txt");
|
|
1816
|
+
const tempMvnParentTree = join(tempDir, "cdxgen-mvn-parent-tree.json");
|
|
1817
|
+
const tempMvnParentTreeText = join(
|
|
1818
|
+
tempDir,
|
|
1811
1819
|
"cdxgen-mvn-parent-tree.txt",
|
|
1812
1820
|
);
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
if (process.env.MVN_ARGS) {
|
|
1816
|
-
addArgs = process.env.MVN_ARGS.split(" ");
|
|
1817
|
-
mvnTreeArgs = mvnTreeArgs.concat(addArgs);
|
|
1818
|
-
}
|
|
1819
|
-
// Automatically use settings.xml to improve the success for fallback
|
|
1820
|
-
if (safeExistsSync(settingsXml)) {
|
|
1821
|
-
mvnTreeArgs.push("-s");
|
|
1822
|
-
mvnTreeArgs.push(settingsXml);
|
|
1823
|
-
}
|
|
1824
|
-
// For the first pom alone, we need to execute first in non-recursive mode to capture
|
|
1825
|
-
// the parent component. Then, we execute all of them in recursive mode
|
|
1826
|
-
if (f === firstPom) {
|
|
1827
|
-
thoughtLog(
|
|
1828
|
-
"What is the parent component here? Let's use maven command to find out.",
|
|
1829
|
-
);
|
|
1830
|
-
let findParentComponentArgs = [
|
|
1821
|
+
try {
|
|
1822
|
+
let mvnTreeArgs = [
|
|
1831
1823
|
"dependency:tree",
|
|
1832
|
-
|
|
1833
|
-
|
|
1824
|
+
`-DoutputFile=${tempMvnTree}`,
|
|
1825
|
+
"-DoutputType=json",
|
|
1834
1826
|
];
|
|
1835
|
-
|
|
1836
|
-
|
|
1827
|
+
let addArgs = [];
|
|
1828
|
+
if (process.env.MVN_ARGS) {
|
|
1829
|
+
addArgs = parseMavenArgs(process.env.MVN_ARGS);
|
|
1830
|
+
mvnTreeArgs = mvnTreeArgs.concat(addArgs);
|
|
1837
1831
|
}
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1832
|
+
// Automatically use settings.xml to improve the success for fallback
|
|
1833
|
+
if (safeExistsSync(settingsXml)) {
|
|
1834
|
+
mvnTreeArgs.push("-s");
|
|
1835
|
+
mvnTreeArgs.push(settingsXml);
|
|
1836
|
+
}
|
|
1837
|
+
// For the first pom alone, we need to execute first in non-recursive mode to capture
|
|
1838
|
+
// the parent component. Then, we execute all of them in recursive mode
|
|
1839
|
+
if (f === firstPom) {
|
|
1840
|
+
thoughtLog(
|
|
1841
|
+
"What is the parent component here? Let's use maven command to find out.",
|
|
1842
|
+
);
|
|
1843
|
+
let findParentComponentArgs = [
|
|
1844
|
+
"dependency:tree",
|
|
1845
|
+
"-N",
|
|
1846
|
+
`-DoutputFile=${tempMvnParentTree}`,
|
|
1847
|
+
"-DoutputType=json",
|
|
1848
|
+
];
|
|
1849
|
+
if (addArgs.length) {
|
|
1850
|
+
findParentComponentArgs = findParentComponentArgs.concat(addArgs);
|
|
1851
|
+
}
|
|
1852
|
+
result = safeSpawnSync(mavenCmd, findParentComponentArgs, {
|
|
1853
|
+
cwd: basePath,
|
|
1854
|
+
shell: isWin,
|
|
1855
|
+
});
|
|
1856
|
+
// If json is empty or unparseable, fallback to text parsing
|
|
1857
|
+
let emptyJson = !safeExistsSync(tempMvnParentTree);
|
|
1843
1858
|
if (safeExistsSync(tempMvnParentTree)) {
|
|
1844
1859
|
const mvnTreeString = readFileSync(tempMvnParentTree, {
|
|
1845
1860
|
encoding: "utf-8",
|
|
1846
1861
|
});
|
|
1847
|
-
const parsedList =
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1862
|
+
const parsedList = parseMavenTreeJson(mvnTreeString, f);
|
|
1863
|
+
if (!parsedList?.pkgList?.length) {
|
|
1864
|
+
emptyJson = true;
|
|
1865
|
+
// Remove the invalid json file so text output is preferred below.
|
|
1866
|
+
if (safeExistsSync(tempMvnParentTree)) {
|
|
1867
|
+
safeUnlinkSync(tempMvnParentTree);
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
if (result.status !== 0 || result.error || emptyJson) {
|
|
1872
|
+
findParentComponentArgs = [
|
|
1873
|
+
"dependency:tree",
|
|
1874
|
+
"-N",
|
|
1875
|
+
`-DoutputFile=${tempMvnParentTreeText}`,
|
|
1876
|
+
];
|
|
1877
|
+
if (addArgs.length) {
|
|
1878
|
+
findParentComponentArgs =
|
|
1879
|
+
findParentComponentArgs.concat(addArgs);
|
|
1880
|
+
}
|
|
1881
|
+
result = safeSpawnSync(mavenCmd, findParentComponentArgs, {
|
|
1882
|
+
cwd: basePath,
|
|
1883
|
+
shell: isWin,
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
if (result.status === 0) {
|
|
1887
|
+
const parentTreeFile = safeExistsSync(tempMvnParentTreeText)
|
|
1888
|
+
? tempMvnParentTreeText
|
|
1889
|
+
: tempMvnParentTree;
|
|
1890
|
+
if (safeExistsSync(parentTreeFile)) {
|
|
1891
|
+
const mvnTreeString = readFileSync(parentTreeFile, {
|
|
1892
|
+
encoding: "utf-8",
|
|
1893
|
+
});
|
|
1894
|
+
const parsedList = parentTreeFile.endsWith(".json")
|
|
1895
|
+
? parseMavenTreeJson(mvnTreeString, f)
|
|
1896
|
+
: parseMavenTree(mvnTreeString, f);
|
|
1897
|
+
const dlist = parsedList.pkgList || [];
|
|
1898
|
+
if (dlist.length) {
|
|
1899
|
+
const tmpParentComponent = dlist.splice(0, 1)[0];
|
|
1900
|
+
tmpParentComponent.type = "application";
|
|
1901
|
+
parentComponent = tmpParentComponent;
|
|
1902
|
+
parentComponent.components = [];
|
|
1903
|
+
if (parentComponent.name) {
|
|
1904
|
+
thoughtLog(
|
|
1905
|
+
`Parent component is called ${parentComponent.name}!`,
|
|
1906
|
+
);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1857
1909
|
}
|
|
1858
1910
|
}
|
|
1859
1911
|
}
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
PREFER_MAVEN_DEPS_TREE ? "mvn" : mavenCmd,
|
|
1870
|
-
mvnTreeArgs,
|
|
1871
|
-
{
|
|
1912
|
+
thoughtLog(
|
|
1913
|
+
`**MAVEN**: Let's use Maven to collect packages from ${basePath}.`,
|
|
1914
|
+
);
|
|
1915
|
+
if (DEBUG_MODE) {
|
|
1916
|
+
console.log(
|
|
1917
|
+
`Executing '${basename(mavenCmd)} dependency:tree ...' in ${basePath}`,
|
|
1918
|
+
);
|
|
1919
|
+
}
|
|
1920
|
+
result = safeSpawnSync(mavenCmd, mvnTreeArgs, {
|
|
1872
1921
|
cwd: basePath,
|
|
1873
1922
|
shell: isWin,
|
|
1874
|
-
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
if (
|
|
1882
|
-
|
|
1923
|
+
});
|
|
1924
|
+
let emptyJson = !safeExistsSync(tempMvnTree);
|
|
1925
|
+
if (safeExistsSync(tempMvnTree)) {
|
|
1926
|
+
const mvnTreeString = readFileSync(tempMvnTree, {
|
|
1927
|
+
encoding: "utf-8",
|
|
1928
|
+
});
|
|
1929
|
+
const parsedList = parseMavenTreeJson(mvnTreeString, f);
|
|
1930
|
+
if (!parsedList?.pkgList?.length) {
|
|
1931
|
+
emptyJson = true;
|
|
1932
|
+
// Remove the invalid json file so text output is preferred below.
|
|
1933
|
+
if (safeExistsSync(tempMvnTree)) {
|
|
1934
|
+
safeUnlinkSync(tempMvnTree);
|
|
1935
|
+
}
|
|
1883
1936
|
}
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1937
|
+
}
|
|
1938
|
+
if (result.status !== 0 || result.error || emptyJson) {
|
|
1939
|
+
mvnTreeArgs = [
|
|
1940
|
+
"dependency:tree",
|
|
1941
|
+
`-DoutputFile=${tempMvnTreeText}`,
|
|
1942
|
+
];
|
|
1943
|
+
if (addArgs.length) {
|
|
1944
|
+
mvnTreeArgs = mvnTreeArgs.concat(addArgs);
|
|
1887
1945
|
}
|
|
1888
|
-
if (
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1946
|
+
if (safeExistsSync(settingsXml)) {
|
|
1947
|
+
mvnTreeArgs.push("-s");
|
|
1948
|
+
mvnTreeArgs.push(settingsXml);
|
|
1949
|
+
}
|
|
1950
|
+
result = safeSpawnSync(mavenCmd, mvnTreeArgs, {
|
|
1951
|
+
cwd: basePath,
|
|
1952
|
+
shell: isWin,
|
|
1953
|
+
});
|
|
1954
|
+
}
|
|
1955
|
+
if (result.status !== 0 || result.error) {
|
|
1956
|
+
possible_misses = true;
|
|
1957
|
+
// Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures
|
|
1958
|
+
// These could be due to a range of reasons that are covered below.
|
|
1959
|
+
if (pomFiles.length === 1 || DEBUG_MODE || PREFER_MAVEN_DEPS_TREE) {
|
|
1960
|
+
if (result.stdout) {
|
|
1961
|
+
console.log(result.stdout);
|
|
1962
|
+
}
|
|
1963
|
+
if (result.stderr) {
|
|
1964
|
+
console.log(result.stderr);
|
|
1965
|
+
console.log("The above build errors could be due to:\n");
|
|
1966
|
+
}
|
|
1967
|
+
if (
|
|
1968
|
+
result.stdout &&
|
|
1969
|
+
(result.stdout.includes("Non-resolvable parent POM") ||
|
|
1970
|
+
result.stdout.includes("points at wrong local POM"))
|
|
1971
|
+
) {
|
|
1972
|
+
console.log(
|
|
1973
|
+
"1. Check if the pom.xml contains valid settings for parent and modules. Some projects can be built only from a specific directory.",
|
|
1974
|
+
);
|
|
1975
|
+
} else if (
|
|
1976
|
+
result.stdout &&
|
|
1977
|
+
(result.stdout.includes("Could not resolve dependencies") ||
|
|
1978
|
+
result.stdout.includes(
|
|
1979
|
+
"no dependency information available",
|
|
1980
|
+
) ||
|
|
1981
|
+
result.stdout.includes(
|
|
1982
|
+
"The following artifacts could not be resolved",
|
|
1983
|
+
))
|
|
1984
|
+
) {
|
|
1985
|
+
console.log(
|
|
1986
|
+
"1. Try building the project with 'mvn package -Dmaven.test.skip=true' using the correct version of Java and maven before invoking cdxgen.",
|
|
1987
|
+
);
|
|
1988
|
+
} else if (
|
|
1989
|
+
result.stdout?.includes(
|
|
1990
|
+
"Could not resolve target platform specification",
|
|
1991
|
+
)
|
|
1992
|
+
) {
|
|
1993
|
+
console.log(
|
|
1994
|
+
"1. Some projects can be built only from the root directory. Invoke cdxgen with --no-recurse option",
|
|
1995
|
+
);
|
|
1996
|
+
} else {
|
|
1997
|
+
console.log(
|
|
1998
|
+
"1. Java version requirement: cdxgen container image bundles Java 24 with maven 3.9 which might be incompatible. Try running cdxgen with the custom JDK11-based image `ghcr.io/cyclonedx/cdxgen-java11:v12`.",
|
|
1999
|
+
);
|
|
2000
|
+
}
|
|
1912
2001
|
console.log(
|
|
1913
|
-
"
|
|
2002
|
+
"2. Private dependencies cannot be downloaded: Check if any additional arguments must be passed to maven and set them via MVN_ARGS environment variable.",
|
|
1914
2003
|
);
|
|
1915
|
-
} else {
|
|
1916
2004
|
console.log(
|
|
1917
|
-
"
|
|
2005
|
+
"3. Check if all required environment variables including any maven profile arguments are passed correctly to this tool.",
|
|
1918
2006
|
);
|
|
1919
2007
|
}
|
|
2008
|
+
// Do not fall back to methods that can produce incomplete results when failOnError is set
|
|
2009
|
+
options.failOnError && process.exit(1);
|
|
1920
2010
|
console.log(
|
|
1921
|
-
"
|
|
2011
|
+
"\nFalling back to parsing pom.xml files. Only direct dependencies would get included!",
|
|
1922
2012
|
);
|
|
1923
|
-
|
|
1924
|
-
"
|
|
2013
|
+
thoughtLog(
|
|
2014
|
+
"**MAVEN**: There appear to be build errors, so the SBOM will be incomplete.",
|
|
1925
2015
|
);
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
console.log(
|
|
1930
|
-
"\nFalling back to parsing pom.xml files. Only direct dependencies would get included!",
|
|
1931
|
-
);
|
|
1932
|
-
thoughtLog(
|
|
1933
|
-
"**MAVEN**: There appear to be build errors, so the SBOM will be incomplete.",
|
|
1934
|
-
);
|
|
1935
|
-
const dlist = parsePom(f);
|
|
1936
|
-
if (dlist?.length) {
|
|
1937
|
-
pkgList = pkgList.concat(dlist);
|
|
1938
|
-
}
|
|
1939
|
-
} else {
|
|
1940
|
-
if (safeExistsSync(tempMvnTree)) {
|
|
1941
|
-
const mvnTreeString = readFileSync(tempMvnTree, {
|
|
1942
|
-
encoding: "utf-8",
|
|
1943
|
-
});
|
|
1944
|
-
const parsedList = parseMavenTree(mvnTreeString, f);
|
|
1945
|
-
const dlist = parsedList.pkgList;
|
|
1946
|
-
const tmpParentComponent = dlist.splice(0, 1)[0];
|
|
1947
|
-
tmpParentComponent.type = "application";
|
|
1948
|
-
if (dlist?.length) {
|
|
2016
|
+
const pomMap = parsePom(f);
|
|
2017
|
+
const dlist = pomMap?.dependencies || [];
|
|
2018
|
+
if (dlist.length) {
|
|
1949
2019
|
pkgList = pkgList.concat(dlist);
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
2020
|
+
}
|
|
2021
|
+
} else {
|
|
2022
|
+
const treeFile = safeExistsSync(tempMvnTreeText)
|
|
2023
|
+
? tempMvnTreeText
|
|
2024
|
+
: tempMvnTree;
|
|
2025
|
+
if (safeExistsSync(treeFile)) {
|
|
2026
|
+
const mvnTreeString = readFileSync(treeFile, {
|
|
2027
|
+
encoding: "utf-8",
|
|
2028
|
+
});
|
|
2029
|
+
const parsedList = treeFile.endsWith(".json")
|
|
2030
|
+
? parseMavenTreeJson(mvnTreeString, f)
|
|
2031
|
+
: parseMavenTree(mvnTreeString, f);
|
|
2032
|
+
const dlist = parsedList.pkgList || [];
|
|
2033
|
+
const tmpParentComponent = dlist.splice(0, 1)[0];
|
|
2034
|
+
if (tmpParentComponent) {
|
|
2035
|
+
tmpParentComponent.type = "application";
|
|
2036
|
+
}
|
|
2037
|
+
if (dlist.length) {
|
|
2038
|
+
pkgList = pkgList.concat(dlist);
|
|
2039
|
+
if (dlist.length > 1) {
|
|
2040
|
+
thoughtLog(`Obtained ${dlist.length} components from maven.`);
|
|
2041
|
+
} else {
|
|
2042
|
+
thoughtLog(
|
|
2043
|
+
`"Received very few components from the maven dependency tree command for ${basePath}."`,
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
// Retain the parent hierarchy
|
|
2048
|
+
if (!tmpParentComponent) {
|
|
1953
2049
|
thoughtLog(
|
|
1954
|
-
`
|
|
2050
|
+
`No parseable components were found after executing '${basename(mavenCmd)}'.`,
|
|
1955
2051
|
);
|
|
2052
|
+
} else if (!Object.keys(parentComponent).length) {
|
|
2053
|
+
parentComponent = tmpParentComponent;
|
|
2054
|
+
parentComponent.components = [];
|
|
2055
|
+
} else {
|
|
2056
|
+
parentComponent.components.push(tmpParentComponent);
|
|
1956
2057
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
} else {
|
|
1963
|
-
parentComponent.components.push(tmpParentComponent);
|
|
1964
|
-
}
|
|
1965
|
-
if (parsedList?.dependenciesList?.length) {
|
|
1966
|
-
dependencies = mergeDependencies(
|
|
1967
|
-
dependencies,
|
|
1968
|
-
parsedList.dependenciesList,
|
|
1969
|
-
tmpParentComponent,
|
|
1970
|
-
);
|
|
1971
|
-
} else {
|
|
1972
|
-
if (dlist?.length) {
|
|
1973
|
-
thoughtLog(
|
|
1974
|
-
`Hmm, I didn't find any dependencies after executing '${basename(mavenCmd)}'. However, I did get ${dlist.length} components, which is confusing.`,
|
|
2058
|
+
if (parsedList?.dependenciesList?.length) {
|
|
2059
|
+
dependencies = mergeDependencies(
|
|
2060
|
+
dependencies,
|
|
2061
|
+
parsedList.dependenciesList,
|
|
2062
|
+
tmpParentComponent,
|
|
1975
2063
|
);
|
|
2064
|
+
} else {
|
|
2065
|
+
if (dlist?.length) {
|
|
2066
|
+
thoughtLog(
|
|
2067
|
+
`Hmm, I didn't find any dependencies after executing '${basename(mavenCmd)}'. However, I did get ${dlist.length} components, which is confusing.`,
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
1976
2070
|
}
|
|
1977
2071
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2072
|
+
}
|
|
2073
|
+
} finally {
|
|
2074
|
+
if (!DEBUG_MODE && tempDir?.startsWith(tempRoot)) {
|
|
2075
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
1981
2076
|
}
|
|
1982
2077
|
}
|
|
1983
2078
|
}
|
|
@@ -3068,7 +3163,7 @@ export async function createNodejsBom(path, options) {
|
|
|
3068
3163
|
`Performing babel-based package usage analysis with source code at ${path}`,
|
|
3069
3164
|
);
|
|
3070
3165
|
}
|
|
3071
|
-
const retData = await findJSImportsExports(path, options
|
|
3166
|
+
const retData = await findJSImportsExports(path, options);
|
|
3072
3167
|
allImports = retData.allImports;
|
|
3073
3168
|
allExports = retData.allExports;
|
|
3074
3169
|
if (shouldDetectMcpInventory(includedAiInventoryTypes)) {
|
|
@@ -3128,11 +3223,23 @@ export async function createNodejsBom(path, options) {
|
|
|
3128
3223
|
`${options.multiProject ? "**/" : ""}pnpm-lock.yaml`,
|
|
3129
3224
|
options,
|
|
3130
3225
|
);
|
|
3131
|
-
|
|
3226
|
+
let pnpmWorkspaceFiles = getAllFiles(
|
|
3132
3227
|
path,
|
|
3133
3228
|
`${options.multiProject ? "**/" : ""}pnpm-workspace.yaml`,
|
|
3134
3229
|
options,
|
|
3135
3230
|
);
|
|
3231
|
+
const rootPnpmLockFile = resolve(path, "pnpm-lock.yaml");
|
|
3232
|
+
const rootPnpmWorkspaceFile = resolve(path, "pnpm-workspace.yaml");
|
|
3233
|
+
if (
|
|
3234
|
+
safeExistsSync(rootPnpmLockFile) &&
|
|
3235
|
+
safeExistsSync(rootPnpmWorkspaceFile) &&
|
|
3236
|
+
pnpmLockFiles.includes(rootPnpmLockFile)
|
|
3237
|
+
) {
|
|
3238
|
+
pnpmLockFiles = [rootPnpmLockFile];
|
|
3239
|
+
pnpmWorkspaceFiles = [rootPnpmWorkspaceFile];
|
|
3240
|
+
yarnLockFiles = [];
|
|
3241
|
+
pkgLockFiles = [];
|
|
3242
|
+
}
|
|
3136
3243
|
const minJsFiles = getAllFiles(
|
|
3137
3244
|
path,
|
|
3138
3245
|
`${options.multiProject ? "**/" : ""}*min.js`,
|
|
@@ -3418,7 +3525,6 @@ export async function createNodejsBom(path, options) {
|
|
|
3418
3525
|
const workspaceDirectDeps = {};
|
|
3419
3526
|
const depsWorkspaceRefs = {};
|
|
3420
3527
|
let workspaceCatalogs = {};
|
|
3421
|
-
let workspaceWarningShown = false;
|
|
3422
3528
|
const seenPkgJsonFiles = {};
|
|
3423
3529
|
// Is this a pnpm workspace?
|
|
3424
3530
|
for (const f of pnpmWorkspaceFiles) {
|
|
@@ -3427,16 +3533,26 @@ export async function createNodejsBom(path, options) {
|
|
|
3427
3533
|
}
|
|
3428
3534
|
const workspaceObj = parsePnpmWorkspace(f);
|
|
3429
3535
|
if (workspaceObj?.packages) {
|
|
3536
|
+
const workspaceBasePath = dirname(f);
|
|
3537
|
+
const workspacePatterns =
|
|
3538
|
+
workspaceObj.packagePatterns || workspaceObj.packages;
|
|
3430
3539
|
// We need the precise purl for all workspace packages and their direct dependencies
|
|
3431
|
-
for (const awp of
|
|
3432
|
-
const
|
|
3540
|
+
for (const awp of workspacePatterns) {
|
|
3541
|
+
const workspaceExcludes = [...(workspaceObj.excludePackages || [])];
|
|
3542
|
+
const workspaceSearchOptions = {
|
|
3543
|
+
...options,
|
|
3544
|
+
exclude: [...(options.exclude || []), ...workspaceExcludes],
|
|
3545
|
+
includeNodeModulesDir: false,
|
|
3546
|
+
};
|
|
3547
|
+
const workspacePackagePattern = awp.endsWith("package.json")
|
|
3548
|
+
? awp
|
|
3549
|
+
: `${awp.replace(/\/+$/, "")}/package.json`;
|
|
3550
|
+
const wpkgJsonFiles = getAllFiles(
|
|
3551
|
+
workspaceBasePath,
|
|
3552
|
+
workspacePackagePattern,
|
|
3553
|
+
workspaceSearchOptions,
|
|
3554
|
+
);
|
|
3433
3555
|
if (!wpkgJsonFiles?.length) {
|
|
3434
|
-
if (!workspaceWarningShown) {
|
|
3435
|
-
workspaceWarningShown = true;
|
|
3436
|
-
console.warn(
|
|
3437
|
-
`Unable to find any package.json files belonging to the workspace '${awp}' referred in ${f}. To improve SBOM precision, run cdxgen from the directory containing the complete source code.`,
|
|
3438
|
-
);
|
|
3439
|
-
}
|
|
3440
3556
|
continue;
|
|
3441
3557
|
}
|
|
3442
3558
|
for (const apj of wpkgJsonFiles) {
|
|
@@ -3444,7 +3560,12 @@ export async function createNodejsBom(path, options) {
|
|
|
3444
3560
|
continue;
|
|
3445
3561
|
}
|
|
3446
3562
|
seenPkgJsonFiles[apj] = true;
|
|
3447
|
-
|
|
3563
|
+
let pkgData;
|
|
3564
|
+
try {
|
|
3565
|
+
pkgData = JSON.parse(readFileSync(apj, "utf-8"));
|
|
3566
|
+
} catch (_err) {
|
|
3567
|
+
continue;
|
|
3568
|
+
}
|
|
3448
3569
|
if (pkgData?.name) {
|
|
3449
3570
|
const relativePkgJsonFile = relative(path, apj);
|
|
3450
3571
|
let workspaceRef = `pkg:npm/${pkgData.name}`;
|
|
@@ -3498,16 +3619,11 @@ export async function createNodejsBom(path, options) {
|
|
|
3498
3619
|
console.log(
|
|
3499
3620
|
`${Object.keys(seenPkgJsonFiles).length} package.json files were parsed to identify workspace names. Total number of package.json files: ${pkgJsonFiles.length}`,
|
|
3500
3621
|
);
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
);
|
|
3507
|
-
console.log(
|
|
3508
|
-
"TIP: Check the configuration in pnpm-workspace.yaml to ensure all the required workspaces are included correctly.",
|
|
3509
|
-
);
|
|
3510
|
-
}
|
|
3622
|
+
}
|
|
3623
|
+
if (!Object.keys(seenPkgJsonFiles).length && pnpmWorkspaceFiles.length) {
|
|
3624
|
+
console.warn(
|
|
3625
|
+
`Unable to find any package.json files belonging to the workspace(s) referred in ${pnpmWorkspaceFiles.join(", ")}. To improve SBOM precision, run cdxgen from the directory containing the complete source code.`,
|
|
3626
|
+
);
|
|
3511
3627
|
}
|
|
3512
3628
|
for (const f of pnpmLockFiles) {
|
|
3513
3629
|
if (DEBUG_MODE) {
|
|
@@ -3570,6 +3686,7 @@ export async function createNodejsBom(path, options) {
|
|
|
3570
3686
|
workspaceCatalogs,
|
|
3571
3687
|
workspaceDirectDeps,
|
|
3572
3688
|
depsWorkspaceRefs,
|
|
3689
|
+
path,
|
|
3573
3690
|
);
|
|
3574
3691
|
const dlist = parsedList.pkgList;
|
|
3575
3692
|
if (dlist?.length) {
|
|
@@ -3697,11 +3814,27 @@ export async function createNodejsBom(path, options) {
|
|
|
3697
3814
|
});
|
|
3698
3815
|
}
|
|
3699
3816
|
if (safeExistsSync(pnpmLock)) {
|
|
3700
|
-
const pnpmLockObj = await parsePnpmLock(
|
|
3817
|
+
const pnpmLockObj = await parsePnpmLock(
|
|
3818
|
+
pnpmLock,
|
|
3819
|
+
null,
|
|
3820
|
+
[],
|
|
3821
|
+
{},
|
|
3822
|
+
{},
|
|
3823
|
+
{},
|
|
3824
|
+
{},
|
|
3825
|
+
path,
|
|
3826
|
+
);
|
|
3701
3827
|
let pkgList = addWasmComponentsFromImports(
|
|
3702
3828
|
pnpmLockObj.pkgList,
|
|
3703
3829
|
allImports,
|
|
3704
3830
|
);
|
|
3831
|
+
let dependencies = [];
|
|
3832
|
+
if (pnpmLockObj?.dependenciesList?.length) {
|
|
3833
|
+
dependencies = mergeDependencies(
|
|
3834
|
+
dependencies,
|
|
3835
|
+
pnpmLockObj.dependenciesList,
|
|
3836
|
+
);
|
|
3837
|
+
}
|
|
3705
3838
|
if (allImports && Object.keys(allImports).length) {
|
|
3706
3839
|
pkgList = await addEvidenceForImports(
|
|
3707
3840
|
pkgList,
|
|
@@ -3710,9 +3843,11 @@ export async function createNodejsBom(path, options) {
|
|
|
3710
3843
|
options.deep,
|
|
3711
3844
|
);
|
|
3712
3845
|
}
|
|
3846
|
+
pkgList = propagateRequiredScopeFromDependencies(pkgList, dependencies);
|
|
3713
3847
|
return buildBomNSData(options, pkgList, "npm", {
|
|
3714
3848
|
allImports,
|
|
3715
3849
|
allExports,
|
|
3850
|
+
dependencies,
|
|
3716
3851
|
src: path,
|
|
3717
3852
|
filename: "pnpm-lock.yaml",
|
|
3718
3853
|
});
|
|
@@ -4013,6 +4148,7 @@ export async function createNodejsBom(path, options) {
|
|
|
4013
4148
|
mergeServices([], mcpInventory.services || []),
|
|
4014
4149
|
aiInventory.services || [],
|
|
4015
4150
|
);
|
|
4151
|
+
pkgList = propagateRequiredScopeFromDependencies(pkgList, dependencies);
|
|
4016
4152
|
if (exactAiInventoryType === "mcp") {
|
|
4017
4153
|
pkgList = trimComponents(filterInventorySubjectsByTypes(pkgList, ["mcp"]));
|
|
4018
4154
|
dependencies = filterInventoryDependencies(
|
|
@@ -8341,6 +8477,13 @@ async function analyzeInstalledExtensionDirs(
|
|
|
8341
8477
|
* @returns {Promise<Object>} Promise resolving to BOM object
|
|
8342
8478
|
*/
|
|
8343
8479
|
export async function createCryptoCertsBom(path, options) {
|
|
8480
|
+
if (!isCycloneDxComponentTypeEnabled("cryptographic-asset", options)) {
|
|
8481
|
+
return {
|
|
8482
|
+
bomJson: {
|
|
8483
|
+
components: [],
|
|
8484
|
+
},
|
|
8485
|
+
};
|
|
8486
|
+
}
|
|
8344
8487
|
const pkgList = [];
|
|
8345
8488
|
const certFiles = getAllFiles(
|
|
8346
8489
|
path,
|
|
@@ -8407,7 +8550,7 @@ export async function createCryptoCertsBom(path, options) {
|
|
|
8407
8550
|
}
|
|
8408
8551
|
return {
|
|
8409
8552
|
bomJson: {
|
|
8410
|
-
components: pkgList,
|
|
8553
|
+
components: filterInvalidCryptoComponents(pkgList),
|
|
8411
8554
|
},
|
|
8412
8555
|
};
|
|
8413
8556
|
}
|
|
@@ -8511,6 +8654,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8511
8654
|
} = await getOSPackages(
|
|
8512
8655
|
options.allLayersExplodedDir,
|
|
8513
8656
|
options.exportData?.inspectData?.Config,
|
|
8657
|
+
options,
|
|
8514
8658
|
);
|
|
8515
8659
|
// TODO: Need to test these with docker-compose type where multiple images could have different values.
|
|
8516
8660
|
// This is also clearly misusing options, which must become immutable at some point.
|
|
@@ -9349,7 +9493,11 @@ export async function createMultiXBom(pathList, options) {
|
|
|
9349
9493
|
}
|
|
9350
9494
|
}
|
|
9351
9495
|
// Collect any crypto keys
|
|
9352
|
-
if (
|
|
9496
|
+
if (
|
|
9497
|
+
options.specVersion >= 1.6 &&
|
|
9498
|
+
options.includeCrypto &&
|
|
9499
|
+
isCycloneDxComponentTypeEnabled("cryptographic-asset", options)
|
|
9500
|
+
) {
|
|
9353
9501
|
if (!hasAnyProjectType(["oci"], options, false)) {
|
|
9354
9502
|
thoughtLog(
|
|
9355
9503
|
"**CBOM**: Wait, the user wants me to look for cryptographic assets. Let's check thoroughly.",
|