Hallucination Attacks with Mutual Tls
How Hallucination Attacks Manifest in Mutual TLS
Hallucination attacks occur when a language model generates plausible‑but‑incorrect output that a developer copies into code. In the context of Mutual TLS (mTLS), the hallucination typically involves TLS configuration snippets that appear correct but disable or misconfigure critical validation steps. For example, an LLM might suggest:
# Node.js (hallucinated)
const tls = require('tls');
const options = {
key: fs.readFileSync('client-key.pem'),
cert: fs.readFileSync('client-cert.pem'),
// ❌ Hallucination: rejectsUnauthorized set to false
rejectUnauthorized: false,
// ❌ Hallucination: ca omitted, relying on system store only
};
const socket = tls.connect(443, 'api.example.com', options, () => {
console.log('connected', socket.authorized ? 'authorized' : 'unauthorized');
});
The two hallucinated lines—rejectUnauthorized: false and missing ca—cause the client to accept any server certificate, defeating mutual authentication. Similar patterns appear in Go (InsecureSkipVerify: true) and Java (setTrustManagers(new TrustManager[]{ new X509TrustManager() { ... } })). These misconfigurations are often introduced when developers rely on AI‑generated boilerplate without verifying the security implications, leading to a classic man‑in‑the‑middle (MITM) scenario where an attacker can present a forged certificate and intercept or modify API traffic.
OWASP LLM Top 10 classifies this as LLM02: Insecure Output Handling, because the model’s output is used directly in a security‑critical control flow without validation.
Mutual TLS‑Specific Detection
Detecting hallucinated mTLS configurations requires observing the actual TLS handshake at runtime, not just inspecting source code. middleBrick performs unauthenticated black‑box scans that include:
- Verifying that the server requests a client certificate (
CertificateRequestmessage). - Checking that the client presents a valid certificate chain that chains to a trusted CA.
- Ensuring that the server rejects connections when the client certificate is missing, expired, or not signed by the expected CA.
- Testing for common hallucination‑induced misconfigurations such as disabled certificate verification (
rejectUnauthorized: falseorInsecureSkipVerify: true) and missing CA pools.
If any of these checks fail, middleBrick flags the finding under the "LLM/AI Security" category with a severity based on the potential impact (e.g., medium if the endpoint is internal‑only, high if exposed to the internet).
Example CLI usage to scan an API endpoint:
# Install the middleBrick CLI (npm)
npm i -g middlebrick
# Scan a target URL; the tool returns a JSON report
middlebrick scan https://api.example.com/health
# Sample excerpt of the report (JSON)
{
"findings": [
{
"id": "mTLS-001",
"title": "Client certificate verification disabled",
"description": "The TLS client connects with rejectUnauthorized: false, accepting any server certificate.",
"severity": "medium",
"remediation": "Set rejectUnauthorized to true and provide a trusted CA pool."
}
]
}
The same detection logic is available via the GitHub Action (fail builds on unsafe mTLS settings) and the MCP Server, allowing developers to catch hallucinated configurations directly from their IDE or CI pipeline.
Mutual TLS‑Specific Remediation
Remediation involves correcting the TLS configuration to enforce proper mutual authentication. Below are language‑specific examples that replace the hallucinated snippets with secure defaults.
Node.js (tls)
const tls = require('tls');
const fs = require('fs');
const options = {
key: fs.readFileSync('client-key.pem'),
cert: fs.readFileSync('client-cert.pem'),
ca: fs.readFileSync('trusted-ca.pem'), // ✅ Explicit trust anchor
rejectUnauthorized: true // ✅ Enforce verification
};
const socket = tls.connect(443, 'api.example.com', options, () => {
if (socket.authorized) {
console.log('Connection authorized');
} else {
console.error('Connection unauthorized:', socket.authorizationError);
}
});
socket.on('error', err => {
console.error('TLS error:', err.message);
});
Go (crypto/tls)
pool := x509.NewCertPool()
caCert, _ := os.ReadFile("trusted-ca.pem")
pool.AppendCertsFromPEM(caCert)
cert, _ := tls.LoadX509KeyPair("client-cert.pem", "client-key.pem")
config := &tls.Config{
RootCAs: pool, // ✅ Trusted CA pool
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: false, // ✅ Do NOT skip verification
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// Optional: enforce specific subject or SAN checks
if len(verifiedChains) == 0 {
return errors.New("client certificate not trusted")
}
return nil
},
}
conn, err := tls.Dial("tcp", "api.example.com:443", config)
if err != nil {
log.Fatalf("TLS handshake failed: %v", err)
}
defer conn.Close()
Java (SSLSocketFactory)
KeyStore clientKS = KeyStore.getInstance("PKCS12");
clientKS.load(new FileInputStream("client.p12"), "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKS, "password".toCharArray());
KeyStore trustKS = KeyStore.getInstance("JKS");
trustKS.load(new FileInputStream("truststore.jks"), "trustpass".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustKS);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
SSLSocketFactory factory = ctx.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket("api.example.com", 443);
// Enable endpoint identification and certificate verification
socket.setEnableSessionCreation(true);
socket.startHandshake();
if (!socket.getSession().getPeerPrincipal().getName().contains("api.example.com")) {
throw new SSLPeerUnverifiedException("Unexpected server certificate");
}
After applying these fixes, rerun the middleBrick scan; the finding should disappear, confirming that the mutual TLS channel now properly authenticates both parties.
Related CWEs: llmSecurity
| CWE ID | Name | Severity |
|---|---|---|
| CWE-754 | Improper Check for Unusual or Exceptional Conditions | MEDIUM |