HIGH pii leakageaxumcockroachdb

Pii Leakage in Axum with Cockroachdb

Pii Leakage in Axum with Cockroachdb — how this specific combination creates or exposes the vulnerability

When building a web service with the Axum framework in Rust and storing data in CockroachDB, PII leakage commonly arises from mismatches between application-layer data handling and database storage practices. Axum encourages strongly typed request extraction and handler composition, which is effective for modeling business logic, but does not automatically enforce privacy controls at the persistence boundary. Developers may inadvertently store or return sensitive fields such as email addresses, phone numbers, government IDs, or location coordinates without encryption, masking, or access restrictions.

In a CockroachDB-backed Axum service, leakage can occur through several specific patterns. If a developer maps request DTOs directly to database columns that contain PII, and then serializes query results back to API consumers, sensitive data can flow unguarded through HTTP responses. For example, a User table with columns like email, phone, or ssn_hash might be queried by an endpoint such as GET /users/{id}; without explicit field filtering, the handler may return the full row, exposing PII to clients or logs. Similarly, CockroachDB’s secondary indexes and JSONB columns can inadvertently expose PII if they store raw personal data and are queried without restriction.

Another common vector is logging and observability. Axum middleware that logs requests or responses may capture PII present in payloads or database rows, especially when developers use generic debug logging on handler results. CockroachDB audit logs or application-level traces that include full structs or serialized rows can retain sensitive information. Additionally, serialization formats like JSON or MessagePack used in APIs may embed PII in nested objects or arrays, and Axum’s extractor patterns may not validate or redact these fields before persistence or transmission.

Compliance-aware developers must also consider scope and retention. Even when PII is stored securely in CockroachDB using encrypted columns, Axum endpoints that aggregate or export data—such as admin dashboards or export endpoints—can create unintended exposure if they do not enforce least-privilege access controls and field-level masking. Without runtime checks, an authenticated route might return more data than necessary, violating principles like data minimization and increasing the impact of a potential breach.

Cockroachdb-Specific Remediation in Axum — concrete code fixes

To prevent PII leakage in an Axum application using CockroachDB, implement explicit data handling, storage-layer controls, and response filtering. Use selective queries and DTOs that exclude sensitive fields unless explicitly required, and apply encryption or hashing at rest where applicable. Below are concrete, realistic code examples tailored for this stack.

1. Define segregated models and DTOs

Separate your database model from API contracts. Store PII in the database but never return it directly from endpoints unless necessary and consented. Use a distinct response DTO that omits sensitive fields.

// Domain model (maps to CockroachDB table)
#[derive(Debug, Queryable, Identifiable)]
pub struct User {
    pub id: i32,
    pub email: String,
    pub phone: String,
    pub ssn_hash: String,
    pub created_at: chrono::NaiveDateTime,
}

// API request DTO
#[derive(Debug, Deserialize)]
pub struct CreateUser {
    pub email: String,
    pub phone: String,
    pub ssn_hash: String,
}

// API response DTO — excludes PII
#[derive(Debug, Serialize)]
pub struct UserPublic {
    pub id: i32,
    pub created_at: chrono::NaiveDateTime,
}

2. Use selective queries and field projection

When fetching data for endpoints that do not require PII, explicitly select only the columns you need using SQLx or Diesel. This reduces accidental exposure and makes intent explicit.

// Using SQLx with CockroachDB — fetch only non-PII fields for public endpoints
async fn get_user_public(
    pool: &PgPool,
    user_id: i32,
) -> Result<UserPublic, sqlx::Error> {
    sqlx::query_as("
        SELECT id, created_at FROM users WHERE id = $1
    ")
    .bind(user_id)
    .fetch_one(pool)
    .await
}

3. Encrypt or hash sensitive fields at rest

For fields such as email or phone, prefer storing encrypted or hashed values when feasible. Use CockroachDB’s built-in cryptographic functions or application-layer encryption with strong keys managed outside the database.

// Example: storing an email as encrypted using application-layer keys
let encrypted_email = encrypt(&email, &app_key); // implement using AES-GCM or similar
sqlx::query("INSERT INTO users (email, email_encrypted) VALUES ($1, $2)")
    .bind(&email)
    .bind(encrypted_email)
    .execute(pool)
    .await?;

4. Apply middleware filters and guards

In Axum, use extractors and guards to ensure handlers only access data they are authorized to see. Combine this with runtime checks before returning any database row.

// Axum extractor example with scope check
async fn user_handler(
    user_id: Path<i32>,
    Extension(state): Extension<AppState>,
) -> Result<Json<UserPublic>, (StatusCode, String)> {
    let user = get_user_public(&state.pool, *user_id)
        .await
        .map_err(|e| (StatusCode::NOT_FOUND, e.to_string()))?;
    Ok(Json(user))
}

5. Redact logs and traces

Ensure logging frameworks do not capture full structs containing PII. Customize log formats in Axum middleware to exclude sensitive fields.

// Axum middleware to redact PII from logs
impl Layer<S> for RedactionLayer {
    type Service = RedactedService<S>;
    fn layer(&self, inner: S) -> Self::Service {
        RedactedService { inner }
    }
}

struct RedactedService<S> {
    inner: S,
}

impl<S, ReqBody, Body> Service<Request<ReqBody>> for RedactedService<S>
where
    S: Service<Request<ReqBody>, Response = Response<Body> + 'static>
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>
    where
        ReqBody: 'static,
    {
        fn call(&self, req: Request<ReqBody>) -> Self::Future {
            // redact known PII keys from request/response logs
            let redacted = redact_request(&req);
            let fut = self.inner.call(redacted);
            Box::pin(async move {
                let res = fut.await?;
                Ok(redact_response(res))
            })
        }
    }
}

6. Enforce least privilege at the database level

Configure CockroachDB roles and row-level security so that Axum services connect with minimal privileges. Avoid using a highly privileged service account for routine queries.

-- Example CockroachDB role for read-only public user access
CREATE ROLE public_reader;
GRANT SELECT ON TABLE users TO public_reader;
REVOKE ALL ON DATABASE mydb FROM public_reader;
-- Application connects as public_reader for public endpoints

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Does middleBrick detect PII leakage in API scans?
Yes. middleBrick runs a Data Exposure check that identifies endpoints and database interactions where PII may be exposed, including patterns common in Axum services backed by CockroachDB. Findings include severity, context, and remediation guidance without claiming to fix or block data flow.
Can I test a local Axum API with CockroachDB using middleBrick?
Yes. If your Axum service is reachable over a network path that middleBrick can access, you can submit its URL to the scanner. middleBrick performs black-box testing and supports OpenAPI/Swagger spec analysis; ensure your spec does not contain credentials, and note that scans typically complete in 5–15 seconds.