mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[AAE-46514] - Fixing other improvements and comments
This commit is contained in:
@@ -154,7 +154,8 @@ async function fetchFromOSV(projectDependencies) {
|
||||
package: { name: dep.name, ecosystem: 'npm' },
|
||||
version: dep.version
|
||||
}))
|
||||
})
|
||||
}),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
@@ -300,7 +301,8 @@ async function fetchFromGitHubAdvisory() {
|
||||
headers: {
|
||||
'Accept': 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
},
|
||||
signal: AbortSignal.timeout(15000)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -601,7 +603,9 @@ async function main() {
|
||||
violations.push(...checkLockfileDependencies(lockfile.packages, blockedPackages));
|
||||
}
|
||||
|
||||
// Check with Meterian CLI for additional vulnerability coverage
|
||||
// Check with Meterian CLI for additional vulnerability coverage (informational by default)
|
||||
// Set ADF_METERIAN_BLOCK=1 to make Meterian findings block installation
|
||||
const meterianFindings = [];
|
||||
if (lockfile?.packages) {
|
||||
console.log('');
|
||||
const deps = Object.entries(lockfile.packages)
|
||||
@@ -614,7 +618,7 @@ async function main() {
|
||||
|
||||
const meterianResult = await checkWithMeterian(deps);
|
||||
for (const vuln of meterianResult.vulnerable || []) {
|
||||
violations.push({
|
||||
meterianFindings.push({
|
||||
package: vuln.name,
|
||||
version: vuln.version,
|
||||
reason: `${vuln.severity}: ${vuln.id}${vuln.safeVersions?.length ? ` (safe: ${vuln.safeVersions[0]})` : ''}`,
|
||||
@@ -623,6 +627,18 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Meterian findings are informational unless ADF_METERIAN_BLOCK is set
|
||||
const blockOnMeterian = process.env.ADF_METERIAN_BLOCK === '1' || process.env.ADF_METERIAN_BLOCK === 'true';
|
||||
if (blockOnMeterian) {
|
||||
violations.push(...meterianFindings);
|
||||
} else if (meterianFindings.length > 0) {
|
||||
console.log('\n⚠️ Meterian found vulnerabilities (informational, not blocking):');
|
||||
for (const v of meterianFindings) {
|
||||
console.log(` ${v.package}@${v.version} - ${v.reason}`);
|
||||
}
|
||||
console.log(' Set ADF_METERIAN_BLOCK=1 to block on these findings.\n');
|
||||
}
|
||||
|
||||
// Deduplicate
|
||||
const uniqueViolations = violations.filter((v, i, arr) =>
|
||||
arr.findIndex(x => x.package === v.package && x.version === v.version) === i
|
||||
@@ -651,9 +667,12 @@ async function main() {
|
||||
console.error(' • Exfiltrate sensitive data\n');
|
||||
|
||||
// Delete node_modules to prevent using compromised packages
|
||||
// Set ADF_SECURITY_KEEP_NODE_MODULES=1 to skip deletion (e.g., in CI for caching)
|
||||
const skipDeletion = process.env.ADF_SECURITY_KEEP_NODE_MODULES === '1' || process.env.ADF_SECURITY_KEEP_NODE_MODULES === 'true';
|
||||
const nodeModulesPath = join(ROOT_DIR, 'node_modules');
|
||||
if (existsSync(nodeModulesPath)) {
|
||||
console.error('🗑️ Removing node_modules to prevent use of compromised packages...\n');
|
||||
if (existsSync(nodeModulesPath) && !skipDeletion) {
|
||||
console.error('🗑️ Removing node_modules to prevent use of compromised packages...');
|
||||
console.error(' (Set ADF_SECURITY_KEEP_NODE_MODULES=1 to skip deletion)\n');
|
||||
try {
|
||||
rmSync(nodeModulesPath, { recursive: true, force: true });
|
||||
console.error('✅ node_modules deleted successfully.\n');
|
||||
@@ -661,6 +680,8 @@ async function main() {
|
||||
console.error(`⚠️ Could not delete node_modules: ${e.message}`);
|
||||
console.error(' Please delete it manually before proceeding.\n');
|
||||
}
|
||||
} else if (skipDeletion) {
|
||||
console.error('⚠️ Skipping node_modules deletion (ADF_SECURITY_KEEP_NODE_MODULES=1)\n');
|
||||
}
|
||||
|
||||
console.error('📋 REQUIRED ACTIONS:');
|
||||
|
||||
+107
-101
@@ -58,56 +58,83 @@ function readCache() {
|
||||
try {
|
||||
const data = JSON.parse(readFileSync(cachePath, 'utf8'));
|
||||
if (Date.now() - data.timestamp < CACHE_TTL) {
|
||||
return new Set(data.threats);
|
||||
return {
|
||||
threats: new Set(data.threats),
|
||||
ranges: data.ranges || []
|
||||
};
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
function writeCache(threats) {
|
||||
function writeCache(threats, ranges) {
|
||||
try {
|
||||
if (!existsSync(CACHE_DIR)) {
|
||||
mkdirSync(CACHE_DIR, { recursive: true });
|
||||
}
|
||||
writeFileSync(join(CACHE_DIR, 'threats.json'), JSON.stringify({
|
||||
timestamp: Date.now(),
|
||||
threats: [...threats]
|
||||
threats: [...threats],
|
||||
ranges: ranges
|
||||
}));
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
async function fetchOSV() {
|
||||
async function fetchOSV(projectDependencies) {
|
||||
// Query OSV batch API for the project's actual dependencies
|
||||
if (!projectDependencies || projectDependencies.length === 0) {
|
||||
return new Set();
|
||||
}
|
||||
|
||||
const malicious = new Set();
|
||||
|
||||
try {
|
||||
const response = await fetch('https://osv-vulnerabilities.storage.googleapis.com/npm/all.zip', {
|
||||
signal: AbortSignal.timeout(10000)
|
||||
});
|
||||
if (!response.ok) return new Set();
|
||||
// Process in batches of 1000
|
||||
const batchSize = 1000;
|
||||
for (let i = 0; i < projectDependencies.length; i += batchSize) {
|
||||
const batch = projectDependencies.slice(i, i + batchSize);
|
||||
const response = await fetch('https://api.osv.dev/v1/querybatch', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
queries: batch.map(dep => ({
|
||||
package: { name: dep.name, ecosystem: 'npm' },
|
||||
version: dep.version
|
||||
}))
|
||||
}),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
});
|
||||
|
||||
const buffer = await response.arrayBuffer();
|
||||
const text = new TextDecoder().decode(buffer);
|
||||
const malicious = new Set();
|
||||
if (!response.ok) continue;
|
||||
|
||||
// Parse JSONL format looking for MALWARE type
|
||||
for (const line of text.split('\n')) {
|
||||
if (!line.trim()) continue;
|
||||
try {
|
||||
const vuln = JSON.parse(line);
|
||||
if (vuln.database_specific?.type === 'MALWARE' && vuln.affected) {
|
||||
for (const affected of vuln.affected) {
|
||||
if (affected.package?.ecosystem === 'npm' && affected.package?.name) {
|
||||
const versions = affected.versions || [];
|
||||
for (const v of versions) {
|
||||
malicious.add(`${affected.package.name}@${v}`);
|
||||
const data = await response.json();
|
||||
for (const result of data.results || []) {
|
||||
for (const vuln of result.vulns || []) {
|
||||
const summary = [vuln.summary || '', vuln.details || ''].join(' ').toLowerCase();
|
||||
const isMalware = summary.includes('malware') ||
|
||||
summary.includes('malicious') ||
|
||||
summary.includes('compromised') ||
|
||||
summary.includes('supply chain') ||
|
||||
summary.includes('backdoor');
|
||||
|
||||
if (isMalware && vuln.affected) {
|
||||
for (const affected of vuln.affected) {
|
||||
if (affected.package?.ecosystem === 'npm' && affected.package?.name) {
|
||||
const versions = affected.versions || [];
|
||||
for (const v of versions) {
|
||||
malicious.add(`${affected.package.name}@${v}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch { /* skip invalid lines */ }
|
||||
}
|
||||
}
|
||||
return malicious;
|
||||
} catch {
|
||||
return new Set();
|
||||
// Ignore errors, return what we have
|
||||
}
|
||||
|
||||
return malicious;
|
||||
}
|
||||
|
||||
async function fetchGitHubAdvisory() {
|
||||
@@ -284,94 +311,73 @@ async function main() {
|
||||
console.log(` Checking ${packages.length} packages (${fromPackageJson} from package.json, ${fromLockfile} from lockfile)\n`);
|
||||
|
||||
// Try to use cache first
|
||||
let threats = readCache();
|
||||
let fromCache = true;
|
||||
const cache = readCache();
|
||||
let threats;
|
||||
let ghRanges;
|
||||
|
||||
if (!threats) {
|
||||
fromCache = false;
|
||||
if (!cache) {
|
||||
console.log(' Fetching latest security databases...\n');
|
||||
|
||||
const [osvThreats, ghThreats] = await Promise.all([
|
||||
fetchOSV().then(r => { console.log(` 📡 OSV: ${r.size} malware entries`); return r; }),
|
||||
fetchOSV(packages).then(r => { console.log(` 📡 OSV: ${r.size} malware entries`); return r; }),
|
||||
fetchGitHubAdvisory().then(r => { console.log(` 📡 GitHub Advisory: ${r.size} malware entries`); return r; })
|
||||
]);
|
||||
|
||||
threats = new Set([...KNOWN_MALICIOUS, ...osvThreats]);
|
||||
ghRanges = [...ghThreats];
|
||||
|
||||
// Store GitHub advisories separately (they have version ranges)
|
||||
const ghRanges = [...ghThreats];
|
||||
|
||||
// Check packages against exact matches and ranges
|
||||
const found = [];
|
||||
|
||||
for (const pkg of packages) {
|
||||
const exact = `${pkg.name}@${pkg.version}`;
|
||||
|
||||
// Check exact match
|
||||
if (threats.has(exact)) {
|
||||
found.push({ ...pkg, source: 'exact match' });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check GitHub Advisory ranges
|
||||
for (const entry of ghRanges) {
|
||||
const [name, range] = entry.split(':');
|
||||
if (pkg.name === name && parseVersionRange(range, pkg.version)) {
|
||||
found.push({ ...pkg, source: 'GitHub Advisory' });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found.length > 0) {
|
||||
console.log('\n' + '!'.repeat(70));
|
||||
console.log('🚨 MALICIOUS PACKAGES DETECTED - BLOCKING INSTALLATION');
|
||||
console.log('!'.repeat(70) + '\n');
|
||||
|
||||
for (const pkg of found) {
|
||||
console.log(` ❌ ${pkg.name}@${pkg.version} (${pkg.source})`);
|
||||
}
|
||||
|
||||
console.log('\nThese packages are known to contain malware or malicious code.');
|
||||
console.log('Installation has been blocked to protect your system.\n');
|
||||
console.log('Actions:');
|
||||
console.log(' 1. Remove these packages from package.json');
|
||||
console.log(' 2. Find safe alternatives');
|
||||
console.log(' 3. Run npm install again\n');
|
||||
console.log('='.repeat(70) + '\n');
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Cache the results
|
||||
writeCache(threats);
|
||||
console.log(`\n✅ Security check passed (${threats.size + ghRanges.length} known threats checked)`);
|
||||
// Cache the results including ranges
|
||||
writeCache(threats, ghRanges);
|
||||
} else {
|
||||
// Quick check against cached threats
|
||||
const found = [];
|
||||
for (const pkg of packages) {
|
||||
const exact = `${pkg.name}@${pkg.version}`;
|
||||
if (threats.has(exact)) {
|
||||
found.push(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
if (found.length > 0) {
|
||||
console.log('\n' + '!'.repeat(70));
|
||||
console.log('🚨 MALICIOUS PACKAGES DETECTED - BLOCKING INSTALLATION');
|
||||
console.log('!'.repeat(70) + '\n');
|
||||
|
||||
for (const pkg of found) {
|
||||
console.log(` ❌ ${pkg.name}@${pkg.version}`);
|
||||
}
|
||||
|
||||
console.log('\n='.repeat(70) + '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`✅ Security check passed (cached, ${threats.size} known threats)`);
|
||||
threats = cache.threats;
|
||||
ghRanges = cache.ranges;
|
||||
console.log(` Using cached security database (${threats.size} exact + ${ghRanges.length} ranges)\n`);
|
||||
}
|
||||
|
||||
// Check packages against exact matches and ranges
|
||||
const found = [];
|
||||
|
||||
for (const pkg of packages) {
|
||||
const exact = `${pkg.name}@${pkg.version}`;
|
||||
|
||||
// Check exact match
|
||||
if (threats.has(exact)) {
|
||||
found.push({ ...pkg, source: 'exact match' });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check GitHub Advisory ranges
|
||||
for (const entry of ghRanges) {
|
||||
const [name, range] = entry.split(':');
|
||||
if (pkg.name === name && parseVersionRange(range, pkg.version)) {
|
||||
found.push({ ...pkg, source: 'GitHub Advisory' });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found.length > 0) {
|
||||
console.log('\n' + '!'.repeat(70));
|
||||
console.log('🚨 MALICIOUS PACKAGES DETECTED - BLOCKING INSTALLATION');
|
||||
console.log('!'.repeat(70) + '\n');
|
||||
|
||||
for (const pkg of found) {
|
||||
console.log(` ❌ ${pkg.name}@${pkg.version} (${pkg.source})`);
|
||||
}
|
||||
|
||||
console.log('\nThese packages are known to contain malware or malicious code.');
|
||||
console.log('Installation has been blocked to protect your system.\n');
|
||||
console.log('Actions:');
|
||||
console.log(' 1. Remove these packages from package.json');
|
||||
console.log(' 2. Find safe alternatives');
|
||||
console.log(' 3. Run npm install again\n');
|
||||
console.log('='.repeat(70) + '\n');
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`\n✅ Security check passed (${threats.size} exact + ${ghRanges.length} ranges checked)`)
|
||||
|
||||
console.log('='.repeat(70) + '\n');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user