The Worst Security Vulnerability in Akka.NET - And How to Fix It
Understanding CVE-2025-61778 and securing your Akka.NET clusters with mTLS
15 minutes to read- Video Overview
- The Vulnerability: CVE-2025-61778
- Understanding Mutual TLS (mTLS)
- The Fix
- Security Best Practices
- Real-World Implementation: DrawTogether.NET
- Key Takeaways
- Resources
In October 2025, we disclosed the most critical security vulnerability ever found in Akka.NET: CVE-2025-61778. This vulnerability affects Akka.Remote’s TLS implementation - specifically, we were supposed to implement mutual TLS (mTLS), but we didn’t. The server never validated client certificates, meaning anyone who could reach your Akka.Remote endpoint could potentially join your cluster without any authentication.
The immediate action you should take: upgrade to Akka.NET v1.5.56 or later. The vulnerability has been fully patched in these versions.
In this post, we’ll cover the nature of this vulnerability, who was affected, how we fixed it, and - most importantly - security best practices for securing your Akka.NET applications going forward.
This vulnerability was discovered by one of our Production Support customers during a security audit. Within 2-3 weeks of being notified, we shipped four patches (v1.5.52 through v1.5.56) to address the issue. This is exactly the kind of critical response our support customers receive - and the entire Akka.NET community benefits from their vigilance.
Video Overview
We’ve also produced a detailed video covering this topic:
The rest of this article covers the same material for those who prefer reading.
The Vulnerability: CVE-2025-61778
What Went Wrong
The fundamental issue was straightforward but severe: the Akka.Remote TLS server never validated client certificates.
When a client connected to an Akka.Remote server with TLS enabled, the server would present its certificate and encrypt the connection - but it never asked the connecting client to prove who they were. This is like a secure building where the guard verifies their own badge but never asks to see yours.
Here’s what the broken handshake looked like:
❌ No Certificate
✓ Has Certificate
The result? Anyone who could reach your Akka.Remote port could connect, regardless of whether they had valid credentials.
CVE Details
| Field | Value |
|---|---|
| Advisory | GHSA-jhpv-4q4f-43g5 |
| Severity | Critical |
| Published | October 6, 2025 |
| Affected Versions | 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) |
Attack Scenario
Consider a three-node Akka.NET cluster where all nodes have valid, pinned certificates - a very secure posture. With this vulnerability, an attacker with no certificate at all could:
- Connect to any node in the cluster
- Join the cluster as a malicious member
- Exfiltrate data by reading cluster messages
- Inject destructive commands (killing actors or removing cluster nodes)
- Disrupt cluster operations entirely
This is what made the CVE so severe - it completely bypassed certificate-based security for clusters that believed they were protected.
Who Was Affected?
NOT affected:
- Applications not using TLS at all (your security posture is unchanged)
- Fully isolated private networks where only trusted software can access Akka.Remote ports
Potentially affected:
- Multi-datacenter deployments with unpeered internet connections between data centers
- IoT systems where untrusted devices communicate with your Akka.NET cluster
- Any deployment relying on TLS to protect against untrusted network boundaries
- Cloud deployments where network isolation isn’t guaranteed
If your Akka.Remote endpoints are never exposed outside a trusted network perimeter, and you have network-level security (firewalls, VPC isolation, etc.), this vulnerability likely didn’t impact you in practice. However, if you were relying on TLS as your primary security mechanism, you were at risk.
Understanding Mutual TLS (mTLS)
Why Akka.NET Needs mTLS
Akka.NET’s security requirements are fundamentally different from typical web applications. In a web application, you have clear client/server roles - users connect to your server, and you don’t need to verify they have certificates (you use passwords, tokens, etc. instead).
Akka.Remote is different. At the TCP level, when Node A connects to Node B, Node A performs client-side behavior and Node B performs server-side behavior. If Node B later connects to Node C, then Node B acts as the client. In a mesh topology, any node might be a client or server depending on who initiated the connection.
This is why mutual TLS matters: we need symmetric credential checking on both sides of every connection. The server must validate the client’s certificate, and the client must validate the server’s certificate. The CVE existed because we only implemented half of this - servers never validated client certificates.
This is mutual TLS - both sides present certificates, and both sides validate each other.
Traditional TLS vs. Mutual TLS
| Aspect | Traditional TLS (Web) | 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
With mTLS properly implemented, here’s what the handshake looks like:
✓ Has Certificate
✓ Has Certificate
Both nodes present their certificates, and both nodes validate the other’s certificate. Only when mutual validation succeeds does the connection proceed.
Certificate Validation Layers
There are multiple layers of certificate validation you can apply:
Layer 1: Chain Validation (Default)
- Validates the certificate is from a trusted Certificate Authority
- Checks the chain of trust is complete
- Verifies the certificate isn’t expired
- Confirms proper key usage attributes
var sslSetup = new DotNettySslSetup(
certificate: cert,
suppressValidation: false, // Enable chain validation
requireMutualAuthentication: true
);
Layer 2: Hostname Validation (Recommended)
- Verifies the certificate’s Common Name (CN) or Subject Alternative Names (SAN) match the connecting host
- Prevents man-in-the-middle attacks with stolen certificates
var sslSetup = new DotNettySslSetup(
certificate: cert,
suppressValidation: false,
requireMutualAuthentication: true,
validateCertificateHostname: true // Enable hostname validation
);
Layer 3: Certificate Pinning (Maximum Security)
- Validates that the certificate has a specific thumbprint
- Every node in the cluster uses the exact same certificate
- Highest security, but requires careful certificate rotation planning
var validator = CertificateValidation.Combine(
CertificateValidation.ValidateChain(),
CertificateValidation.PinnedCertificate("2531c78c51e5041...")
);
var sslSetup = new DotNettySslSetup(cert, false, true, validator);
The Fix
What Changed
Starting with Akka.NET v1.5.52, we added a new requireMutualAuthentication parameter that is enabled by default. This ensures the server actively validates client certificates.
Before (v1.5.51 and earlier) - Vulnerable:
// Old API - no mTLS support
var sslSetup = new DotNettySslSetup(
certificate: cert,
suppressValidation: false
);
// Client never had to present certificate!
After (v1.5.52+) - Secure:
// New API with mTLS support
var sslSetup = new DotNettySslSetup(
certificate: cert,
suppressValidation: false,
requireMutualAuthentication: true // NEW - enabled by default!
);
The server now aggressively validates client certificates and will reject any connection from a client with an invalid or missing certificate.
Advanced Validation (v1.5.56+)
In v1.5.56, we added powerful programmatic validation helpers through the CertificateValidation factory class:
// Combine multiple validation rules
var validator = CertificateValidation.Combine(
CertificateValidation.ValidateChain(), // OS trust store
CertificateValidation.ValidateHostname(), // CN/SAN check
CertificateValidation.PinnedCertificate( // Exact thumbprint
"2531c78c51e5041abc123...")
);
// Or validate specific certificate attributes
var validator = CertificateValidation.Combine(
CertificateValidation.ValidateSubject("CN=*.mycompany.com"),
CertificateValidation.ValidateIssuer("CN=MyCompany Root CA")
);
These methods are fully composable, allowing you to build validation logic that matches your organization’s security requirements.
Configuration Options
You can configure TLS through HOCON, Akka.Hosting, or the DotNettySslSetup class - all paths ultimately go to the same place:
HOCON:
akka.remote.dot-netty.tcp.ssl {
suppress-validation = false
validate-certificate-hostname = true
}
Akka.Hosting:
var validator = CertificateValidation.Combine(
CertificateValidation.ValidateChain(),
CertificateValidation.ValidateHostname("*.prod.mycompany.internal")
);
builder.WithRemoting(options => {
options.EnableSsl = true;
options.Ssl = new SslOptions {
X509Certificate = cert,
SuppressValidation = false,
CertificateValidation = validator
};
});
Security Best Practices
Option 1: Don’t Expose Akka.Remote Publicly
The simplest and most effective security posture is to never expose Akka.Remote to untrusted networks. Think of Akka.Remote like your database - you wouldn’t expose your database port publicly, and you shouldn’t expose Akka.Remote either.
Instead:
- Keep Akka.Remote on private networks only
- Expose functionality through web APIs, gRPC, or message brokers
- Use firewalls and VPC isolation to restrict access
- Use Kubernetes network policies to limit pod-to-pod communication
For most Akka.NET applications, this network-level isolation is sufficient security. If only your own trusted software can reach the Akka.Remote port, you may not need TLS at all.
Option 2: Use mTLS When Needed
There are scenarios where TLS is necessary or recommended:
- Multi-datacenter deployments where traffic crosses unpeered network boundaries
- Regulated industries (healthcare, energy, finance) with compliance requirements
- IoT systems where untrusted devices communicate with your cluster
- Cluster Client scenarios where external parties need to interact with your cluster
If you’re in one of these scenarios, enable mTLS with at least chain validation, and consider adding hostname validation for defense in depth.
When to Use Each Validation Level
| Scenario | Recommended Validation |
|---|---|
| Private network, trusted software only | TLS optional, network isolation sufficient |
| Multi-datacenter with VPN/peering | Chain validation minimum |
| Cross-cloud or untrusted networks | Chain + hostname validation |
| Maximum security / compliance | Chain + hostname + certificate pinning |
Note that certificate pinning provides the highest security but requires careful planning for certificate rotation - all nodes need the new certificate before you can rotate.
Real-World Implementation: DrawTogether.NET
We recently added TLS support to DrawTogether.NET, our sample Akka.NET application running on Kubernetes. Here’s how it’s configured:
TLS Settings Class
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 (string.IsNullOrWhiteSpace(CertificatePath))
return null;
if (!File.Exists(CertificatePath))
throw new FileNotFoundException(
$"Certificate file not found at: {CertificatePath}");
return !string.IsNullOrWhiteSpace(CertificatePassword)
? X509CertificateLoader.LoadPkcs12FromFile(
CertificatePath, CertificatePassword)
: X509CertificateLoader.LoadCertificateFromFile(CertificatePath);
}
}
Kubernetes Deployment
The certificate is stored as a Kubernetes secret and mounted into pods:
# StatefulSet configuration
env:
- name: AkkaSettings__TlsSettings__Enabled
value: "true"
- name: AkkaSettings__TlsSettings__CertificatePath
value: "/certs/akka-node.pfx"
- name: AkkaSettings__TlsSettings__CertificatePassword
valueFrom:
secretKeyRef:
name: akka-tls-password
key: password
volumeMounts:
- name: tls-cert
mountPath: /certs
readOnly: true
volumes:
- name: tls-cert
secret:
secretName: akka-tls-cert
The full implementation is available in the DrawTogether.NET repository.
Key Takeaways
- Upgrade immediately to Akka.NET v1.5.56 or later if you’re using TLS
- mTLS is essential for peer-to-peer distributed systems like Akka.NET clusters
- Network isolation is the simplest security approach for most deployments
- Use mTLS when crossing trust boundaries or when compliance requires it
- Enable hostname validation for additional protection against MITM attacks
- Consider certificate pinning for maximum security in high-risk environments
- Never set
suppressValidation: truein production - it disables all certificate validation
Resources
- GitHub Security Advisory: GHSA-jhpv-4q4f-43g5
- Akka.NET Security Documentation
- DrawTogether.NET Repository
- Akka.NET v1.5.56 Release
If you have any questions about securing your Akka.NET cluster, feel free to leave a comment below or reach out through our support channels.
If you liked this post, you can share it with your followers or follow us on Twitter!
- Read more about:
- Akka.NET
- Case Studies
- Videos
Observe and Monitor Your Akka.NET Applications with Phobos
Did you know that Phobos can automatically instrument your Akka.NET applications with OpenTelemetry?
Click here to learn more.
