Certificate Pinning in 2025: The Dangerous Balancing Act Between Security and Self-Inflicted DDoS
In the world of application security, few mechanisms are as polarizing as certificate pinning. On paper, it is the ultimate defense against Man-in-the-Middle (MitM) attacks, ensuring your application talks only to your server and never to an imposter—even one wielding a valid certificate from a compromised Certificate Authority (CA).
However, in the operational trenches of 2025, certificate pinning has earned a reputation as a "double-edged sword." For every attack it prevents, it likely causes ten self-inflicted outages. With the industry moving aggressively toward 90-day certificate lifespans and automated rotation, the friction between strict pinning and crypto-agility has never been higher.
If you are a DevOps engineer or security architect, you are likely facing a difficult question: Is the security benefit of pinning worth the operational risk of bricking your application?
This guide explores the modern state of certificate pinning, how the push for shorter certificate validity impacts your strategy, and how to implement pinning without causing a catastrophic "Denial of Service" against your own users.
The "90-Day Validity" Earthquake
To understand why pinning is so dangerous right now, we have to look at the shifting landscape of TLS/SSL management.
Historically, certificates were valid for years. You could hardcode a certificate into a mobile app, release the app, and not worry about it for a long time. Today, that luxury is gone. Major browser vendors and Certificate Authorities, led by Google, are pushing to reduce the maximum TLS certificate validity to 90 days.
This shift is driven by security—shorter lifespans mean compromised keys are valuable for less time—but it creates a logistical nightmare for pinning.
The Mobile Update Lag
Consider this scenario:
1. You pin your server's leaf certificate inside your iOS app.
2. Your server's certificate expires in 80 days.
3. You renew the certificate on the server.
4. The Crisis: Every user who hasn't updated their app via the App Store now has a "bricked" application. The app rejects the new valid certificate because it doesn't match the old hardcoded pin.
In the web world, you can update code instantly. In the mobile and IoT world, you are at the mercy of user behavior and App Store review times. If you are not careful, the "90-day cliff" becomes a recurring operational crisis.
The Core Conflict: Security vs. Operations
Before implementing pinning, you must define your threat model. Pinning is designed to stop one specific, high-severity threat: A Compromised Certificate Authority.
If a hacker compromises a root CA (or an intermediate), they can issue a valid certificate for api.yourdomain.com. To a standard client, this fake certificate looks perfectly legitimate. Pinning stops this by telling the client, "I don't care if the CA says this is valid; if the public key doesn't match X, terminate the connection."
The Operational "Suicide Note"
The downside is what industry veterans call the "Suicide Note." If you lose your private key, or if you rotate your keys without updating the app's pinset, you effectively DDoS yourself.
Furthermore, pinning often breaks legitimate corporate environments. Many enterprises use Deep Packet Inspection (DPI) tools like Zscaler or BlueCoat to inspect traffic for malware. These tools act as a "benevolent MitM," re-signing traffic with a corporate root CA. If your app uses strict pinning, it will reject the corporate proxy, meaning your app simply won't work on enterprise Wi-Fi networks.
Technical Implementation: How to Pin Correctly in 2025
If you determine that your application requires this level of security (common in Fintech, Healthcare, and Banking), you must implement it in a way that survives the 90-day rotation cycle.
1. Never Pin the Leaf Certificate
Pinning the exact leaf certificate is a relic of the past. It forces you to update your app binary every time you renew your certificate.
The Solution: Pin the Subject Public Key Info (SPKI).
Instead of pinning the certificate file, you pin the SHA-256 hash of the Public Key. This allows you to renew your certificate repeatedly using the same Certificate Signing Request (CSR) and private key. The certificate changes, the expiration date changes, but the public key (and its hash) remains the same.
2. The "Backup Pin" Rule
This is the single most critical rule of pinning: Never deploy a single pin.
You must always include at least two pins:
1. The Active Pin: The hash of the key currently in use.
2. The Backup Pin: The hash of a key pair that you generated, saved to an encrypted USB drive, and locked in a physical safe (cold storage).
If your active server key is compromised or lost, you can pull the backup key out of the safe, install it on your server, and your app will continue to work without an update.
3. Implementation on Android (Network Security Config)
Modern Android (API 24+) makes pinning declarative and safer using the network_security_config.xml. You don't need to write complex Java/Kotlin code.
Create a file at res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">api.expiring.at</domain>
<pin-set expiration="2025-12-31">
<!-- Active Pin (Subject Public Key Info) -->
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
<!-- Backup Pin (Cold Storage) -->
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldWDURappCnOgQWo3Wp0=</pin>
</pin-set>
</domain-config>
</network-security-config>
Note the expiration attribute: This is a failsafe. If you screw up the pins, the app will stop enforcing pinning after this date, preventing the app from being bricked forever on older devices.
4. Implementation on iOS
iOS relies on App Transport Security (ATS) or third-party libraries like TrustKit, which is widely considered the gold standard for iOS pinning. TrustKit handles the validation logic and, crucially, provides reporting features.
let trustKitConfig = [
kTSKSwizzleNetworkDelegates: false,
kTSKPinnedDomains: [
"api.expiring.at": [
kTSKEnforcePinning: true,
kTSKIncludeSubdomains: true,
kTSKPublicKeyAlgorithms: [kTSKAlgorithmRsa2048],
kTSKPublicKeyHashes: [
"7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=", // Active
"fwza0LRMXouZHRC8Ei+4PyuldWDURappCnOgQWo3Wp0=" // Backup
]
]
]
]
TrustKit.initSharedInstance(withConfiguration: trustKitConfig)
The "Soft Fail" Strategy: Look Before You Leap
The biggest mistake teams make is turning on "Hard Fail" (blocking connections) immediately. You have no idea how many of your users are behind corporate firewalls or weird ISP proxies that will trigger a failure.
Phase 1: Report-Only Mode
For the first 1-2 months, configure your pinning library (like TrustKit) to notify but not block.
* The app validates the pin.
* If validation fails, the connection is allowed to proceed.
* The app silently sends a report to your backend logs.
Analyze these logs. If you see a 5% failure rate coming from legitimate users (e.g., users on "CorporateGuest" Wi-Fi), you know that enabling hard pinning will drop 5% of your traffic. You can then decide if that business loss is acceptable for the security gain.
Modern Alternatives to Pinning
If the operational overhead of pinning sounds too high for your team, you are not alone. Many organizations are moving away from pinning in favor of Certificate Transparency (CT) Monitoring.
CT Monitoring vs. Pinning
- Pinning (Proactive): Blocks the connection. Prevents the attack but risks outages.
- CT Monitoring (Reactive): Allows the connection but alerts you immediately if a rogue certificate is issued.
With tools like Facebook Certificate Transparency Monitoring or Expiring.at, you can be alerted the moment a CA issues a certificate for your domain. While this doesn't stop the initial connection, it allows security teams to revoke the rogue cert and respond within minutes, rather than months.
For most non-banking applications, CT Monitoring combined with CAA (Certification Authority Authorization) DNS records provides a sufficient level of security without the risk of breaking the application.
Best Practices Checklist for 2025
If you decide to proceed with pinning, follow this checklist to ensure you don't wake up to a production outage:
- Pin SPKI, not Certs: Ensure your rotation strategy reuses private keys or that you have a mechanism to push new pins dynamically.
- Automate Expiration Tracking: With 90-day lifespans, you cannot rely on calendar reminders. Use a tool like Expiring.at to monitor the validity of your endpoints. If a server cert rotates unexpectedly, you need to know immediately to verify it matches your pinned keys.
- Establish a "Break Glass" Procedure: Document exactly how to retrieve the backup key from cold storage and deploy it to your load balancers.
- Handle Corporate Proxies: Decide if you will allow "User Installed CAs" (common in MDM environments) to bypass pinning. In Android, this is done via
<certificates src="user" overridePins="true" />. - Monitor Your Pins: Treat your pin expiration just like your certificate expiration. If your pinned key is set to expire (or the algorithm is being deprecated), you need a migration plan months in advance.
Conclusion
Certificate pinning remains a powerful tool in the security engineer's arsenal, but in the era of 90-day certificates and automated DevOps, it requires a sophisticated operational approach. The days of "set it and forget it" are over.
By pinning public keys instead of certificates, maintaining offline backups, and utilizing "soft fail" reporting periods, you can achieve a high security posture without sacrificing availability. However, always ask yourself: does the risk of a compromised CA outweigh the risk of a self-inflicted outage? In 2025, for many, the answer is shifting toward robust monitoring rather than rigid blocking.
Ensure your certificates—and your peace of mind—never expire unexpectedly. Check out Expiring.at for comprehensive monitoring solutions tailored for modern DevOps teams.