DEV Community

SPF record hygiene: the security debt nobody logs

Nobody opens a ticket for an SPF record. There is no alert, no dashboard turning red, no user calling to say that an IP address from a provider the company stopped paying two years ago is still authorized to send email on its behalf. That is exactly what makes it dangerous. I audited the SPF record of a mid-sized manufacturing company in Brazil and found authorized senders that had not been part of the environment for years. Nothing was broken. Email was flowing normally. And that is the point - a bloated SPF record does not fail loudly. It fails quietly, on the day someone decides to use it. The problem The company had migrated its email to Microsoft 365. The migration itself went fine - mailboxes moved, mail flow worked, users were happy, project closed. What nobody revisited was DNS. The SPF record still authorized the IP ranges of the previous email security provider, alongside the current include:spf.protection.outlook.com. Those ranges had been left in place when the provider was decommissioned, and nothing in the environment depended on them anymore. The record said, in effect: these servers are allowed to send email as us. And they were no longer under our control. Two concrete risks come out of that: Spoofing surface. An SPF record is an authorization list. If infrastructure you no longer control is still on it, and that infrastructure is ever repurposed, resold, or compromised, mail from it passes SPF authentication as your domain. Receiving servers will trust it, because you told them to. The 10-lookup limit. SPF allows a maximum of 10 DNS lookups when evaluating a record. Mechanisms like include, a, mx, ptr and redirect each consume from that budget, and nested includes count too. Cross the limit and the evaluation returns permerror - which many receivers treat as a failed check. Legacy entries do not just sit there harmlessly; they consume a budget you may need the next time a business team adopts a new platform. The constraints This is the part that shapes every decision: No dedicated email security team. Infrastructure, networking, endpoints, physical security and email all sit with the same small team. No budget for a specialized deliverability platform. Everything had to be done with DNS tooling, message headers, and what Microsoft 365 already provides. Zero tolerance for downtime. This is a manufacturing operation. If a purchase order confirmation or a logistics notification stops being delivered, it is not an IT inconvenience - it is a production problem. Incomplete institutional knowledge. The people involved in the original configuration were no longer around, and there was no change log. That last constraint is the real one. It is easy to write "remove what you do not need." It is much harder to prove something is not needed when nobody remembers what it was for. What I ruled out Deleting everything and rebuilding from scratch. Fastest, and by far the worst idea. Any legitimate sender I did not know about would start failing SPF immediately, and I would only find out through a broken business process - probably at the worst possible time. Publishing a permissive record as a safety net. Loosening the policy to avoid breaking senders would defeat the entire purpose. The goal was to reduce spoofing surface, not to formalize it. Trusting documentation. There was none worth trusting. Whatever list I produced had to come from observed traffic, not from a wiki page. Assuming the SPF record was the whole story. SPF only validates the envelope sender. It says nothing about the visible From: header a user actually sees. SPF alone was never going to be the finish line. What I did - Snapshot the current state. Query the record and read it as an authorization list, mechanism by mechanism. bash dig +short TXT example.com | grep spf1 nslookup -type=txt example.com Then count the DNS lookups actually consumed, including nested includes. This is where most records are quietly over budget without anyone knowing. - Build an inventory of real senders. Not who should be sending, but who is sending. Message headers and Microsoft 365 message trace were the source of truth here - every system that legitimately sends mail as the domain: the mail platform itself, ERP notifications, monitoring alerts, scanners and multifunction devices, and any third-party tool business teams had signed up for without telling IT. That last category is always the surprise. Marketing and HR sign up for platforms that send on the company's behalf, and IT finds out only when something breaks. Classify every existing entry. Three buckets: confirmed in use, confirmed obsolete, unknown. The unknown bucket is where the work is - each entry has to be traced back to an actual sending system or written off. Enable DMARC in monitoring mode before touching anything. v=DMARC1; p=none; rua=mailto:dma**********@example.com p=none enforces nothing. It simply asks receiving servers to report what they are seeing - which sources are sending as the domain, at what volume, and whether they are passing authentication, including sources that never appear in message trace because they are not yours. This is the step people skip, and the one that turns guesswork into evidence. Remove obsolete entries, one change at a time. The legacy provider ranges came out first, since those were unambiguous. Each change was made individually, with observation time in between. Lowering the record's TTL beforehand meant a mistake could be rolled back in minutes instead of hours. Tighten the policy only after the record is clean. Moving toward a strict fail policy makes sense only once you are confident every legitimate sender is authorized. Doing it earlier is how you end up rolling back under pressure. The result Legacy provider IP ranges removed from the authorized sender list. DNS lookup consumption reduced, restoring headroom under the 10-lookup limit. A documented inventory of legitimate senders - which had never existed. No delivery incidents during the process. I want to be honest about the size of this win. It is not dramatic. Nothing was on fire before and nothing is faster now. What changed is that the domain stopped extending trust to infrastructure the company no longer controls - and the next person to touch this record will have a list to work from instead of archaeology to perform. What I would do differently DNS belongs on the migration checklist, not in the backlog. The migration was considered complete when mail flowed. It should not have been considered complete until DNS reflected only the new reality. Decommissioning a provider means decommissioning its authorizations too. Start with DMARC monitoring, before even reading the SPF record. Aggregate reports give you a full picture of who is sending as your domain, including sources that never show up in message trace. Reading the record first tells you what someone once authorized; reading the reports tells you what is actually happening. Documenting sending systems is not optional. The reason this took as long as it did is that nobody wrote down what was added, when, or why. The inventory is now the most valuable artifact from the whole exercise - more valuable than the cleaned record itself, because records drift again, and the inventory is what makes the next cleanup a task instead of an investigation. If you have inherited an email environment, go read your SPF record right now. Not because something is broken - because you probably do not know what is in it. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.