What Is CVE-2026-94418?
Vulnerability Overview
CVE-2026-94418 is a critical authentication bypass vulnerability in wolfSSL’s embedded TLS library that allows attackers to present forged certificates without valid cryptographic signatures. The flaw emerges when wolfSSL is compiled with the WOLFSSL_SMALL_CERT_VERIFY optimization macro—a memory-saving feature designed for resource-constrained devices—combined with application-level verification callbacks that override certificate date errors.
The core issue: a logic flaw in the ProcessPeerCertParse() function suppresses signature verification failures (ASN_SIG_CONFIRM_E) when certificate parsing errors occur first. Because date validity checks happen during the parsing phase, an intentionally expired certificate can mask an invalid signature. If the application’s callback returns 1 to override the date error, the handshake succeeds despite the forged signature.
Key distinction: This is not a cryptographic weakness in signature algorithms themselves, but rather a control-flow bug that prevents signature verification from being properly evaluated and reported.
Why It Matters for Your Infrastructure
Authentication is the foundation of TLS security. If peer certificates can be forged without CA compromise, attackers can:
- Impersonate any server or client in a TLS/DTLS session
- Intercept encrypted traffic without detection
- Poison certificate caches with invalid chain certificates that persist across connection restarts
- Bypass mutual authentication in both directions (client and server verification)
The vulnerability affects TLS 1.2, TLS 1.3, and DTLS—protocols used across IoT devices, embedded systems, industrial control networks, and resource-constrained edge deployments where WOLFSSL_SMALL_CERT_VERIFY is most likely to be enabled.
Affected Systems & Build Configurations
Vulnerable Autotools Flags
The vulnerability is only present when wolfSSL is compiled with specific low-resource build flags:
./configure --enable-lowresource
./configure --enable-leantls
./configure --enable-tinytls13=cert
./configure --enable-tinytls13=mutualauth
Each of these flags implicitly enables WOLFSSL_SMALL_CERT_VERIFY at compile time.
Vulnerable Embedded Header Settings
Alternatively, the macro can be enabled by manually setting WC_CFG_SMALL_CERT_VERIFY to a non-zero value in examples/configs/user_settings_embedded.h:
#define WC_CFG_SMALL_CERT_VERIFY 1 // Vulnerable if set
Default state: Ships as 0 (disabled).
Default (Safe) Build Paths
The vulnerability is NOT present in:
- Standard
./configurebuilds (no flags) ./configure --enable-all./configure --enable-distro- Any CMake-based build (no CMake option exists for this macro)
- Default preset headers or platform-specific configurations
Critical point: WOLFSSL_SMALL_CERT_VERIFY is opt-in only. It does not activate implicitly through dependency chains or environment variables.
Technical Root Cause
Memory Optimization Trade-Off
Under normal wolfSSL operation, certificate parsing and signature verification occur in a single pass. The WOLFSSL_SMALL_CERT_VERIFY macro decouples these steps to reduce peak memory consumption:
- Parsing phase (
ParseCertRelative()): Extracts certificate fields, validates structure, checks date validity, name constraints, and critical extensions. - Signature verification phase (
ConfirmSignature()): Deferred and executed separately. - Result merging: Signature result is merged back into the overall parsing return code.
This separation is intentional for devices with limited RAM. However, the merging logic contains a critical flaw.
Logic Flaw in ProcessPeerCertParse()
The vulnerability exists in how ProcessPeerCertParse() merges the signature verification result:
// Pseudocode representation of the flaw
int ProcessPeerCertParse() {
int parseResult = ParseCertRelative(...); // Returns error if date is invalid
int sigResult = ConfirmSignature(...); // Signature verification
// FLAWED LOGIC:
if (parseResult == 0) { // Only merge if parsing succeeded
return sigResult; // Return signature result
}
return parseResult; // Return parsing error, IGNORING sigResult
}
The problem: If parseResult contains an error (e.g., ASN_BEFORE_DATE_E), the signature verification result is never merged and never returned to the application.
Error Masking Mechanism
In standard certificate validation, the sequence is:
- Verify signature first
- Only if signature is valid, check date validity
Separating these steps inverts the precedence:
- Check date validity (during parsing)
- Signature verification happens separately but is masked if parsing failed
Result: ASN_SIG_CONFIRM_E (signature failure) is never surfaced to the application callback. The callback only sees the date error.
Callback Exploitation Path
If an application registers a verify callback like this:
int myVerify(int preverify_ok, X509_STORE_CTX *ctx) {
int err = X509_STORE_CTX_get_error(ctx);
// Override date errors
if (err == ASN_BEFORE_DATE_E || err == ASN_AFTER_DATE_E) {
return 1; // Accept the certificate anyway
}
return preverify_ok;
}
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
The callback never sees the signature failure. It only sees the date error, overrides it, and the handshake succeeds with a forged certificate.
Attack Scenarios & Real-World Impact
Man-In-The-Middle via Forged Certificates
Attacker prerequisites:
- Network position to intercept TLS/DTLS handshakes (ARP spoofing, DNS hijacking, BGP hijacking, compromised router, etc.)
- No CA private key compromise required
- No stolen certificates required
Attack execution:
- Attacker crafts a self-signed certificate containing:
- Target server’s expected subject name (e.g.,
CN=api.example.com) - Trusted CA’s subject name as the issuer (spoofed)
- Validity period entirely in the past (e.g.,
notBefore: 2000-01-01,notAfter: 2000-12-31) - Arbitrary, invalid signature bytes
- Attacker’s own public/private key pair
-
Attacker presents this certificate during TLS handshake
-
Vulnerable client/server:
- Parses certificate, encounters date error
- Signature verification is masked
- Callback sees only date error, returns
1to override - Handshake completes successfully
- Attacker now has a TLS session with the victim using the forged certificate
Impact: Complete MITM capability. Attacker can decrypt, modify, or forge all traffic.
No CA Compromise Required
This is fundamentally different from traditional certificate forgery attacks. Attackers do not need:
- CA’s private key
- Stolen intermediate certificates
- Compromised HSMs or key management systems
- Access to certificate issuance infrastructure
The vulnerability bypasses signature verification entirely, making CA compromise unnecessary.
Certificate Chain Caching Contamination
If the forged certificate is presented as part of a chain (e.g., as an intermediate CA), wolfSSL caches it in the WOLFSSL_CTX certificate manager after the callback approves it.
Critical consequence: Closing the TLS connection does not clear the cached certificate. The contaminated context persists, and subsequent connections may accept the forged intermediate without re-verification.
Remediation requirement: Applications must restart the WOLFSSL_CTX context or restart the entire process to flush the cache.
Affected Protocols (TLS 1.2, TLS 1.3, DTLS)
The vulnerability affects:
- TLS 1.2 peer certificate verification
- TLS 1.3 peer certificate verification
- DTLS 1.2 peer certificate verification
- Both directions: Client-side server verification AND server-side client verification
Threat Assessment Matrix

