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>
88 lines
2.0 KiB
JavaScript
88 lines
2.0 KiB
JavaScript
/**
|
|
* VulnBank - Database Operations with intentional vulnerabilities
|
|
*
|
|
* Vulnerabilities:
|
|
* - SQL injection via template literals
|
|
* - SQL injection via string concatenation
|
|
*/
|
|
|
|
const mysql = require('mysql2/promise');
|
|
|
|
// BLOCK: Hardcoded database password
|
|
const pool = mysql.createPool({
|
|
host: 'localhost',
|
|
user: 'vulnbank',
|
|
password: 'password123',
|
|
database: 'vulnbank'
|
|
});
|
|
|
|
/**
|
|
* VULNERABILITY: SQL injection via template literal
|
|
* User input directly interpolated into SQL query
|
|
*/
|
|
async function getUserById(userId) {
|
|
const connection = await pool.getConnection();
|
|
try {
|
|
// BLOCK: SQL injection - template literal with user input
|
|
const [rows] = await connection.query(
|
|
`SELECT * FROM users WHERE id = '${userId}'`
|
|
);
|
|
return rows[0];
|
|
} finally {
|
|
connection.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* VULNERABILITY: SQL injection via string concatenation
|
|
*/
|
|
async function searchProducts(name) {
|
|
const connection = await pool.getConnection();
|
|
try {
|
|
// BLOCK: SQL injection - string concatenation with user input
|
|
const query = "SELECT * FROM products WHERE name LIKE '%" + name + "%'";
|
|
const [rows] = await connection.query(query);
|
|
return rows;
|
|
} finally {
|
|
connection.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* VULNERABILITY: SQL injection in DELETE statement
|
|
*/
|
|
async function deleteOrder(orderId) {
|
|
const connection = await pool.getConnection();
|
|
try {
|
|
// BLOCK: SQL injection - user input in DELETE query
|
|
await connection.query(`DELETE FROM orders WHERE id = ${orderId}`);
|
|
return true;
|
|
} finally {
|
|
connection.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Safe version for comparison - uses parameterized queries
|
|
*/
|
|
async function getUserByIdSafe(userId) {
|
|
const connection = await pool.getConnection();
|
|
try {
|
|
// This is the correct approach - parameterized query
|
|
const [rows] = await connection.query(
|
|
'SELECT * FROM users WHERE id = ?',
|
|
[userId]
|
|
);
|
|
return rows[0];
|
|
} finally {
|
|
connection.release();
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getUserById,
|
|
searchProducts,
|
|
deleteOrder,
|
|
getUserByIdSafe
|
|
};
|