Xss Cross Site Scripting in Axum with Cockroachdb
Xss Cross Site Scripting in Axum with Cockroachdb — how this specific combination creates or exposes the vulnerability
Cross-site scripting (XSS) in an Axum application using CockroachDB typically occurs when user-controlled data is retrieved from the database and rendered into an HTML response without proper escaping. Even though CockroachDB is a PostgreSQL-compatible database and does not introduce XSS by itself, the way application code handles and serializes query results can introduce reflected or stored XSS. Axum is a Rust web framework that relies on developers to manage response content types and escaping when constructing HTTP responses. If a handler deserializes rows containing user input (for example, a comment or profile field) and injects that data into an HTML template or JSON response without sanitization, an attacker can supply payloads that execute in victim browsers.
Consider an endpoint that fetches a user profile from CockroachDB and returns it as JSON for a frontend to render. If the frontend directly interpolates fields like display_name into the DOM without escaping, a stored XSS payload in the database can be executed. A sample malicious input might be <script>stealCookies()</script>. When the Axum handler queries CockroachDB and returns the row as JSON, the payload is preserved in the database and later delivered to clients, leading to execution in their browsers. In other scenarios, an Axum handler might render HTML using a string concatenation pattern that embeds database fields directly into the response body, bypassing any template engine auto-escaping.
The risk is often discovered during black-box scans that include input validation and data exposure checks. Because CockroachDB supports full PostgreSQL wire protocol and typical ORMs (like SeaORM or SQLx) return rows as structured data, developers might assume safety while neglecting output encoding. XSS is not a database vulnerability per se, but CockroachDB can store malicious payloads supplied through Axum handlers that fail to validate or escape input. When combined with missing Content-Security-Policy headers or unsafe JavaScript frameworks on the client, the impact is amplified.
Cockroachdb-Specific Remediation in Axum — concrete code fixes
Remediation centers on handling data safely between CockroachDB and HTTP responses. In Axum, prefer strong typing and serialization that escapes HTML-sensitive characters for JSON outputs, and use template engines with auto-escaping when generating HTML. Below are concrete patterns and code examples.
Example 1: Safe JSON response with SQLx
Use SQLx to query CockroachDB and return a serialized struct. Ensure that strings are not re-interpreted as HTML in the frontend. Axum will serialize the struct to JSON, and proper escaping is handled by the JSON serializer.
// Cargo.toml dependencies:
// sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres"] }
// axum = "0.7"
// serde = { version = "1.0", features = ["derive"] }
use axum::response::Json;
use serde::Serialize;
use sqlx::postgres::PgPoolOptions;
#[derive(Serialize, sqlx::FromRow)]
struct UserProfile {
id: i32,
display_name: String,
email: String,
}
async fn get_profile(
Path(user_id): Path,
pool: State<PgPool>
) -> Result<Json<UserProfile>, (StatusCode, String)> {
let row = sqlx::query_as::<_, UserProfile>(
"SELECT id, display_name, email FROM profiles WHERE id = $1"
)
.bind(user_id)
.fetch_one(pool.inner())
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
Ok(Json(row))
}
Example 2: HTML rendering with askama (auto-escaping template)
If you return HTML, use a template engine that auto-escapes variables. Askama integrates well with Axum and ensures that data from CockroachDB is escaped.
// Cargo.toml dependencies:
// askama = "0.12"
// axum = "0.7"
// sqlx = { version = "0.7", features = ["postgres"] }
use askama::Template;
use axum::response::Html;
#[derive(Template)]
#[template(path = "profile.html")]
struct ProfileTemplate {
display_name: String,
email: String,
}
async fn html_profile(
Path(user_id): Path<i32>,
pool: State<PgPool>
) -> Result<Html<String>, (StatusCode, String)> {
let profile = sqlx::query_as::<_, (String, String)>(
"SELECT display_name, email FROM profiles WHERE id = $1"
)
.bind(user_id)
.fetch_one(pool.inner())
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
let template = ProfileTemplate {
display_name: profile.0,
email: profile.1,
};
Ok(Html(template.render().unwrap()))
}
Example 3: Input validation and parameterized queries
Always use parameterized queries to avoid SQL injection, and validate length/format of user-supplied data before storing it in CockroachDB. This prevents stored XSS payloads from entering the database via Axum handlers.
async fn create_profile(
Json(payload): Json<CreateProfile>,
pool: State<PgPool>
) -> Result<StatusCode, (StatusCode, String)> {
// Basic validation to reduce stored malicious content
if payload.display_name.len() > 200 {
return Err((StatusCode::BAD_REQUEST, "display_name too long".into()));
}
sqlx::query(
"INSERT INTO profiles (display_name, email) VALUES ($1, $2)"
)
.bind(&payload.display_name)
.bind(&payload.email)
.execute(pool.inner())
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
Ok(StatusCode::CREATED)
}
Security headers and testing
Complement backend fixes with HTTP headers. While Axum does not set security headers automatically, you can add middleware to include Content-Security-Policy and X-Content-Type-Options. To verify your fixes, use scans that include input validation and data exposure checks to confirm that stored payloads are not executable in the browser context.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |