Nosql Injection in Cockroachdb
How NoSQL Injection Manifests in CockroachDB
While CockroachDB is PostgreSQL-compatible and primarily uses SQL, it is frequently deployed in architectures that leverage its JSONB data type for flexible, document-like storage. This hybrid relational/NoSQL pattern creates a unique attack surface for NoSQL injection, distinct from traditional SQL injection. The vulnerability arises when application code dynamically constructs queries—either SQL or JSON path expressions—by concatenating untrusted user input without proper parameterization.
CockroachDB-specific manifestations include:
- Dynamic SQL with JSONB operators: Applications often build queries that filter on JSONB fields using operators like
->,->>, or@>. If user input is interpolated directly into these expressions, an attacker can manipulate the query logic. For example, a query likeSELECT * FROM users WHERE data->>'email' = '${userInput}'becomes exploitable ifuserInputcontains a JSON payload that alters the predicate. - Unsafe JSON path queries: CockroachDB supports SQL/JSON path syntax (
jsonb_path_exists,jsonb_path_query). If an application allows user-controlled path expressions (e.g., in a search API), an attacker can use path predicates like?(@.role == 'admin')or wildcards to extract unauthorized data. - Exploiting flexible schemas: Because JSONB allows varying keys per row, attackers may inject new keys or modify existing ones to bypass application logic. For instance, adding a
"isAdmin": truefield to a user-provided JSON object could elevate privileges if the application trusts this field without server-side validation.
A concrete vulnerable pattern in a Go API using the pgx driver might look like this:
func getUserByFilter(w http.ResponseWriter, r *http.Request) {
filter := r.URL.Query().Get("filter") // e.g., {"email": "user@example.com"}
query := fmt.Sprintf("SELECT * FROM users WHERE data @> '%s'::jsonb", filter)
// Execute query...
}Here, an attacker could supply a filter like {"$or": [{"email": ""}, {"role": "admin"}]} to retrieve all admin users, exploiting CockroachDB's JSONB containment operator (@>) with a NoSQL-style query.
CockroachDB-Specific Detection
Detecting NoSQL injection in CockroachDB-backed APIs requires testing for both SQL-style concatenation and JSONB-specific payloads. middleBrick's Input Validation check systematically probes API endpoints with payloads designed to trigger logical errors, data leaks, or authentication bypasses in CockroachDB's query engine.
The scanner operates as a black-box tool—no database credentials or internal access needed—by submitting malicious inputs to API parameters and analyzing HTTP responses. It looks for:
- Error messages that reveal CockroachDB syntax (e.g.,
ERROR: invalid input syntax for type jsonb). - Unexpected data volumes indicating a
WHEREclause was neutralized (e.g., receiving all rows when a filter should limit results). - Status code anomalies like 500 errors from malformed JSONB paths.
- Response content containing sensitive fields (e.g., admin email, API keys) that should be inaccessible.
For example, middleBrick might send a payload like {"$ne": null} in a JSON request body parameter that maps to a JSONB column filter. If the response includes records where that field is null, it suggests the $ne operator was evaluated, confirming injection.
The scanner cross-references any provided OpenAPI/Swagger specification to identify parameters likely used in database queries (e.g., named filter, query, where). Even without a spec, it heuristically tests common parameter names. This approach is particularly effective against CockroachDB because its error messages often include the exact query fragment that failed, giving attackers (and scanners) precise feedback.
Using middleBrick's CLI, you can scan an endpoint manually:
middlebrick scan https://api.example.com/v1/users?filter=The resulting report will flag any parameter where NoSQL injection payloads altered the expected response, assigning a severity based on data exposure and exploitability. In the Pro tier, continuous monitoring can track such findings over time and alert via Slack if a new injection vector appears.
CockroachDB-Specific Remediation
Remediation centers on eliminating dynamic query construction and rigorously validating any input that influences database queries. For CockroachDB, this means treating both SQL fragments and JSONB expressions as untrusted.
1. Use parameterized queries exclusively. CockroachDB's PostgreSQL wire protocol supports prepared statements. Never interpolate user input into query strings, even for JSONB operators. Instead:
// VULNERABLE (Go with pgx)
query := fmt.Sprintf("SELECT * FROM orders WHERE metadata @> '%s'::jsonb", userJSON)
// SECURE
query := "SELECT * FROM orders WHERE metadata @> $1::jsonb"
err := conn.QueryRow(context.Background(), query, userJSON)This ensures the driver sends the JSON value as a binary parameter, preventing it from being parsed as query syntax.
2. Validate and sanitize JSONB input at the application layer. Before passing user-supplied JSON to a query, parse it into a typed structure and reject unexpected keys or operators. For example, in a Node.js service using pg:
const userFilter = req.body.filter;
// Validate that filter is a plain object with allowed keys only
const allowedKeys = ['email', 'status'];
if (!isPlainObject(userFilter) || Object.keys(userFilter).some(k => !allowedKeys.includes(k))) {
return res.status(400).send('Invalid filter');
}
const query = 'SELECT * FROM users WHERE data @> $1';
const values = [userFilter];
client.query(query, values);3. Avoid user-controlled JSON path expressions. If your API allows searching within JSONB documents, map user input to predefined path constants rather than accepting raw path strings. For instance, convert a field=email parameter to a fixed path $.email in the query, never concatenating the field name directly.
4. Leverage CockroachDB's built-in security features:
- Enable row-level security (RLS) policies to enforce access controls at the database level, reducing reliance on application logic.
- Use SQL roles with minimal privileges for application connections—avoid superuser credentials.
- Consider column-level encryption for highly sensitive JSONB fields using CockroachDB's
encryptedcolumn option (available in Enterprise).
middleBrick does not fix code but provides remediation guidance in its reports, such as: "Replace string concatenation in query building with parameterized statements for JSONB filters". The GitHub Action can enforce that new code doesn't reintroduce such patterns by failing PRs when high-risk findings are detected.
FAQ
- Why is NoSQL injection a risk in CockroachDB if it's SQL-compatible?
CockroachDB's support for the JSONB data type and SQL/JSON path queries introduces NoSQL-style attack patterns. Applications often treat JSONB fields as schemaless documents and build queries by concatenating user-supplied JSON fragments, leading to injection similar to MongoDB or CouchDB—but within a SQL context. - How can middleBrick detect NoSQL injection without database credentials?
middleBrick performs black-box testing by sending crafted payloads (e.g.,{"$ne": ""},{"$regex": ".*"}) to API endpoints and analyzing HTTP responses. It looks for error messages, data leaks, or behavioral changes that indicate CockroachDB evaluated the malicious JSON logic, all without needing direct database access.