Skip to content

Commit f59a207

Browse files
committed
feat: enhance CSV entry extraction and update README for clarity
1 parent 1f1ba53 commit f59a207

2 files changed

Lines changed: 35 additions & 19 deletions

File tree

check.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function parseCsvLine(line) {
3737
return values;
3838
}
3939

40-
function extractAffectedEntriesFromCsvContent(content, sourceFile, seen) {
40+
function extractAffectedEntriesFromCsvContent(content, sourceFile, seen, skippedEcosystems) {
4141
const affectedEntries = [];
4242
const lines = content.split(/\r?\n/).filter(line => line.trim() !== '');
4343

@@ -61,7 +61,14 @@ function extractAffectedEntriesFromCsvContent(content, sourceFile, seen) {
6161
const version = (row[versionIndex] || '').trim();
6262

6363
// This scanner validates node_modules, so we only keep npm packages.
64-
if (ecosystem !== 'npm' || !packageName || !version) {
64+
if (ecosystem !== 'npm') {
65+
if (packageName && version && skippedEcosystems) {
66+
skippedEcosystems[ecosystem] = (skippedEcosystems[ecosystem] || 0) + 1;
67+
}
68+
continue;
69+
}
70+
71+
if (!packageName || !version) {
6572
continue;
6673
}
6774

@@ -81,7 +88,9 @@ function httpsGet(url, token) {
8188
return new Promise((resolve, reject) => {
8289
const headers = {
8390
'User-Agent': 'supply-chain-scanner',
84-
'Accept': 'application/vnd.github+json'
91+
'Accept': 'application/vnd.github+json',
92+
'Cache-Control': 'no-cache',
93+
'Pragma': 'no-cache'
8594
};
8695

8796
if (token) {
@@ -156,20 +165,21 @@ async function loadAffectedVersionsFromGithubCsvFolder(config) {
156165
const csvFileNames = fileNames.filter(name => typeof name === 'string' && name.toLowerCase().endsWith('.csv'));
157166
const affectedEntries = [];
158167
const seen = new Set();
168+
const skippedEcosystems = {};
159169

160170
for (const fileName of csvFileNames) {
161171
const downloadUrl = `${rawBase}/${fileName}`;
162172
try {
163173
const content = await httpsGet(downloadUrl);
164174
const sourceFile = `${owner}/${repo}/${folderPath}/${fileName}@${ref}`;
165-
const parsed = extractAffectedEntriesFromCsvContent(content, sourceFile, seen);
175+
const parsed = extractAffectedEntriesFromCsvContent(content, sourceFile, seen, skippedEcosystems);
166176
affectedEntries.push(...parsed);
167177
} catch (error) {
168178
console.warn(`Warning: Failed to load CSV file "${fileName}" from GitHub: ${error.message}`);
169179
}
170180
}
171181

172-
return affectedEntries;
182+
return { affectedEntries, skippedEcosystems };
173183
}
174184

175185
function loadAffectedVersionsFromCsv(csvDirectory) {
@@ -182,6 +192,7 @@ function loadAffectedVersionsFromCsv(csvDirectory) {
182192

183193
const affectedEntries = [];
184194
const seen = new Set();
195+
const skippedEcosystems = {};
185196

186197
for (const fileName of csvFiles) {
187198
const filePath = path.join(csvDirectory, fileName);
@@ -193,11 +204,11 @@ function loadAffectedVersionsFromCsv(csvDirectory) {
193204
continue;
194205
}
195206

196-
const parsed = extractAffectedEntriesFromCsvContent(content, fileName, seen);
207+
const parsed = extractAffectedEntriesFromCsvContent(content, fileName, seen, skippedEcosystems);
197208
affectedEntries.push(...parsed);
198209
}
199210

200-
return affectedEntries;
211+
return { affectedEntries, skippedEcosystems };
201212
}
202213

203214
async function resolveAffectedEntries(cli, source) {
@@ -466,8 +477,9 @@ async function checkAffectedVersions() {
466477
? 'Loading affected package list from GitHub CSV data...'
467478
: 'Loading affected package list from local CSV data...';
468479
let affectedEntries;
480+
let skippedEcosystems = {};
469481
try {
470-
affectedEntries = await runWithSpinner(sourceLabel, () => resolveAffectedEntries(cli, source));
482+
({ affectedEntries, skippedEcosystems } = await runWithSpinner(sourceLabel, () => resolveAffectedEntries(cli, source)));
471483
} catch (error) {
472484
log(`Failed to load CSV data from GitHub: ${error.message}`, 'red');
473485
log('Check that csv/index.json exists in the configured repository and branch.', 'yellow');
@@ -486,7 +498,12 @@ async function checkAffectedVersions() {
486498
return;
487499
}
488500

489-
log(`Loaded affected package versions from CSV: ${affectedEntries.length}`, 'blue');
501+
log(`Loaded affected package versions from CSV: ${affectedEntries.length} (npm only)`, 'blue');
502+
const skippedTotal = Object.values(skippedEcosystems).reduce((a, b) => a + b, 0);
503+
if (skippedTotal > 0) {
504+
const detail = Object.entries(skippedEcosystems).map(([eco, n]) => `${eco}: ${n}`).join(', ');
505+
log(`Skipped non-npm entries: ${skippedTotal} (${detail}) — this scanner only checks node_modules`, 'yellow');
506+
}
490507
log(`Scan path: ${cli.scanPath}`, 'blue');
491508
log(`Recursive scan: ${cli.recursive ? 'enabled' : 'disabled'}`, 'blue');
492509
log('', 'reset');
@@ -601,7 +618,10 @@ async function checkAffectedVersions() {
601618
});
602619

603620
log('', 'reset');
604-
log(`Checked packages: ${checkedPackages.length}`, 'blue');
621+
log(`Checked packages: ${checkedPackages.length} (npm only)`, 'blue');
622+
if (skippedTotal > 0) {
623+
log(`Skipped (non-npm): ${skippedTotal}`, 'yellow');
624+
}
605625
log(`Found installed packages: ${checkedPackages.filter(p => p.foundLocations.length > 0).length}`, 'blue');
606626
log(`Compromised packages: ${vulnerablePackages.length}`, vulnerablePackages.length > 0 ? 'red' : 'green');
607627
log('', 'reset');

readme.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Supply Chain Scanner
1+
# Supply Chain Scanner for NPM Packages
22

33
By default, this scanner loads affected package versions directly from the GitHub csv folder and then checks your node_modules.
44

@@ -8,15 +8,11 @@ By default, this scanner loads affected package versions directly from the GitHu
88

99
`curl -L -o check.js https://raw.githubusercontent.com/OpenForgeProject/supply-chain-scanner/main/check.js`
1010

11-
2. Run it in your target project
11+
2. Options to run it in your target project
1212

13-
`node check.js`
14-
or
15-
`node check.js -r`
16-
17-
## Recursively scan multiple projects in a directory
18-
19-
`node check.js /path/to/scan -r`
13+
- `node check.js`
14+
- `node check.js -r`
15+
- `node check.js /path/to/scan -r`
2016

2117
## Use a custom GitHub CSV source
2218

0 commit comments

Comments
 (0)