HIGH information disclosureactix

Information Disclosure in Actix

How Information Disclosure Manifests in Actix

Information disclosure vulnerabilities in Actix applications typically arise from improper error handling, debug information exposure, and misconfigured logging. The Actix web framework, while performant and type-safe, can inadvertently leak sensitive data through several common patterns.

One primary vector is Actix's default error handling. When an error occurs, Actix's built-in error handlers often return detailed error messages containing stack traces, database queries, or internal server paths. Consider this vulnerable pattern:

async fn vulnerable_handler() -> Result<HttpResponse, Error> { 
    let db_result = sqlx::query_as("SELECT * FROM users WHERE id = $1") 
        .bind(1) 
        .fetch_one(&pool) 
        .await;
    
    match db_result {
        Ok(user) => Ok(HttpResponse::Ok().json(user)),
        Err(e) => Err(e.into()) // Leaks SQL query details
    }
}

The sqlx::Error contains the actual SQL query and connection details, which Actix serializes into the HTTP response. In production, this reveals database structure and potential injection points to attackers.

Another Actix-specific disclosure vector is the use of #[catch] blocks without proper sanitization. Developers often wrap entire modules with catch-all error handlers that return raw error data:

#[catch(default)]
fn default_handler(err: &actix_web::error::Error) -> actix_web::Result<HttpResponse> {
    // Exposes internal error structure
    Ok(HttpResponse::InternalServerError().body(err.to_string()))
}

Actix's error::Error implements Display by exposing internal error chains, which may include file paths, environment variables, or cryptographic material from failed operations.

Debug mode compilation creates another disclosure risk. When Actix applications are compiled with debug assertions enabled, they may include additional validation checks that expose internal state through panic messages or assertion failures. These messages often contain memory addresses, type information, or partial data structures.

Logging configuration in Actix middleware presents a third vector. The default logging middleware can expose request headers, query parameters, or response bodies in log files. If logs are accessible through the application or improperly secured, attackers can extract sensitive data like API keys, session tokens, or personal information.

Actix's JSON deserialization also creates disclosure opportunities. When using serde_json::from_str with ? operator error propagation, malformed input can cause deserialization errors that reveal schema information:

async fn create_user(json: web::Json<UserRequest>) -> Result<HttpResponse, Error> {
    // If deserialization fails, Actix returns detailed schema info
    let user: UserRequest = json.into_inner();
    
    // Error messages show exact field names and types
    // Example: "missing field `email` at line 1 column 1"
}

This pattern helps legitimate clients but also aids attackers in understanding the expected data structure for further exploitation attempts.

Actix-Specific Detection

Detecting information disclosure vulnerabilities in Actix applications requires both static analysis and runtime scanning. The Actix framework's architecture creates specific detection opportunities that differ from other Rust web frameworks.

Static analysis should focus on error handling patterns throughout the codebase. Search for actix_web::error::Error returns without sanitization, particularly in Result<T, Error> return types where errors are propagated directly. Tools like clippy can help identify suspicious patterns, but custom rules are needed for Actix-specific vulnerabilities.

