Cors Wildcard in Express with Cockroachdb
Cors Wildcard in Express with Cockroachdb — how this specific combination creates or exposes the vulnerability
Using a wildcard Access-Control-Allow-Origin (e.g., *) in an Express app that connects to CockroachDB can unintentionally expose database-backed endpoints to any origin. When credentials or cookies are required, browsers block requests to a wildcard origin, which often leads developers to set Access-Control-Allow-Credentials: true alongside Access-Control-Allow-Origin: *. This combination is disallowed by the CORS specification and causes browsers to reject requests, but it also encourages insecure patterns where developers assume the server-side origin check is sufficient. In a CockroachDB-backed Express service, this can result in allowing untrusted web origins to invoke authenticated or semi-authenticated API routes that query or mutate data in the cluster.
If the Express app uses per-route CORS configuration or dynamically sets Access-Control-Allow-Origin based on a request header (e.g., Origin) without strict validation, an attacker can supply any origin and potentially leverage the browser to make authenticated requests on behalf of a victim. CockroachDB itself enforces strong SQL authentication and network controls, but if the Express layer does not validate origins and relies on CORS to enforce access boundaries, malicious origins may trigger unauthorized SQL queries through authenticated API endpoints. This is especially risky when the Express routes expose query parameters or body inputs that directly influence SQL statements without strict allowlists, increasing the risk of unauthorized data access or injection through the API surface.
For example, an endpoint like /api/users/:accountId that constructs SQL with string concatenation or poorly parameterized queries can be invoked from any origin if CORS is misconfigured. Even if CockroachDB uses strong certificates and IAM authentication for server-side connections, the API remains open to abuse at the Express layer. The CORS misconfiguration does not break CockroachDB’s security, but it removes a critical client-side enforcement boundary, enabling attacker-controlled web pages to issue requests that the browser will process, potentially exposing sensitive data returned by the database through the Express API.
Cockroachdb-Specific Remediation in Express — concrete code fixes
Remediation focuses on strict CORS policy and safe database interaction in Express. Replace wildcard origins with explicit origins, avoid allowing credentials with wildcards, and validate origins against an allowlist. Use parameterized SQL queries to prevent injection regardless of CORS state, and ensure that per-request CORS logic does not dynamically reflect untrusted Origin headers.
Secure CORS configuration for Express
const cors = require('cors');
const allowedOrigins = ['https://app.yourdomain.com', 'https://admin.yourdomain.com'];
const corsOptions = {
origin: function (origin, callback) {
if (!origin) return callback(null, true); // handle non-browser requests carefully
if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true // only use with explicit origins, never with wildcard
};
app.use(cors(corsOptions));
Parameterized CockroachDB queries in Express
Use the CockroachDB Node.js driver with placeholders to avoid SQL injection. Never concatenate user input into SQL strings.
const postgres = require('postgres');
// Recommended: use connection pooling in production
const client = postgres({ connectionString: process.env.DATABASE_URL });
app.get('/api/users/:accountId', async (req, res) => {
const accountId = req.params.accountId;
try {
const result = await client.query('SELECT id, email, name FROM users WHERE id = $1', [accountId]);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'User not found' });
}
res.json(result.rows[0]);
} catch (err) {
console.error('Database query failed', err);
res.status(500).json({ error: 'Internal server error' });
}
});
Combined secure route with origin validation and safe DB access
app.get('/api/accounts/:accountId', cors(corsOptions), async (req, res) => {
const accountId = req.params.accountId;
// Additional business-level authorization should happen here
try {
const queryResult = await client.query(
'SELECT id, owner_id, balance FROM accounts WHERE id = $1',
[accountId]
);
if (queryResult.rows.length === 0) {
return res.status(404).json({ error: 'Account not found' });
}
res.json(queryResult.rows[0]);
} catch (err) {
console.error('Failed to fetch account', err);
res.status(500).json({ error: 'Internal server error' });
}
});
These steps ensure that CORS does not become an implicit access control mechanism and that CockroachDB interactions remain safe regardless of browser-origin policies. Combine these Express-side controls with CockroachDB’s native network policies, IAM roles, and prepared statements for defense in depth.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |