Ssrf Server Side in Express with Cockroachdb
Ssrf Server Side in Express with Cockroachdb — how this specific combination creates or exposes the vulnerability
Server-side request forgery (SSRF) in an Express service that uses CockroachDB can occur when an attacker is able to influence a URL or host that the server later uses to build SQL queries or connection parameters. Because CockroachDB supports connection strings and URLs (host, port, database, and TLS options), an attacker-supplied value can lead the backend to open unexpected network connections or to route queries through an unintended path. For example, if an endpoint accepts a database URL or host header and passes it directly to a CockroachDB client, SSRF can allow the server to reach internal services, metadata endpoints (e.g., cloud metadata APIs), or external hosts that should be unreachable from the application.
The risk is amplified when the Express app builds connection details dynamically from user input without strict validation. An attacker might provide a hostname that resolves to internal infrastructure, or supply a URL that includes credentials, leading to unintended database interactions or lateral movement. Since CockroachDB often appears in distributed and cloud-native environments, SSRF can expose cluster-internal services or sensitive configuration endpoints that are not publicly routable. Even when the app does not directly pass a URL to CockroachDB, an SSRF vulnerability can allow an attacker to make the server perform arbitrary HTTP requests, which may then be used to trigger actions or exfiltrate data via other integrated services.
middleBrick scans such APIs by running unauthenticated checks that include SSRF among its 12 parallel security checks. It does not attempt to fix or block requests, but reports findings with severity ratings and remediation guidance. If your API is built with Express and integrates CockroachDB, validating and sanitizing any user-controlled input that affects network destinations is essential to reduce the attack surface.
Cockroachdb-Specific Remediation in Express — concrete code fixes
Remediation focuses on strict input validation, rejecting or transforming user-controlled values before they reach database drivers, and avoiding dynamic connection-string assembly. The following examples show safe patterns when using CockroachDB with the pg client in Express.
1. Use a fixed connection string and environment variables
Define the CockroachDB connection string in environment variables and avoid concatenating user input into it.
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.COCKROACH_CONNECTION_STRING,
ssl: {
rejectUnauthorized: true
}
});
app.get('/users/:id', async (req, res) => {
const id = parseInt(req.params.id, 10);
if (Number.isNaN(id)) {
return res.status(400).send('Invalid user ID');
}
const result = await pool.query('SELECT id, name FROM users WHERE id = $1', [id]);
res.json(result.rows);
});
2. Validate and allowlist hostnames if you must resolve dynamic targets
If your use case requires selecting among predefined endpoints, use an allowlist and reject anything not explicitly permitted.
const allowedHosts = new Set(['cockroachdb.example.com', 'read-replica.example.com']);
function getClientForHost(hostname) {
if (!allowedHosts.has(hostname)) {
throw new Error('Hostname not allowed');
}
return new Pool({
connectionString: `postgresql://${hostname}:26257/defaultdb?sslmode=require`,
ssl: {
rejectUnauthorized: true
}
});
}
app.post('/query', (req, res) => {
const { hostname } = req.body;
try {
const client = getClientForHost(hostname);
// use client for safe, expected workloads
} catch (err) {
res.status(400).send(err.message);
}
});
3. Reject unexpected URL schemes and protocols
When you accept any configuration that may include a URL, parse it and reject non-HTTP/S or non-SQL schemes, and enforce strict port rules.
const url = require('url');
function sanitizeDatabaseUrl(input) {
let parsed;
try {
parsed = new URL(input);
} catch {
throw new Error('Invalid URL');
}
if (!['https:', 'postgresql:'].includes(parsed.protocol)) {
throw new Error('Unsupported protocol');
}
if (!['cockroachdb.example.com', 'your-allowlisted-host'].includes(parsed.hostname)) {
throw new Error('Hostname not permitted');
}
return parsed.toString();
}
app.post('/connect', (req, res) => {
try {
const safeUrl = sanitizeDatabaseUrl(req.body.dbUrl);
const client = new Pool({ connectionString: safeUrl });
res.send('Connection validated');
} catch (err) {
res.status(400).send(err.message);
}
});
4. Use parameterized queries and avoid dynamic SQL construction
Never interpolate user input into SQL strings, even when the input appears to be an identifier. Use parameterized queries or, if dynamic table/column names are required, use an allowlist mapping.
app.get('/report', async (req, res) => {
const table = req.query.table;
const allowedTables = { sales: 'sales', events: 'events' };
if (!allowedTables[table]) {
return res.status(400).send('Invalid table');
}
// Use parameterized values for data, not table names
const result = await pool.query(`SELECT * FROM ${allowedTables[table]} WHERE region = $1`, ['EMEA']);
res.json(result.rows);
});
5. Network-level protections and observability
Run your Express service with network policies that prevent outbound connections to unexpected hosts. Combine this with request validation and logging to detect anomalies. middleBrick can be integrated into your workflow via the CLI, GitHub Action, or MCP Server to scan endpoints for SSRF and related issues without requiring credentials.
CLI example:
middlebrick scan https://api.example.com/openapi.json
GitHub Action and MCP Server options are also available to automate checks in CI/CD and IDE contexts.