Attacker Prerequisites
| Requirement | Details |
|---|---|
| Network Position | Ability to intercept or redirect TLS/DTLS traffic (MITM capability) |
| Certificate Crafting | Ability to generate X.509 certificates with arbitrary fields |
| CA Compromise | NOT required – no private key material needed |
| Stolen Credentials | NOT required – no legitimate certificates needed |
| Cryptographic Knowledge | Minimal – signature bytes can be random garbage |
System Prerequisites
| Requirement | Details |
|---|---|
| Build Configuration | Binary compiled with --enable-lowresource, --enable-leantls, or --enable-tinytls13=* |
| Callback Registration | Application calls wolfSSL_CTX_set_verify() or wolfSSL_set_verify() with WOLFSSL_VERIFY_PEER |
| Callback Behavior | Callback returns 1 (accept) when encountering ASN_BEFORE_DATE_E or ASN_AFTER_DATE_E |
| Protocol Version | TLS 1.2, TLS 1.3, or DTLS 1.2 |
Impact Scope
| Aspect | Scope |
|---|---|
| Authentication Bypass | Complete – peer identity cannot be verified |
| Confidentiality | Compromised – attacker can decrypt all traffic |
| Integrity | Compromised – attacker can modify all traffic |
| Availability | Potentially compromised – attacker can terminate connections |
| Persistence | Certificate caching allows contamination across sessions |
Severity Rating
- CVSS Base Score: 9.8 (Critical)
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: High
- Integrity Impact: High
- Availability Impact: High
How to Detect Vulnerable Deployments
Build Flag Audit Checklist
Step 1: Examine build scripts and configuration files
# Check Autotools configure invocations
grep -r "enable-lowresource\|enable-leantls\|enable-tinytls13" \
build_scripts/ Makefile.* configure.ac
# Check CMakeLists.txt
grep -i "WOLFSSL_SMALL_CERT_VERIFY\|lowresource\|leantls" CMakeLists.txt
# Check environment variables at build time
env | grep -i wolfssl
Step 2: Inspect compiled binaries
# Extract build flags from binary symbols
strings libwolfssl.a | grep -i "WOLFSSL_SMALL_CERT_VERIFY"
# Check for presence of vulnerable function signatures
nm -D libwolfssl.so | grep ProcessPeerCertParse
Step 3: Review source code configuration
# Check user_settings.h or user_settings_embedded.h
grep -n "WC_CFG_SMALL_CERT_VERIFY\|WOLFSSL_SMALL_CERT_VERIFY" \
user_settings*.h examples/configs/user_settings*.h
Source Code Callback Review
Identify vulnerable callback patterns:
// VULNERABLE PATTERN 1: Explicit date error override
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
int err = X509_STORE_CTX_get_error(ctx);
if (err == ASN_BEFORE_DATE_E || err == ASN_AFTER_DATE_E) {
return 1; // DANGEROUS: Accepts forged certificates
}
return preverify_ok;
}
// VULNERABLE PATTERN 2: Blanket override
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
return 1; // DANGEROUS: Accepts all certificates
}
// VULNERABLE PATTERN 3: Conditional override based on context
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
// ... some logic ...
if (is_development_mode) {
return 1; // DANGEROUS if WOLFSSL_SMALL_CERT_VERIFY is enabled
}
return preverify_ok;
}
Search for these patterns:
grep -rn "ASN_BEFORE_DATE_E\|ASN_AFTER_DATE_E" src/ --include="*.c"
grep -rn "wolfSSL_CTX_set_verify\|wolfSSL_set_verify" src/ --include="*.c"
grep -A 10 "verify_callback\|verify_func" src/ --include="*.c" | grep "return 1"
Automated Detection Approach
Create a detection script:
#!/bin/bash
# detect_cve_2026_94418.sh
VULNERABLE=0
# Check 1: Build flags
if grep -q "enable-lowresource\|enable-leantls\|enable-tinytls13" build.log; then
echo "[ALERT] Vulnerable build flag detected"
VULNERABLE=1
fi
# Check 2: Source code patterns
if grep -q "ASN_BEFORE_DATE_E.*return 1\|ASN_AFTER_DATE_E.*return 1" src/*.c; then
echo "[ALERT] Vulnerable callback pattern detected"
VULNERABLE=1
fi
# Check 3: Binary symbols
if strings libwolfssl.a | grep -q "WOLFSSL_SMALL_CERT_VERIFY"; then
echo "[ALERT] WOLFSSL_SMALL_CERT_VERIFY macro found in binary"
VULNERABLE=1
fi
if [ $VULNERABLE -eq 1 ]; then
echo "[CRITICAL] System may be vulnerable to CVE-2026-94418"
exit 1
else
echo "[OK] No obvious vulnerability indicators found"
exit 0
fi
Remediation & Hardening Steps
Recompile Without WOLFSSLSMALLCERT_VERIFY
Option 1: Use standard build flags
# Remove all low-resource flags
./configure \
--prefix=/usr/local \
--enable-shared \
--disable-lowresource \
--disable-leantls
make clean
make
make install
Option 2: Explicitly disable the macro
./configure \
CFLAGS="-UWOLFSSL_SMALL_CERT_VERIFY" \
--prefix=/usr/local
make clean
make
make install
Option 3: Use CMake (recommended for new projects)
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DWOLFSSL_SMALL_CERT_VERIFY=OFF
make
make install
Update Verification Callback Logic
Before (vulnerable):
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
int err = X509_STORE_CTX_get_error(ctx);
// Dangerous: Overrides date errors
if (err == ASN_BEFORE_DATE_E || err == ASN_AFTER_DATE_E) {
fprintf(stderr, "Warning: Certificate date invalid, accepting anyway
");
return 1;
}
return preverify_ok;
}
After (secure):
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
int err = X509_STORE_CTX_get_error(ctx);
// Log the error but do not override
if (err != 0) {
fprintf(stderr, "Certificate verification failed: %d
", err);
return 0; // Reject the certificate
}
return preverify_ok;
}
If date override is genuinely required (rare):
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
int err = X509_STORE_CTX_get_error(ctx);
// ONLY override date errors, NEVER ignore signature failures
if (err == ASN_BEFORE_DATE_E || err == ASN_AFTER_DATE_E) {
// Verify that signature verification succeeded
// (This is a workaround; proper fix is to recompile without WOLFSSL_SMALL_CERT_VERIFY)
fprintf(stderr, "Warning: Date error detected, but signature verified
");
return 1;
}
// Reject all other errors
return preverify_ok;
}
Clear Cached Certificates Safely
Identify certificate manager contexts:
// Find all WOLFSSL_CTX instances in your codebase
WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
// After handling potentially malicious connections:
// Option 1: Destroy and recreate the context
wolfSSL_CTX_free(ctx);
ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
// Option 2: Clear the certificate manager (if available)
// Note: wolfSSL does not provide a direct "clear cache" function
// Restart the context or process
Process-level remediation:
#!/bin/bash
# Restart application to clear all cached certificates
systemctl restart myapp
# Or for containerized deployments
docker restart myapp-container
Testing & Validation
Step 1: Verify recompilation
# Confirm WOLFSSL_SMALL_CERT_VERIFY is not present
strings libwolfssl.a | grep -c "WOLFSSL_SMALL_CERT_VERIFY"
# Should output: 0
# Confirm callback is updated
grep -n "ASN_BEFORE_DATE_E.*return 1" src/verify.c
# Should output: (no results)
Step 2: Test with expired certificate
# Generate a test certificate with past validity dates
openssl req -x509 -newkey rsa:2048 -keyout test.key -out test.crt \
-days -365 -nodes -subj "/CN=test.example.com"
# Attempt TLS connection with patched wolfSSL
# Should FAIL with certificate verification error
Step 3: Regression testing
# Run wolfSSL test suite
cd wolfssl
./configure
make
make test
# Verify all tests pass
Deployment Considerations
Low-Resource Device Trade-Offs
If you cannot recompile without WOLFSSL_SMALL_CERT_VERIFY:
- Evaluate memory constraints: Measure actual peak memory usage with standard build
# Monitor memory during TLS handshake
valgrind --tool=massif ./your_app
- Consider alternative optimizations:
- Increase available RAM
- Use hardware acceleration (if available)
- Implement certificate pinning to reduce verification overhead
- Use session resumption to reduce handshake frequency
- Implement compensating controls:
- Restrict TLS connections to known, trusted servers only
- Use mutual TLS (mTLS) with client certificates
- Implement certificate pinning
- Monitor for unexpected certificate changes
Callback Pattern Best Practices
Secure callback template:
int secure_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
int err = X509_STORE_CTX_get_error(ctx);
int depth = X509_STORE_CTX_get_error_depth(ctx);
X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
// Log all verification events
char subject[256];
X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject));
fprintf(stderr, "Cert verification: depth=%d, subject=%s, error=%d, preverify=%d
",
depth, subject, err, preverify_ok);
// NEVER override signature failures
if (err == ASN_SIG_CONFIRM_E) {
fprintf(stderr, "CRITICAL: Signature verification failed
");
return 0;
}
// NEVER override critical extension failures
if (err == ASN_CRITICAL_EXT_E) {
fprintf(stderr, "CRITICAL: Critical extension validation failed
");
return 0;
}
// Date errors should typically be rejected
if (err == ASN_BEFORE_DATE_E || err == ASN_AFTER_DATE_E) {
fprintf(stderr, "ERROR: Certificate date validation failed
");
return 0; // Reject
}
// Return preverify result for other errors
return preverify_ok;
}
Context Restart Requirements
Implement graceful context restart:
typedef struct {
WOLFSSL_CTX *ctx;
pthread_mutex_t lock;
} AppContext;
void restart_wolfssl_context(AppContext *app) {
pthread_mutex_lock(&app->lock);
if (app->ctx != NULL) {
wolfSSL_CTX_free(app->ctx);
}
app->ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
if (app->ctx == NULL) {
fprintf(stderr, "Failed to create new wolfSSL context
");
pthread_mutex_unlock(&app->lock);
return;
}
// Reconfigure context (certs, callbacks, etc.)
wolfSSL_CTX_set_verify(app->ctx, WOLFSSL_VERIFY_PEER, secure_verify_callback);
pthread_mutex_unlock(&app->lock);
}
FAQs
Is wolfSSL vulnerable by default?
No. WOLFSSL_SMALL_CERT_VERIFY is disabled by default. The vulnerability only exists when:
- Binary is explicitly compiled with
--enable-lowresource,--enable-leantls, or--enable-tinytls13=* - Application registers a callback that overrides date errors
Standard builds are not vulnerable.
What callback behavior triggers the vulnerability?
The vulnerability requires a callback that:
- Is registered via
wolfSSL_CTX_set_verify()orwolfSSL_set_verify()withWOLFSSL_VERIFY_PEER - Returns
1(accept) when encounteringASN_BEFORE_DATE_EorASN_AFTER_DATE_E
Callbacks that return 0 (reject) on date errors are safe.
Can an attacker exploit this without a stolen CA key?
Yes, absolutely. This is a fundamental difference from traditional certificate forgery. Attackers need:
- Network position to intercept TLS traffic
- Ability to craft X.509 certificates (trivial with OpenSSL)
They do not need:
- CA private key
- Stolen certificates
- Compromised infrastructure
Does closing a TLS connection clear forged certificates from memory?
No. If a forged certificate is cached in the WOLFSSL_CTX certificate manager, closing the TLS connection does not clear it. The context persists the cached certificate.
Remediation: Restart the WOLFSSL_CTX context or restart the entire application process.
Which TLS versions are affected?
All versions are affected:
- TLS 1.2 ✓ Vulnerable
- TLS 1.3 ✓ Vulnerable
- DTLS 1.2 ✓ Vulnerable
How do I know if my build includes WOLFSSLSMALLCERT_VERIFY?
Method 1: Check build flags
grep "enable-lowresource\|enable-leantls\|enable-tinytls13" build.log
Method 2: Check binary
strings libwolfssl.a | grep "WOLFSSL_SMALL_CERT_VERIFY"
Method 3: Check source configuration
grep "WC_CFG_SMALL_CERT_VERIFY\|WOLFSSL_SMALL_CERT_VERIFY" user_settings*.h
What’s the difference between this vulnerability and standard certificate validation failures?
Standard certificate validation failures:
- Signature verification fails → certificate rejected ✓ Correct behavior
- Date validation fails → certificate rejected ✓ Correct behavior
CVE-2026-94418:
- Signature verification fails BUT is masked by date error
- Date error is reported to callback
- Callback overrides date error
- Signature failure is never reported
- Certificate is accepted despite invalid signature ✗ Incorrect behavior
Can I safely override date errors in my callback?
No, not with WOLFSSL_SMALL_CERT_VERIFY enabled. Overriding date errors masks signature verification failures.
Safe alternatives:
- Recompile without
WOLFSSL_SMALL_CERT_VERIFY(recommended) - Use certificate pinning to reduce reliance on date validation
- Implement strict callback logic that never overrides errors
- Use mutual TLS with client certificates for additional authentication
References
- CVE Identifier: CVE-2026-94418
- Affected Component: wolfSSL Embedded TLS Library
- Vulnerable Functions:
ProcessPeerCertParse(),ParseCertRelative(),ConfirmSignature() - Build Macros:
WOLFSSL_SMALL_CERT_VERIFY,WC_CFG_SMALL_CERT_VERIFY - Autotools Flags:
--enable-lowresource,--enable-leantls,--enable-tinytls13 - Test References:
wolfssl/test.h(VERIFY_OVERRIDE_DATE_ERR,myVerify()) - Configuration Files:
examples/configs/user_settings_embedded.h
Article Type: CVE Analysis
Submenu: IT Security
Menu: TECH OPS
Last Updated: 2026
Status: Published