cognium-dev 3.202.0 → 3.204.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/dist/cli.js +234 -19
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -45953,6 +45953,112 @@ function parseNpmDependencies(packageJson) {
|
|
|
45953
45953
|
}
|
|
45954
45954
|
return out2;
|
|
45955
45955
|
}
|
|
45956
|
+
function parsePep508(spec) {
|
|
45957
|
+
let s = spec.trim();
|
|
45958
|
+
s = s.split(";")[0].trim();
|
|
45959
|
+
if (!s)
|
|
45960
|
+
return null;
|
|
45961
|
+
const m = s.match(/^([A-Za-z0-9._-]+)\s*(?:\[[^\]]*\])?\s*(.*)$/);
|
|
45962
|
+
if (!m)
|
|
45963
|
+
return null;
|
|
45964
|
+
const rest = m[2].trim();
|
|
45965
|
+
const verMatch = rest.replace(/^\(/, "").match(/^(?:==|>=|<=|~=|!=|>|<|===)?\s*([^,\s)]+)/);
|
|
45966
|
+
const version = verMatch && verMatch[1] ? verMatch[1] : "unknown";
|
|
45967
|
+
return { name: m[1], version };
|
|
45968
|
+
}
|
|
45969
|
+
function parseNpmLockDependencies(packageLock) {
|
|
45970
|
+
if (!packageLock)
|
|
45971
|
+
return [];
|
|
45972
|
+
let parsed;
|
|
45973
|
+
try {
|
|
45974
|
+
parsed = JSON.parse(packageLock);
|
|
45975
|
+
} catch {
|
|
45976
|
+
return [];
|
|
45977
|
+
}
|
|
45978
|
+
if (!parsed || typeof parsed !== "object")
|
|
45979
|
+
return [];
|
|
45980
|
+
const root = parsed;
|
|
45981
|
+
const out2 = [];
|
|
45982
|
+
const scopeOf = (info2) => info2.dev === true ? "dev" : info2.optional === true ? "optional" : "required";
|
|
45983
|
+
const packages = root.packages;
|
|
45984
|
+
if (packages && typeof packages === "object") {
|
|
45985
|
+
for (const [path, raw] of Object.entries(packages)) {
|
|
45986
|
+
if (!path || !raw || typeof raw !== "object")
|
|
45987
|
+
continue;
|
|
45988
|
+
const info2 = raw;
|
|
45989
|
+
const marker = "node_modules/";
|
|
45990
|
+
const idx = path.lastIndexOf(marker);
|
|
45991
|
+
const name2 = idx >= 0 ? path.slice(idx + marker.length) : typeof info2.name === "string" ? info2.name : path;
|
|
45992
|
+
if (!name2)
|
|
45993
|
+
continue;
|
|
45994
|
+
const version = typeof info2.version === "string" ? info2.version : "unknown";
|
|
45995
|
+
out2.push(dep("npm", name2, version, scopeOf(info2)));
|
|
45996
|
+
}
|
|
45997
|
+
} else if (root.dependencies && typeof root.dependencies === "object") {
|
|
45998
|
+
const walk = (deps) => {
|
|
45999
|
+
for (const [name2, raw] of Object.entries(deps)) {
|
|
46000
|
+
if (!raw || typeof raw !== "object")
|
|
46001
|
+
continue;
|
|
46002
|
+
const info2 = raw;
|
|
46003
|
+
const version = typeof info2.version === "string" ? info2.version : "unknown";
|
|
46004
|
+
out2.push(dep("npm", name2, version, scopeOf(info2)));
|
|
46005
|
+
if (info2.dependencies && typeof info2.dependencies === "object") {
|
|
46006
|
+
walk(info2.dependencies);
|
|
46007
|
+
}
|
|
46008
|
+
}
|
|
46009
|
+
};
|
|
46010
|
+
walk(root.dependencies);
|
|
46011
|
+
}
|
|
46012
|
+
const seen = new Set;
|
|
46013
|
+
return out2.filter((d) => {
|
|
46014
|
+
const key = `${d.name}|${d.version}|${d.scope}`;
|
|
46015
|
+
if (seen.has(key))
|
|
46016
|
+
return false;
|
|
46017
|
+
seen.add(key);
|
|
46018
|
+
return true;
|
|
46019
|
+
});
|
|
46020
|
+
}
|
|
46021
|
+
function parseTomlPackageArray(content, ecosystem) {
|
|
46022
|
+
const out2 = [];
|
|
46023
|
+
let name2 = null;
|
|
46024
|
+
let version = null;
|
|
46025
|
+
let inPackage = false;
|
|
46026
|
+
const flush = () => {
|
|
46027
|
+
if (inPackage && name2 && version)
|
|
46028
|
+
out2.push(dep(ecosystem, name2, version, "required"));
|
|
46029
|
+
name2 = null;
|
|
46030
|
+
version = null;
|
|
46031
|
+
};
|
|
46032
|
+
for (const raw of content.split(/\r?\n/)) {
|
|
46033
|
+
const line = raw.trim();
|
|
46034
|
+
if (line === "[[package]]") {
|
|
46035
|
+
flush();
|
|
46036
|
+
inPackage = true;
|
|
46037
|
+
continue;
|
|
46038
|
+
}
|
|
46039
|
+
if (line.startsWith("[")) {
|
|
46040
|
+
flush();
|
|
46041
|
+
inPackage = false;
|
|
46042
|
+
continue;
|
|
46043
|
+
}
|
|
46044
|
+
if (!inPackage)
|
|
46045
|
+
continue;
|
|
46046
|
+
const nm = line.match(/^name\s*=\s*"([^"]+)"/);
|
|
46047
|
+
if (nm)
|
|
46048
|
+
name2 = nm[1];
|
|
46049
|
+
const vm = line.match(/^version\s*=\s*"([^"]+)"/);
|
|
46050
|
+
if (vm)
|
|
46051
|
+
version = vm[1];
|
|
46052
|
+
}
|
|
46053
|
+
flush();
|
|
46054
|
+
return out2;
|
|
46055
|
+
}
|
|
46056
|
+
function parseCargoLockDependencies(cargoLock) {
|
|
46057
|
+
return cargoLock ? parseTomlPackageArray(cargoLock, "cargo") : [];
|
|
46058
|
+
}
|
|
46059
|
+
function parsePoetryLockDependencies(poetryLock) {
|
|
46060
|
+
return poetryLock ? parseTomlPackageArray(poetryLock, "pypi") : [];
|
|
46061
|
+
}
|
|
45956
46062
|
function parsePypiDependencies(requirementsTxt) {
|
|
45957
46063
|
if (!requirementsTxt)
|
|
45958
46064
|
return [];
|
|
@@ -45964,17 +46070,101 @@ function parsePypiDependencies(requirementsTxt) {
|
|
|
45964
46070
|
if (line.startsWith("-") || /^[a-z]+:\/\//i.test(line))
|
|
45965
46071
|
continue;
|
|
45966
46072
|
line = line.split("#")[0].trim();
|
|
45967
|
-
line = line.split(";")[0].trim();
|
|
45968
46073
|
if (!line)
|
|
45969
46074
|
continue;
|
|
45970
|
-
const
|
|
45971
|
-
if (
|
|
46075
|
+
const parsed = parsePep508(line);
|
|
46076
|
+
if (parsed)
|
|
46077
|
+
out2.push(dep("pypi", parsed.name, parsed.version, "required"));
|
|
46078
|
+
}
|
|
46079
|
+
return out2;
|
|
46080
|
+
}
|
|
46081
|
+
function parsePyprojectDependencies(pyprojectToml) {
|
|
46082
|
+
if (!pyprojectToml)
|
|
46083
|
+
return [];
|
|
46084
|
+
const out2 = [];
|
|
46085
|
+
const lines = pyprojectToml.split(/\r?\n/);
|
|
46086
|
+
let table = "";
|
|
46087
|
+
let poetryScope = null;
|
|
46088
|
+
let inArray = false;
|
|
46089
|
+
let arrayScope = "required";
|
|
46090
|
+
const pushReq = (raw, scope) => {
|
|
46091
|
+
const cleaned = raw.trim().replace(/^["']|["'],?$/g, "").replace(/,$/, "").trim();
|
|
46092
|
+
if (!cleaned)
|
|
46093
|
+
return;
|
|
46094
|
+
const parsed = parsePep508(cleaned);
|
|
46095
|
+
if (parsed && parsed.name.toLowerCase() !== "python")
|
|
46096
|
+
out2.push(dep("pypi", parsed.name, parsed.version, scope));
|
|
46097
|
+
};
|
|
46098
|
+
for (const raw of lines) {
|
|
46099
|
+
const line = raw.trim();
|
|
46100
|
+
if (!line || line.startsWith("#"))
|
|
45972
46101
|
continue;
|
|
45973
|
-
|
|
45974
|
-
|
|
45975
|
-
|
|
45976
|
-
|
|
45977
|
-
|
|
46102
|
+
if (inArray) {
|
|
46103
|
+
if (line.startsWith("]")) {
|
|
46104
|
+
inArray = false;
|
|
46105
|
+
continue;
|
|
46106
|
+
}
|
|
46107
|
+
pushReq(line, arrayScope);
|
|
46108
|
+
continue;
|
|
46109
|
+
}
|
|
46110
|
+
const header = line.match(/^\[([^\]]+)\]$/);
|
|
46111
|
+
if (header) {
|
|
46112
|
+
table = header[1];
|
|
46113
|
+
if (table === "tool.poetry.dependencies")
|
|
46114
|
+
poetryScope = "required";
|
|
46115
|
+
else if (/^tool\.poetry\.(dev-dependencies|group\..+\.dependencies)$/.test(table))
|
|
46116
|
+
poetryScope = "dev";
|
|
46117
|
+
else
|
|
46118
|
+
poetryScope = null;
|
|
46119
|
+
continue;
|
|
46120
|
+
}
|
|
46121
|
+
const arrayOpen = line.match(/^(dependencies|[A-Za-z0-9._-]+)\s*=\s*\[(.*)$/);
|
|
46122
|
+
if (arrayOpen && (arrayOpen[1] === "dependencies" || table === "project.optional-dependencies")) {
|
|
46123
|
+
arrayScope = arrayOpen[1] === "dependencies" ? "required" : "optional";
|
|
46124
|
+
const inline = arrayOpen[2];
|
|
46125
|
+
if (inline.includes("]")) {
|
|
46126
|
+
for (const item of inline.slice(0, inline.indexOf("]")).split(","))
|
|
46127
|
+
pushReq(item, arrayScope);
|
|
46128
|
+
} else {
|
|
46129
|
+
inArray = true;
|
|
46130
|
+
if (inline.trim())
|
|
46131
|
+
pushReq(inline, arrayScope);
|
|
46132
|
+
}
|
|
46133
|
+
continue;
|
|
46134
|
+
}
|
|
46135
|
+
if (poetryScope) {
|
|
46136
|
+
const kv = line.match(/^([A-Za-z0-9._-]+)\s*=\s*(.+)$/);
|
|
46137
|
+
if (!kv || kv[1].toLowerCase() === "python")
|
|
46138
|
+
continue;
|
|
46139
|
+
let version = "unknown";
|
|
46140
|
+
const strv = kv[2].match(/^["']([^"']+)["']/);
|
|
46141
|
+
if (strv)
|
|
46142
|
+
version = strv[1];
|
|
46143
|
+
else {
|
|
46144
|
+
const inlinev = kv[2].match(/version\s*=\s*["']([^"']+)["']/);
|
|
46145
|
+
if (inlinev)
|
|
46146
|
+
version = inlinev[1];
|
|
46147
|
+
}
|
|
46148
|
+
out2.push(dep("pypi", kv[1], version, poetryScope));
|
|
46149
|
+
}
|
|
46150
|
+
}
|
|
46151
|
+
return out2;
|
|
46152
|
+
}
|
|
46153
|
+
function parseGradleDependencies(buildGradle) {
|
|
46154
|
+
if (!buildGradle)
|
|
46155
|
+
return [];
|
|
46156
|
+
const out2 = [];
|
|
46157
|
+
const re = /\b(implementation|api|compileOnly|compileOnlyApi|runtimeOnly|testImplementation|testCompileOnly|testRuntimeOnly|annotationProcessor|kapt|classpath)\s*[(\s]\s*['"]([\w.-]+:[\w.-]+(?::[\w.\-+]+)?)['"]/g;
|
|
46158
|
+
let m;
|
|
46159
|
+
while ((m = re.exec(buildGradle)) !== null) {
|
|
46160
|
+
const config = m[1];
|
|
46161
|
+
const coord = m[2].split(":");
|
|
46162
|
+
if (coord.length < 2)
|
|
46163
|
+
continue;
|
|
46164
|
+
const name2 = `${coord[0]}:${coord[1]}`;
|
|
46165
|
+
const version = coord[2] ?? "unknown";
|
|
46166
|
+
const scope = config.startsWith("test") ? "dev" : "required";
|
|
46167
|
+
out2.push(dep("maven", name2, version, scope));
|
|
45978
46168
|
}
|
|
45979
46169
|
return out2;
|
|
45980
46170
|
}
|
|
@@ -46753,7 +46943,7 @@ var colors = {
|
|
|
46753
46943
|
};
|
|
46754
46944
|
|
|
46755
46945
|
// src/version.ts
|
|
46756
|
-
var version = "3.
|
|
46946
|
+
var version = "3.204.0";
|
|
46757
46947
|
|
|
46758
46948
|
// src/formatters.ts
|
|
46759
46949
|
var LIBRARY_API_SURFACE_TAG2 = "library-api-surface:caller-responsibility";
|
|
@@ -47411,7 +47601,10 @@ SBOM OPTIONS:
|
|
|
47411
47601
|
--prod-only Exclude dev/test dependencies
|
|
47412
47602
|
--deterministic Omit timestamp / serialNumber / namespace for reproducible output
|
|
47413
47603
|
-o, --output <file> Write the document to a file (default: stdout)
|
|
47414
|
-
Discovers package.json / requirements.txt /
|
|
47604
|
+
Discovers package.json / requirements.txt / pyproject.toml /
|
|
47605
|
+
pom.xml / build.gradle(.kts) / Cargo.toml / go.mod.
|
|
47606
|
+
A package-lock.json supersedes its package.json
|
|
47607
|
+
(exact + transitive versions).
|
|
47415
47608
|
CVE matching is out of scope (deterministic SAST — no network).
|
|
47416
47609
|
|
|
47417
47610
|
EXAMPLES:
|
|
@@ -48451,11 +48644,24 @@ function parseCrossFileBudgetMs(raw) {
|
|
|
48451
48644
|
}
|
|
48452
48645
|
var SBOM_MANIFESTS = {
|
|
48453
48646
|
"package.json": parseNpmDependencies,
|
|
48647
|
+
"package-lock.json": parseNpmLockDependencies,
|
|
48648
|
+
"npm-shrinkwrap.json": parseNpmLockDependencies,
|
|
48454
48649
|
"requirements.txt": parsePypiDependencies,
|
|
48650
|
+
"pyproject.toml": parsePyprojectDependencies,
|
|
48651
|
+
"poetry.lock": parsePoetryLockDependencies,
|
|
48455
48652
|
"pom.xml": parseMavenDependencies,
|
|
48653
|
+
"build.gradle": parseGradleDependencies,
|
|
48654
|
+
"build.gradle.kts": parseGradleDependencies,
|
|
48456
48655
|
"Cargo.toml": parseCargoDependencies,
|
|
48656
|
+
"Cargo.lock": parseCargoLockDependencies,
|
|
48457
48657
|
"go.mod": parseGoDependencies
|
|
48458
48658
|
};
|
|
48659
|
+
var SBOM_SUPERSEDES = {
|
|
48660
|
+
"package-lock.json": "package.json",
|
|
48661
|
+
"npm-shrinkwrap.json": "package.json",
|
|
48662
|
+
"poetry.lock": "pyproject.toml",
|
|
48663
|
+
"Cargo.lock": "Cargo.toml"
|
|
48664
|
+
};
|
|
48459
48665
|
var SBOM_SKIP_DIRS = /^(node_modules|vendor|target|dist|build|out|coverage)$/;
|
|
48460
48666
|
async function collectManifestFiles(targetPath) {
|
|
48461
48667
|
const found = [];
|
|
@@ -48489,22 +48695,31 @@ async function runSbom(targetPath, options) {
|
|
|
48489
48695
|
}
|
|
48490
48696
|
const manifests = await collectManifestFiles(absPath);
|
|
48491
48697
|
if (manifests.length === 0) {
|
|
48492
|
-
console.error(colors.red("Error: no supported manifests found (package.json, requirements.txt, pom.xml, Cargo.toml, go.mod)"));
|
|
48698
|
+
console.error(colors.red("Error: no supported manifests found (package.json/-lock, requirements.txt, pyproject.toml, poetry.lock, pom.xml, build.gradle, Cargo.toml/.lock, go.mod)"));
|
|
48493
48699
|
process.exit(1);
|
|
48494
48700
|
}
|
|
48495
|
-
|
|
48496
|
-
let projectName = options.name;
|
|
48701
|
+
const supersededInDir = new Set;
|
|
48497
48702
|
for (const m of manifests) {
|
|
48498
|
-
const
|
|
48499
|
-
|
|
48500
|
-
|
|
48703
|
+
const superseded = SBOM_SUPERSEDES[basename(m)];
|
|
48704
|
+
if (superseded)
|
|
48705
|
+
supersededInDir.add(`${dirname3(m)}\x00${superseded}`);
|
|
48706
|
+
}
|
|
48707
|
+
const effective = manifests.filter((m) => !supersededInDir.has(`${dirname3(m)}\x00${basename(m)}`));
|
|
48708
|
+
let projectName = options.name;
|
|
48709
|
+
if (!projectName) {
|
|
48710
|
+
const pkg = manifests.find((m) => basename(m) === "package.json");
|
|
48711
|
+
if (pkg) {
|
|
48501
48712
|
try {
|
|
48502
|
-
const n = JSON.parse(
|
|
48713
|
+
const n = JSON.parse(readFileSync(pkg, "utf-8")).name;
|
|
48503
48714
|
if (typeof n === "string" && n)
|
|
48504
48715
|
projectName = n;
|
|
48505
48716
|
} catch {}
|
|
48506
48717
|
}
|
|
48507
48718
|
}
|
|
48719
|
+
let deps = [];
|
|
48720
|
+
for (const m of effective) {
|
|
48721
|
+
deps.push(...SBOM_MANIFESTS[basename(m)](readFileSync(m, "utf-8")));
|
|
48722
|
+
}
|
|
48508
48723
|
const seen = new Set;
|
|
48509
48724
|
deps = deps.filter((d) => {
|
|
48510
48725
|
const key = `${d.ecosystem}|${d.name}|${d.version}|${d.scope}`;
|
|
@@ -48528,10 +48743,10 @@ async function runSbom(targetPath, options) {
|
|
|
48528
48743
|
const out2 = JSON.stringify(doc, null, 2);
|
|
48529
48744
|
if (options.output) {
|
|
48530
48745
|
writeFileSync(options.output, out2);
|
|
48531
|
-
console.error(colors.green(`SBOM written to ${options.output} — ${deps.length} dependencies from ${
|
|
48746
|
+
console.error(colors.green(`SBOM written to ${options.output} — ${deps.length} dependencies from ${effective.length} manifest(s)`));
|
|
48532
48747
|
} else {
|
|
48533
48748
|
console.log(out2);
|
|
48534
|
-
console.error(colors.green(`SBOM: ${deps.length} dependencies from ${
|
|
48749
|
+
console.error(colors.green(`SBOM: ${deps.length} dependencies from ${effective.length} manifest(s)`));
|
|
48535
48750
|
}
|
|
48536
48751
|
process.exit(0);
|
|
48537
48752
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cognium-dev",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.204.0",
|
|
4
4
|
"description": "Static Application Security Testing CLI for detecting security vulnerabilities via taint tracking",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@cognium/project-profile-detect": "^1.1.0",
|
|
69
|
-
"circle-ir": "^3.
|
|
69
|
+
"circle-ir": "^3.204.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "^25.5.0",
|