Missing Tls in Actix with Mutual Tls
Missing Tls in Actix with Mutual Tls — how this specific combination creates or exposes the vulnerability
When an Actix web service is configured to require client certificates for Mutual TLS but the server listener itself lacks TLS, the transport is effectively unencrypted and unauthenticated. This mismatch means clients may establish a plaintext HTTP connection even though the application expects client-side authentication, bypassing the intended Mutual TLS protections.
The vulnerability arises because Mutual TLS relies on two-way authentication over a cryptographically secured channel. Without server-side TLS, there is no encryption in transit, exposing credentials, tokens, and session cookies to eavesdropping. Additionally, without server certificate validation, clients cannot verify the identity of the server, enabling man-in-the-middle attacks. An attacker on the network can intercept or modify requests, and because the server is not enforcing TLS, it may treat the unauthenticated plaintext connection as trusted based solely on the presence of a client certificate that is never validated due to missing server-side TLS termination.
During a middleBrick scan, this configuration appears as Missing Tls combined with ineffective Mutual Tls, producing findings in the Encryption and Authentication categories. The scanner detects that the endpoint does not present a valid server certificate and does not enforce HTTPS, even when the application logic assumes Mutual TLS is active. Findings include the absence of server certificate validation, lack of transport-layer encryption, and potential exposure of sensitive data. Remediation guidance typically involves enabling TLS on the server, ensuring the server presents a valid certificate, and configuring the Actix service to require and verify client certificates over the encrypted channel.
In the context of compliance frameworks referenced by middleBrick, such findings map to OWASP API Top 10 A02:2023 — Cryptographic Failures, and can also affect PCI-DSS and SOC2 controls where encryption in transit is required. middleBrick’s scans identify these gaps and provide prioritized remediation steps so teams can enforce proper Mutual TLS in Actix deployments.
Mutual Tls-Specific Remediation in Actix — concrete code fixes
To secure an Actix service with Mutual TLS, you must enable server-side TLS with a valid certificate and private key, and configure the Actix application to require and validate client certificates. Below is a concrete, working example using Rust and Actix-web with native-tls or rustls.
Using native-tls (openssl-based)
use actix_web::{web, App, HttpServer, Responder};
use actix_web::middleware::Logger;
use native_tls::Identity;
use std::fs::File;
use std::io::Read;
async fn index() -> impl Responder {
"Hello over Mutual TLS"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Load server identity (certificate + private key)
let mut cert_file = File::open("server-cert.pem").expect("cannot open server cert");
let mut key_file = File::open("server-key.pem").expect("cannot open server key");
let mut cert_buf = Vec::new();
let mut key_buf = Vec::new();
cert_file.read_to_end(&mut cert_buf).unwrap();
key_file.read_to_end(&mut key_buf).unwrap();
let identity = Identity::from_pkcs8(&cert_buf, &key_buf).expect("invalid pkcs8");
// Configure TLS acceptor with client CA for client certificate verification
let mut builder = native_tls::TlsAcceptor::builder(identity);
let mut ca_file = File::open("ca-chain.pem").expect("cannot open CA cert");
let mut ca_buf = Vec::new();
ca_file.read_to_end(&mut ca_buf).unwrap();
let ca = native_tls::Certificate::from_pem(&ca_buf).expect("invalid CA cert");
builder.add_root_certificate(ca);
builder.client_auth_native_tls(native_tls::ClientAuth::Required);
let acceptor = builder.build().expect("failed to build TLS acceptor");
HttpServer::new(|| {
App::new()
.wrap(Logger::default())
.route("/", web::get().to(index))
})
.bind_rustls("0.0.0.0:8443", acceptor)?
.run()
.await
}
Using rustls (recommended for modern Rust)
use actix_web::{web, App, HttpServer, Responder};
use actix_web::middleware::Logger;
use rustls::{Certificate, PrivateKey, ServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::fs::File;
use std::io::BufReader;
use std::sync::Arc;
async fn index() -> impl Responder {
"Hello over Mutual TLS (rustls)"
}
fn load_rustls_config() -> Arc {
// Load server certificate and key
let cert_file = &mut BufReader::new(File::open("server-cert.pem").unwrap());
let key_file = &mut BufReader::new(File::open("server-key.pem").unwrap());
let cert_chain = certs(cert_file).unwrap_or_else(|_| panic!("failed to load certs"));
let mut keys = pkcs8_private_keys(key_file).unwrap_or_else(|_| panic!("failed to load keys"));
let certs: Vec = cert_chain.into_iter().map(Certificate).collect();
let priv_key = PrivateKey(keys.remove(0));
// Load trusted client CA for client certificate verification
let mut ca_file = BufReader::new(File::open("ca-chain.pem").unwrap());
let client_certs = certs(&mut ca_file).unwrap_or_else(|_| panic!("failed to load CA"));
let client_certs: Vec = client_certs.into_iter().map(Certificate).collect();
let mut config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_client_auth_cert(client_certs, priv_key)
.expect("invalid client auth config");
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
Arc::new(config)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let config = load_rustls_config();
HttpServer::new(move || {
App::new()
.wrap(Logger::default())
.route("/", web::get().to(index))
})
.bind_rustls("0.0.0.0:8443", config)?
.run()
.await
}
Key points in the remediation:
- Always enable TLS on the server with a valid certificate; do not rely on application-level checks alone.
- Configure the TLS acceptor to require client certificates (e.g.,
client_auth_native_tls(native_tls::ClientAuth::Required)or.with_client_auth_cert(...)in rustls). - Provide a trusted CA bundle to validate presented client certificates; reject connections without a valid client cert.
- Ensure the server certificate chain is complete and the private key is protected.
- Use strong cipher suites and disable outdated protocols (TLS 1.2+ recommended).
After applying these fixes, re-run the middleBrick scan to confirm that Encryption and Authentication findings are resolved and that the endpoint now presents a valid server certificate while enforcing Mutual TLS.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |