Open Redirect in Cockroachdb
How Open Redirect Manifests in Cockroachdb
CockroachDB itself does not expose an open‑redirect vulnerability in its core protocol, but applications that store redirect URLs in CockroachDB tables and then use those values directly in HTTP redirect headers can introduce the classic open‑redirect flaw. A typical pattern looks like this:
// Go example using the pgx driver (CockroachDB speaks PostgreSQL wire protocol)
func handleLogin(w http.ResponseWriter, r *http.Request) {
sessionID := r.FormValue("session")
var redirectURL string
err := db.QueryRow(context.Background(), "SELECT redirect_url FROM sessions WHERE id = $1", sessionID).Scan(&redirectURL)
if err != nil {
http.Error(w, "session not found", http.StatusNotFound)
return
}
// Vulnerable: redirectURL is used without validation
http.Redirect(w, r, redirectURL, http.StatusFound)
}
If an attacker can write a malicious value into the redirect_url column (for example via SQL injection, a poorly protected admin UI, or a feature that lets users set a "return URL"), the application will blindly redirect victims to any external domain the attacker chooses. This can be used for phishing, session theft, or bypassing SSO checks.
Another vector is CockroachDB’s built‑in admin UI. The login page accepts a redirect query parameter that tells the UI where to send the user after a successful login. If the UI does not validate that the URL belongs to the same origin, an attacker can craft a link like https://cockroach-example.com/login?redirect=https://evil.com/phish and trick a user into logging in and then being sent to the attacker’s site.
Both scenarios share the same root cause: data taken from CockroachDB (or supplied by the user and persisted there) is used to construct a redirect response without proper validation.
Cockroachdb-Specific Detection
Detecting this issue requires looking for places where values fetched from CockroachDB are fed into HTTP redirect functions (http.Redirect in Go, redirect in Flask/Django, res.redirect in Express, etc.) without intermediate validation. Static analysis can flag patterns like:
- SQL query → variable →
http.Redirect - ORM model field → variable → redirect helper
- Template variable that originates from a database column used in a
window.locationassignment
Dynamic testing (black‑box scanning) can confirm the flaw by sending crafted requests that cause the endpoint to issue a redirect to an external domain and observing the response.
middleBrick performs exactly this kind of unauthenticated, black‑box test. When you point it at an API endpoint, it runs a set of active probes that include open‑redirect checks: it supplies a URL with an external host in parameters that are likely to be used for redirects and watches the HTTP response for a Location header pointing to that host. If a redirect is observed, middleBrick reports the finding with severity and remediation guidance.
You can initiate a scan from the CLI:
middlebrick scan https://api.myapp.com/login
Or integrate it into CI/CD with the GitHub Action, which will fail the build if the open‑redirect finding (or any other finding) raises the overall risk score above your threshold:
name: API Security
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick
uses: middlebrick/action@v1
with:
url: https://staging.myapp.com
max-score: 80 # fail if score > 80 (i.e., grade worse than B)
The dashboard then lets you track the open‑redirect finding over time, view the exact payload that triggered the redirect, and see the prioritized remediation steps.
Cockroachdb-Specific Remediation
The fix is to validate or sanitize any URL taken from CockroachDB before using it in a redirect. CockroachDB’s native features can help enforce good data at the storage layer, while application‑level validation guarantees safety at runtime.
1. Enforce a format constraint on the column
Add a CHECK constraint that only allows URLs from trusted domains. This prevents malicious data from being written in the first place.
ALTER TABLE sessions
ADD CONSTRAINT chk_redirect_url
CHECK (redirect_url ~ '^https?://trusted\.example\.com/.*$');
If the application needs to support multiple subdomains, adjust the regular expression accordingly (e.g., ^https?://([a-z0-9-]+\.)?trusted\.example\.com/.*$).
2. Validate at runtime with Go’s net/url
Even with a constraint, defensive programming dictates validating the value right before the redirect.
func safeRedirect(w http.ResponseWriter, r *http.Request, rawURL string) {
u, err := url.Parse(rawURL)
if err != nil || !u.IsAbs() {
http.Error(w, "invalid URL", http.StatusBadRequest)
return
}
// Allowlist of trusted hosts
allowed := map[string]bool{
"trusted.example.com": true,
"api.trusted.example.com": true,
}
if !allowed[u.Host] {
http.Error(w, "redirect to untrusted host blocked", http.StatusBadRequest)
return
}
http.Redirect(w, r, rawURL, http.StatusFound)
}
// Usage
func handleLogin(w http.ResponseWriter, r *http.Request) {
var redirectURL string
err := db.QueryRow(context.Background(), "SELECT redirect_url FROM sessions WHERE id = $1", sessionID).Scan(&redirectURL)
if err != nil {
http.Error(w, "session not found", http.StatusNotFound)
return
}
safeRedirect(w, r, redirectURL)
}
3. Use CockroachDB’s EXCLUDE constraint for more complex rules (optional)
If you need to enforce that the redirect URL must belong to the same scheme and host as the current service, you can use an EXCLUDE constraint with the = operator on a normalized host extracted via a SQL function. This is more advanced but demonstrates how CockroachDB can enforce redirect safety directly in the database.
By combining a storage‑level check, runtime validation, and regular scanning with middleBrick, you eliminate the open‑redirect vector while still allowing legitimate redirect functionality.