MEDIUM hallucination attacksmutual tls

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 (CertificateRequest message).
  • 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: false or InsecureSkipVerify: 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 IDNameSeverity
CWE-754Improper Check for Unusual or Exceptional Conditions MEDIUM

Frequently Asked Questions

Can middleBrick automatically fix hallucinated mTLS configurations in my code?
No. middleBrick only detects and reports security issues, providing remediation guidance. You must apply the fixes yourself in your source code or configuration.
Does middleBrick require any agents or credentials to scan for mTLS problems?
No. middleBrick performs unauthenticated black‑box scans by simply submitting the target URL; no agents, agents, or credentials are needed.