Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7757,15 +7757,16 @@
}
},
"node_modules/compression": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.2.tgz",
"integrity": "sha512-o8vI5RE5A6EVVOd9o41jKp41aJom+QTEO/Bx8MYNjexMo/Bv2WOjUfZr+aL0WnYSgymUy6zeguqLTsIhV0gMvQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"compressible": "~2.0.18",
"debug": "2.6.9",
"destroy": "1.2.0",
"negotiator": "~0.6.4",
"on-headers": "~1.1.0",
"safe-buffer": "5.2.1",
Expand Down Expand Up @@ -8892,6 +8893,17 @@
"node": ">= 0.8"
}
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
Expand Down Expand Up @@ -14856,9 +14868,9 @@
}
},
"node_modules/markdown-it": {
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz",
"integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==",
"version": "14.3.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.2.tgz",
"integrity": "sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q==",
"dev": true,
"funding": [
{
Expand Down Expand Up @@ -16427,9 +16439,9 @@
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz",
"integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==",
"dev": true,
"license": "MIT",
"dependencies": {
Expand Down Expand Up @@ -17877,9 +17889,9 @@
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
"integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
Expand Down
36 changes: 24 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion scripts/check-ui-npm-audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,28 @@ function evaluateAudit({ audit, lock, pending, now = new Date(), npmExitCode })
visiting.add(name);
const v = vulnerabilities[name];
need(v.severity === 'high' && v.nodes.every(n => pinned.includes(n)), 'UNREVIEWED_HIGH_NODE');
let reviewedHighCause = false;
for (const via of v.via) {
if (typeof via === 'string') {
need(v.nodes.every(from => {
const spec = { ...packages[from].dependencies, ...packages[from].optionalDependencies }[via];
return typeof spec === 'string' && vulnerabilities[via].nodes.includes(resolveDependency(packages, from, via));
}), 'METAVULNERABILITY_LOCK_EDGE_MISMATCH');
knownClosure(via);
// npm meta packages can have separate lower-severity branches.
// Their shape, severity and actual lock edge are still checked,
// but they are neither a High exception nor evidence for one.
if (vulnerabilities[via].severity === 'high') {
knownClosure(via);
reviewedHighCause = true;
}
} else {
if (LEVELS.indexOf(via.severity) < LEVELS.indexOf('high')) continue;
need(name === 'braces' && via.name === 'braces' && via.dependency === 'braces' && via.severity === 'high' &&
via.url === ADVISORY && via.range === '<=3.0.3', 'UNREVIEWED_DIRECT_ADVISORY');
reviewedHighCause = true;
}
}
need(reviewedHighCause, 'HIGH_WITHOUT_REVIEWED_CAUSE');
visiting.delete(name);
verified.add(name);
}
Expand Down
46 changes: 46 additions & 0 deletions scripts/test-ui-npm-audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,52 @@ test('exact actual seven-node npm12 closure passes and keeps raw High plus separ
assert.equal(result.knownPending.metavulnerabilityCount, 6);
assert.equal(result.knownPending.upstreamPatchedVersion, null);
});
function mixedSeverityInput() {
const value = input();
value.audit.vulnerabilities['underscore.string'] = {
name: 'underscore.string', severity: 'moderate', isDirect: false,
via: [{ source: 99, name: 'underscore.string', dependency: 'underscore.string', title: 'Separate Moderate fixture',
url: 'https://github.com/advisories/GHSA-aaaa-bbbb-cccc', severity: 'moderate', cwe: ['CWE-400'],
cvss: { score: 5, vectorString: null }, range: '*' }],
effects: ['broccoli'], range: '*', nodes: ['node_modules/underscore.string'], fixAvailable: false
};
value.audit.vulnerabilities.broccoli.via.push('underscore.string');
value.audit.metadata.vulnerabilities.moderate++;
value.audit.metadata.vulnerabilities.total++;
return value;
}
test('reviewed High meta retains independent Moderate branches without expanding the High exception', () => {
const result = evaluateAudit(mixedSeverityInput());
assert.equal(result.ok, true);
assert.equal(result.outcome, 'PASS_BUILD_VENDOR_PENDING');
assert.equal(result.totals.high, 7);
assert.equal(result.totals.moderate, 1);
assert.equal(result.knownPending.metavulnerabilityCount, 6);
});
test('mixed-severity branches still require actual lock edges and reject a newly promoted High', () => {
const edge = mixedSeverityInput();
edge.audit.vulnerabilities.sane.via.push('underscore.string');
fail(edge, 'METAVULNERABILITY_LOCK_EDGE_MISMATCH');
const promoted = mixedSeverityInput();
promoted.audit.vulnerabilities['underscore.string'].severity = 'high';
promoted.audit.metadata.vulnerabilities.moderate--;
promoted.audit.metadata.vulnerabilities.high++;
fail(promoted, 'UNREVIEWED_HIGH_NODE');
});
test('lower-severity paths alone cannot manufacture a reviewed High cause', () => {
const value = mixedSeverityInput();
value.audit.vulnerabilities.broccoli.via = ['underscore.string'];
fail(value, 'HIGH_WITHOUT_REVIEWED_CAUSE');
});
test('a direct Moderate on a reviewed node stays raw Moderate, while a new direct High is refused', () => {
const value = input();
const moderate = { ...value.audit.vulnerabilities.braces.via[0], source: 99,
url: 'https://github.com/advisories/GHSA-aaaa-bbbb-cccc', severity: 'moderate' };
value.audit.vulnerabilities.braces.via.push(moderate);
assert.equal(evaluateAudit(value).ok, true);
moderate.severity = 'high';
fail(value, 'UNREVIEWED_DIRECT_ADVISORY');
});
test('unknown High or extra direct advisory cannot borrow the known package name', () => {
const value = input();
value.audit.vulnerabilities.braces.via[0].url = 'https://github.com/advisories/GHSA-aaaa-bbbb-cccc';
Expand Down
Loading