Securing Akka.NET Clusters: Understanding CVE-2025-61778 and mTLS

Akka.NET

A deep dive into the critical TLS authentication bypass vulnerability in Akka.NET and how mutual TLS (mTLS) fixes it

Aaron Stannard / November 24, 2025

What We'll Cover Today

  • The Vulnerability: CVE-2025-61778
  • Understanding Mutual TLS (mTLS)
  • How Akka.NET Fixed It
  • Real-World Implementation (DrawTogether.NET)
  • Security Best Practices

Why Cluster Security Matters

Akka.NET Clusters in the Wild

  • Financial services processing transactions
  • Gaming backends managing player state
  • IoT platforms coordinating devices
  • Microservices communicating across cloud networks

The Risk: Unauthorized nodes joining your cluster

  • Data exfiltration
  • Command injection
  • Cluster disruption

The Vulnerability

CVE-2025-61778: What Went Wrong?

CVE-2025-61778 Overview

Critical Severity

Advisory: GHSA-jhpv-4q4f-43g5

Published: October 6, 2025

Affected: v1.2.0 - v1.5.51

CWE Classifications

  • CWE-290: Auth Bypass by Spoofing
  • CWE-295: Improper Cert Validation
  • CWE-306: Missing Auth for Critical Function

The Broken Handshake

What the original TLS implementation looked like

Client Node
Connecting...
❌ No Certificate
- - - - →
Server Node
Listening on :5055
✓ Has Certificate
⚠️ Anyone Can Connect!
Server never requests client certificate

Attack Scenario

How an attacker could exploit this vulnerability

Node-1
Seed 🔒
Node-2
Worker 🔒
Node-3
Worker 🔒
Attacker
❌ No Cert
📤 Data Theft
💉 Injection
💥 Disruption

Result: Attacker joins cluster without valid credentials

What Was Wrong?

One-Way Authentication

"The TLS implementation was fundamentally incomplete. While it enforced server-side certificate validation for inbound connections, it never asked the outbound-connecting client to present its certificate."
— CVE-2025-61778 Description

Technical Details

  • Server validated its own certificate ✓
  • Server never requested client certificate ❌
  • Asymmetrical security posture
  • No mutual authentication

Who Was Affected?

⚠️ High Risk

  • Internet-exposed clusters
  • Cloud/multi-tenant deployments
  • Environments requiring TLS
  • Untrusted network boundaries

ℹ️ Lower Risk

  • Fully isolated private networks
  • Air-gapped environments
  • Trusted network perimeters
  • No TLS needed/configured

Key Point: This vulnerability affected environments where TLS was needed - exposed to the internet or untrusted networks.

Understanding mTLS

Mutual Transport Layer Security

Traditional TLS vs Mutual TLS

🌐
Traditional TLS
🔐
Mutual TLS (mTLS)
Direction Server → Client Server ↔ Client
Server Certificate ✓ Presents ✓ Presents
Client Certificate ✗ Anonymous ✓ Presents
Validation Client validates server Both validate each other
Use Case Websites, public APIs Internal APIs, clusters

The Correct Handshake

How mTLS provides mutual authentication

Client Node
Authenticated
✓ Has Certificate
Client Cert →
← Server Cert
Server Node
Authenticated
✓ Has Certificate
✓ Secure Connection Established
Both parties authenticated

Result: Only nodes with valid certificates can communicate

Certificate Validation: Layer 1

Chain Validation - Is this certificate trustworthy?

Configuration

new DotNettySslSetup(cert,
  suppressValidation: false,
  requireMutualAuthentication: true);

What It Validates

  • From trusted CA?
  • Chain complete?
  • Not expired?
  • Proper key usage?

✓ Enabled by default - Never set suppressValidation: true in production!

Certificate Validation: Layer 2

Hostname Validation - Is this certificate for this server?

Configuration

new DotNettySslSetup(cert,
  suppressValidation: false,
  requireMutualAuthentication: true,
  validateCertificateHostname: true);

What It Validates

  • Hostname matches cert?
  • Alt names match?
  • Cert is for this server?

⚠️ Optional but recommended - Prevents MITM attacks with stolen certs

Before: Vulnerable Code

Akka.NET v1.5.51 and earlier

❌ Missing Mutual Authentication

// Old API - no mTLS support
var sslSetup = new DotNettySslSetup(
    certificate: cert,
    suppressValidation: false
);
// Client never had to present certificate!

The Problem

  • Server presents its certificate ✓
  • Client validates server ✓
  • Client never presents certificate ✗
  • Server never validates client ✗

After: Secure Code

Akka.NET v1.5.52+

✓ Mutual Authentication Enabled

