Major additions: - Community Next.js app (port 18187) for browsing claims with API docs - stemedb-chaos crate: Fault injection, chaos testing, CRDT properties - Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents - Disputed claims handling: Manual review workflows and validation - Aphoria security scanner: New extractors (SQL injection, command injection, weak crypto, TLS version), policy-based ignores, UAT reports - Docker infrastructure: Dockerfile, docker-compose.yml for full stack - VulnBank demo: Intentionally vulnerable multi-language test corpus SDK & API enhancements: - Source registry handlers for tracking data provenance - Metrics endpoint - Skeptic filtering improvements Code quality: - Split 14 large files (>500 lines) into focused modules - All files now under 500-line limit per project guidelines Documentation: - Chaos testing guide, circuit breakers, observability docs - Phase 7 UAT documentation updates - Martin Kleppmann technical writer agent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
92 lines
2.1 KiB
JavaScript
92 lines
2.1 KiB
JavaScript
/**
|
|
* VulnBank - Command Execution with intentional vulnerabilities
|
|
*
|
|
* Vulnerabilities:
|
|
* - Command injection via exec()
|
|
* - Command injection via execSync()
|
|
*/
|
|
|
|
const { exec, execSync } = require('child_process');
|
|
|
|
/**
|
|
* VULNERABILITY: Command injection via exec()
|
|
* User input passed directly to shell command
|
|
*/
|
|
function listFiles(directory, callback) {
|
|
// BLOCK: exec with user input enables command injection
|
|
exec(`ls -la ${directory}`, (error, stdout, stderr) => {
|
|
if (error) {
|
|
callback(error, null);
|
|
return;
|
|
}
|
|
callback(null, stdout);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* VULNERABILITY: Command injection via execSync()
|
|
* Synchronous command execution with user input
|
|
*/
|
|
function readFileHead(filename) {
|
|
try {
|
|
// BLOCK: execSync with user input enables command injection
|
|
const output = execSync(`head -10 ${filename}`);
|
|
return output.toString();
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* VULNERABILITY: Command injection in image processing
|
|
* User-controlled filename in shell command
|
|
*/
|
|
function resizeImage(inputPath, outputPath, size) {
|
|
// BLOCK: Command injection - user controls file paths
|
|
exec(`convert ${inputPath} -resize ${size} ${outputPath}`, (error) => {
|
|
if (error) {
|
|
console.error('Image resize failed:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* VULNERABILITY: Command injection in backup script
|
|
*/
|
|
function backupDatabase(backupName) {
|
|
// BLOCK: Command injection - user controls backup filename
|
|
const command = `pg_dump vulnbank > /backups/${backupName}.sql`;
|
|
return execSync(command);
|
|
}
|
|
|
|
/**
|
|
* Safe version for comparison - uses spawn with array arguments
|
|
*/
|
|
const { spawn } = require('child_process');
|
|
|
|
function listFilesSafe(directory, callback) {
|
|
// This is the correct approach - no shell, array of arguments
|
|
const ls = spawn('ls', ['-la', directory]);
|
|
|
|
let output = '';
|
|
ls.stdout.on('data', (data) => {
|
|
output += data;
|
|
});
|
|
|
|
ls.on('close', (code) => {
|
|
if (code !== 0) {
|
|
callback(new Error(`Process exited with code ${code}`), null);
|
|
return;
|
|
}
|
|
callback(null, output);
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
listFiles,
|
|
readFileHead,
|
|
resizeImage,
|
|
backupDatabase,
|
|
listFilesSafe
|
|
};
|