// Detection pattern: unsanitized error propagation
fn check_error_propagation(file_content: &str) -> Vec<Span> {
    let syntax = syn::parse_file(file_content).unwrap();
    let mut issues = Vec::new();
    
    for item in syntax.items {
        if let syn::Item::Fn(func) = item {
            for attr in &func.attrs {
                if attr.path.is_ident("catch") {
                    // Check catch blocks for direct error returns
                    for stmt in &func.block.stmts {
                        if let syn::Stmt::Expr(expr) = stmt {
                            if let syn::Expr::Return(ret) = expr {
                                if let syn::Expr::Call(call) = &*ret.expr {
                                    if let syn::Expr::Path(path) = &*call.func {
                                        if path.path.is_ident("Err") {
                                            issues.push(ret.span());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    issues
}

Runtime detection with middleBrick specifically targets Actix's error handling and response patterns. The scanner sends malformed requests to trigger error conditions, then analyzes responses for sensitive information disclosure. middleBrick's black-box approach tests the actual running application without requiring source code access.

middleBrick's Actix-specific checks include:

  • Stack trace detection in error responses
  • Database query exposure analysis
  • Internal path disclosure through error messages
  • Schema information leakage in JSON errors
  • Debug mode detection through response characteristics
  • Logging middleware configuration analysis

The scanner uses a comprehensive test suite that sends requests designed to trigger various error conditions in Actix applications. For example, it sends invalid JSON to test deserialization error messages, malformed query parameters to test validation errors, and requests to non-existent endpoints to test 404 handling.

middleBrick's LLM security module also detects when Actix applications serve AI/ML endpoints that might leak system prompts or training data. This is particularly relevant as Actix gains popularity for serving machine learning models and chatbot APIs.

Continuous monitoring through middleBrick's Pro plan provides ongoing detection as your Actix application evolves. The scanner can be integrated into CI/CD pipelines to catch new disclosure vulnerabilities before deployment.

Actix-Specific Remediation

Remediating information disclosure vulnerabilities in Actix requires implementing proper error handling, sanitization, and configuration practices specific to the framework's architecture.

The foundation of secure error handling in Actix is implementing custom error types that never expose internal details. Create a sealed error enum that maps internal errors to safe, generic messages:

#[derive(Debug, thiserror::Error)]
pub enum AppError {
    #[error("Database operation failed")]
    DbError(#[from] sqlx::Error),
    #[error("Validation failed")]
    ValidationError(#[from] ValidationError),
    #[error("Internal server error")]
    InternalError,
}

impl actix_web::error::ResponseError for AppError {
    fn error_response(&self) -> HttpResponse {
        match self {
            AppError::DbError(_) => {
                // Log detailed error internally
                error!("Database error: {:?}", self);
                // Return generic message to client
                HttpResponse::InternalServerError()
                    .content_type("text/plain")
                    .body("Database operation failed")
            }
            AppError::ValidationError(_) => HttpResponse::BadRequest()
                .content_type("text/plain")
                .body("Invalid request data"),
            AppError::InternalError => HttpResponse::InternalServerError()
                .content_type("text/plain")
                .body("Internal server error"),
        }
    }
}

// Usage in handlers
async fn secure_handler() -> Result<HttpResponse, AppError> {
    let db_result = sqlx::query_as("SELECT * FROM users WHERE id = $1")
        .bind(1)
        .fetch_one(&pool)
        .await?;
        
    Ok(HttpResponse::Ok().json(db_result))
}

This pattern ensures that database errors, validation failures, and other internal issues never expose implementation details to clients. The detailed error information is logged internally for debugging while users receive only safe, generic messages.

For Actix's error catching mechanism, implement a custom catch block that sanitizes all errors:

#[catch(default)]
fn custom_catch(err: &actix_web::error::Error) -> actix_web::Result<HttpResponse> {
    // Log detailed error for internal use
    error!("Unhandled error: {:?}", err);
    
    // Return sanitized response
    Ok(HttpResponse::InternalServerError()
        .content_type("text/plain")
        .body("An unexpected error occurred"))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    std::env::set_var("RUST_BACKTRACE", "0");
    
    HttpServer::new(|| {
        App::new()
            .wrap(ErrorHandler::new(custom_catch))
            .service(user_service)
            .service(auth_service)
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Configure Actix's logging middleware to prevent sensitive data exposure:

use actix_web::middleware::Logger;
use env_logger::Env;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::init_from_env(Env::default().default_filter_or("info"));
    
    HttpServer::new(|| {
        App::new()
            .wrap(Logger::new(
                #[cfg(debug_assertions)]
                "%t (%a) %s %T",
                #[cfg(not(debug_assertions))]
                "%t (%a) %s",
            ))
            .service(user_service)
            .service(auth_service)
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

This configuration ensures that in production builds, request timing and other potentially sensitive information is omitted from logs.

For JSON deserialization, implement custom deserialization error handling that returns safe error messages:

#[derive(Debug, serde::Deserialize)]
pub struct SafeUserRequest {
    #[serde(deserialize_with = "deserialize_email")]
    pub email: String,
    // other fields...
}

fn deserialize_email<'de, D>(deserializer: D) -> Result
where
    D: serde::Deserializer<'de>,
{
    let email = String::deserialize(deserializer)?;
    if email.contains('@') {
        Ok(email)
    } else {
        // Return generic validation error without schema details
        Err(serde::de::Error::custom("Invalid email format"))
    }
}

async fn create_user(
    json: web::Json<SafeUserRequest>,
) -> Result<HttpResponse, AppError> {
    // Safe deserialization with generic error messages
    let user: SafeUserRequest = json.into_inner();
    
    // Process user creation...
    Ok(HttpResponse::Ok().finish())
}

Finally, implement comprehensive input validation using Actix's built-in validation features or crates like validator to prevent malformed input from causing error conditions that might leak information:

use actix_web_validator::ValidatedQuery;
use validator::Validate;

#[derive(Validate, Deserialize)]
pub struct SearchQuery {
    #[validate(length(min = 1, max = 100))]
    pub query: String,
    #[validate(range(min = 1, max = 100))]
    pub page: usize,
}

async fn search(
    query: ValidatedQuery<SearchQuery>,
) -> Result<HttpResponse, AppError> {
    let query = query.into_inner();
    
    // Safe to use query parameters without further validation
    let results = search_database(&query.query, query.page)?;
    Ok(HttpResponse::Ok().json(results))
}

These remediation strategies, combined with middleBrick's continuous scanning, create a robust defense against information disclosure vulnerabilities in Actix applications.

Frequently Asked Questions

How does middleBrick detect information disclosure in Actix applications?
middleBrick uses black-box scanning to send malformed requests that trigger error conditions in Actix applications. It analyzes responses for sensitive information like stack traces, database queries, internal paths, and schema details. The scanner tests error handling patterns specific to Actix's architecture, including catch blocks, JSON deserialization errors, and middleware logging configurations. middleBrick's 12 security checks include specialized detection for information disclosure across authentication, input validation, and error handling components.
What makes Actix applications particularly vulnerable to information disclosure?