Server Side Template Injection in Actix with Cockroachdb
Server Side Template Injection in Actix with Cockroachdb — how this specific combination creates or exposes the vulnerability
Server Side Template Injection (SSTI) occurs when user-controlled input is rendered by a template engine and results in unintended code execution. In an Actix web application using a server-side templating engine combined with Cockroachdb as the data store, the risk arises when untrusted data is interpolated into templates that are later evaluated or used to construct queries. While Actix does not include a built-in server-side template engine, many Actix services integrate third-party template libraries (such as Askama or Tera) or generate dynamic SQL from user input. If a developer passes a request parameter directly into a template context and that template is processed in a mode that allows function calls or variable evaluation, an attacker may achieve SSTI.
When the compromised template is used to construct Cockroachdb queries—especially via string concatenation or unsafe query building—this can lead to more than template manipulation; it can enable unauthorized SQL execution. For example, if a template variable is used to dynamically select a column or table name in a Cockroachdb statement, and that variable is attacker-controlled, the boundary between template logic and database logic blurs, enabling injection. Because Cockroachdb is PostgreSQL-wire compatible, standard SQL injection behaviors apply when unsafe inputs are incorporated into dynamic queries.
The combination increases impact because an SSTI vector can pivot to the database layer, allowing data exfiltration, schema probing, or write operations. An attacker might supply a payload that executes arbitrary template code, which then manipulates SQL strings sent to Cockroachdb. Even if the application uses parameterized queries elsewhere, dynamic query construction via templates can bypass those protections. This is particularly relevant when developers use raw template output to build SQL strings without validation or escaping, effectively creating an injection channel.
Cockroachdb-Specific Remediation in Actix — concrete code fixes
Remediation centers on strict separation of data and logic, avoiding dynamic SQL construction from templates, and using Cockroachdb-safe patterns in Actix handlers.
- Use strongly typed query builders or an ORM that supports parameterization. For Cockroachdb, prefer libraries that generate parameterized statements rather than string-interpolated SQL.
- Never pass raw user input into template variables that are later used to construct SQL or command logic.
- Validate and whitelist any identifiers (table or column names) that must be dynamic; do not allow direct user control.
Example of a vulnerable pattern in Actix with Cockroachdb:
use actix_web::{web, HttpResponse};
use cockroach_client::Client;
// UNSAFE: dynamic SQL built from user input
async fn unsafe_handler(
query: web::Query>,
db: web::Data,
) -> HttpResponse {
let table = query.get("table").unwrap_or(&"users".to_string());
let sql = format!("SELECT * FROM {}", table); // SSTI/SQL injection risk
let rows = db.query(&sql, &[]).await.unwrap();
HttpResponse::Ok().body(format!("{:?}", rows))
}
Secure alternative using parameterized queries and whitelisting:
use actix_web::{web, HttpResponse};
use cockroach_client::Client;
async fn safe_handler(
query: web::Query>,
db: web::Data,
) -> HttpResponse {
let table_candidates = ["users", "products", "orders"];
let table = query.get("table")
.filter(|t| table_candidates.contains(&t.as_str()))
.unwrap_or(&"users");
// Use a parameterized query for values; identifiers must be whitelisted
let sql = format!("SELECT id, name FROM {}", table); // table is whitelisted
let stmt = db.prepare(&sql).await.expect("valid sql");
let rows = db.query(&stmt, &[]).await.expect("execute");
HttpResponse::Ok().body(format!("{:?}", rows))
}
When using a templating engine such as Tera within Actix, ensure templates are precompiled and user input is only passed as data, never as template logic. Validate and sanitize all inputs before they reach the template context and avoid exposing database-specific syntax in templates.