// New API with mTLS support
var sslSetup = new DotNettySslSetup(
    certificate: cert,
    suppressValidation: false,
    requireMutualAuthentication: true  // NEW!
);

The Fix

  • Server presents its certificate ✓
  • Client validates server ✓
  • Client presents certificate ✓
  • Server validates client ✓

Advanced Validation (v1.5.55+)

Programmatic certificate validation helpers

CertificateValidation Methods

  • ValidateChain() - OS trust store
  • ValidateHostname() - CN/SAN check
  • PinnedCertificate() - Thumbprint pin
  • ValidateSubject() - Subject match
  • ValidateIssuer() - Issuer match
  • Combine() - Multiple validators

Example: Certificate Pinning

var validator = CertificateValidation.Combine(
  CertificateValidation.ValidateChain(),
  CertificateValidation.PinnedCertificate(
    "2531c78c51e5041...") // thumbprint
);

var ssl = new DotNettySslSetup(
  cert, false, true, validator);

Migration Path

How to update your cluster

1. Update Akka.NET

dotnet add package Akka --version 1.5.55

2. Enable Validation

akka.remote.dot-netty.tcp.ssl {
  suppress-validation = false
  validate-certificate-hostname = true
}

3. Certificate Requirements

  • Use CA-signed certificates in production
  • Ensure proper CN/SAN values
  • All nodes need valid certificates

4. Testing

  • Test in staging first
  • Verify cluster formation
  • Monitor for connection errors

Real-World Implementation

DrawTogether.NET on Kubernetes

DrawTogether.NET Architecture

Akka.NET cluster with TLS on Kubernetes

Load Balancer
HTTP :8080
Headless Service
akka.ssl.tcp://drawtogether
🔒 TLS Certs
K8s Secret
Pod-0
Seed :5055 🔒
Pod-1
Worker :5055 🔒
Pod-2
Worker :5055 🔒

TLS Configuration in DrawTogether.NET


public class TlsSettings
{
    public bool Enabled { get; set; } = false;
    public string? CertificatePath { get; set; }
    public string? CertificatePassword { get; set; }
    public bool ValidateCertificates { get; set; } = true;

    public X509Certificate2? LoadCertificate()
    {
        if (!Enabled || string.IsNullOrEmpty(CertificatePath))
            return null;

        return new X509Certificate2(
            CertificatePath,
            CertificatePassword
        );
    }
}

Simple, configuration-driven TLS settings

Best Practices

Security Recommendations for Production

Security Best Practices

✓ DO

  • Use TLS in production environments
  • Enable certificate validation (suppress-validation = false)
  • Enable hostname validation when possible
  • Use CA-signed certificates in production
  • Store certificates in OS certificate store
  • Use Kubernetes secrets for certificate management
  • Validate certificates at application startup
  • Keep Akka.NET updated (v1.5.52+)
  • Test certificate rotation procedures
  • Use network isolation (firewalls, VPCs)

✗ DON'T

  • Expose Akka.Remote to public internet
  • Use suppress-validation = true in production
  • Use self-signed certificates in production
  • Store certificate passwords in code
  • Commit certificates to source control
  • Use the same certificate for everything
  • Ignore certificate expiration dates
  • Skip testing TLS in staging environments
  • Assume private networks are secure
  • Delay security updates

Production Deployment Checklist

  • ☐ Running Akka.NET v1.5.52 or later (v1.5.55 recommended)
  • ☐ TLS enabled on all cluster nodes
  • ☐ Certificate validation enabled (suppress-validation = false)
  • ☐ Hostname validation enabled (validate-certificate-hostname = true)
  • ☐ Using CA-signed certificates (not self-signed)
  • ☐ Certificates stored securely (OS store or K8s secrets)
  • ☐ Certificate expiration monitoring in place
  • ☐ Certificate rotation procedure documented and tested
  • ☐ Akka.Remote not exposed to public internet
  • ☐ Network isolation configured (firewall rules, network policies)
  • ☐ TLS tested in staging environment
  • ☐ Monitoring and alerting for connection failures

Key Takeaways

  1. CVE-2025-61778 was critical but fixable - The vulnerability allowed unauthenticated access to TLS-enabled clusters
  2. mTLS = mutual authentication - Both client and server must prove their identity
  3. Two-layer validation matters - Chain validation AND hostname validation provide defense in depth
  4. Update immediately - Akka.NET v1.5.52+ required for secure TLS
  5. DrawTogether.NET shows it works - Real-world Kubernetes deployment with production-ready security
  6. Security is a process - Regular updates, monitoring, and testing are essential

Resources & References

Official Documentation

Example Implementation

Related Pull Requests

  • PR #7847: Fail-fast certificate validation
  • PR #7851: Mutual TLS enforcement

Thank You!

Questions?

https://aaronstannard.com
@aaronstannard