Client and context
A US financial-services business with a long trading history, a national footprint and a website that had grown with it for over a decade. The engagement came by referral from another client.
It began as an informal favour. Look at the website, they said, and see what could be done.
The problem
The site was a large, ageing WordPress build carrying a decade of real substance: hundreds of articles, genuine testimonials, a credentialled team, working lead magnets. All of it wrapped in something that undersold the operation.
The obvious commercial move was to propose a rebuild. That was not the right answer, and saying so was most of the value.
What we did
A full review of the site as it actually stood, not as it appeared on the homepage. The site was mirrored in full and examined page by page: 1,029 pages and 2,936 files.
That surfaced the sort of thing nobody notices from the inside. A services page still leading with a tax offer for a year that had already passed. A content-management placeholder, never replaced, sitting under a team member’s biography. A duplicated word in the homepage title tag, which is the strongest single statement a page makes about what it is, and usually, though not always, the headline a search engine shows for it. And 790 references across the site still pointing at the staging server rather than the live one.
That last one is worth dwelling on, because it is a good illustration of what an audit is for. 790 broken references sounds like weeks of remediation. In fact 755 of them, 95.6%, came from two links in shared page furniture. Two template edits by the client’s administrator and one serialisation-safe search and replace across the database cleared almost all of it. The naive version of that command silently corrupts serialised data, which is the sort of thing worth knowing before you run it. The job of an audit is to find out how small the work actually is, not to make it sound large.
A security review, which is where the engagement earned its keep.
It found a code-injection flaw in a form plugin rated 9.8 out of 10 for severity: no login required, arbitrary code execution, and being actively exploited in the wild at the time. On a site that collects personal and financial information from the public.
Finding it was the straightforward part. It was flagged as urgent and it took repeated asking before the plugin was disabled. Once it was, the fix was verified rather than assumed: the vulnerable endpoints were probed again and confirmed to be returning nothing, alongside a made-up control request to prove the test itself was sound.
That establishes the hole is shut. It does not establish that nobody walked through it while it was open, which is a separate piece of work: administrator accounts, file modification dates, scheduled tasks, outbound connections, and a support case raised with the platform. That was recommended in writing, and raised more than once.
The broader finding was the plugin estate. A long-lived WordPress site accumulates plugins the way a workshop accumulates tools, and every one is attack surface whether or not anybody still uses it. Several were installed and active with no evident purpose. One had been abandoned by its author years earlier, carried four unpatched vulnerabilities, and had no update path in existence, which meant removal was the only available remediation. That finding corrected earlier advice, in writing.
Email authentication that was failing silently. The domain’s SPF record had accumulated senders across years of CRM and marketing platforms arriving and departing. RFC 7208 caps the number of mechanisms in a record that trigger DNS lookups at ten, and it counts nested ones: an include that itself contains includes costs more than one. Eight lookup-costing senders remained, two of which nested four further records between them. Twelve against a limit of ten.
Past that limit the check must return PermError. That is not a strictness setting on the receiving end, it is what the specification requires. PermError is not a pass, so anything relying on SPF alignment fails, and what a receiver chooses to do beyond that is its own local policy. The record existed, looked plausible, and authenticated nobody, including the organisation’s own mail. An authorised, controlled test confirmed a forged message from the domain could be delivered.
SPF was only ever a third of the problem. DKIM had to be inventoried for every genuine sender, and DMARC published in monitoring mode first, because aggregate reports are the only way to prove a sender list is complete rather than assume it.
The fix was a sequence rather than an edit: establish which senders were genuinely still in use, remove the rest, keep the record on soft-fail until the sender list was proven complete, and only then tighten. Doing it the other way round is how an organisation takes its own mail offline.
A recommendation not to rebuild. The site had real problems, and the commercially obvious answer was to propose replacing it. The argument against was search.
URLs can be preserved through a rebuild, and anyone arguing otherwise is arguing badly. The costs that cannot be waved away are different: a thousand-odd addresses to map one for one and verify, every one of them a single hop; gated lead magnets and forms to rebuild and re-test; and a re-crawl of the whole estate, during which positions move before they settle. Everything actually wrong with this site was fixable in place, at a fraction of that.
Outcome
The critical vulnerability was closed. Email authentication was put on a repair path. The audit was independently checked against the live site by the client’s own reviewer before any of it was acted on, and it held up.
And the engagement ended, which is the part worth being straight about.
This was advisory work without hands-on access: every finding depended on somebody else carrying it out. That arrangement works when each action has a clear owner and a clear report back. Here it did not settle into that, and after a few cycles it was no longer possible to say with confidence which recommendations had been implemented.
1NM does not put its name to outcomes it cannot influence. So rather than continue and invoice for advice with no way of knowing whether it landed, we said so.
And then wrote the plan for carrying on without us. Leaving quietly would have been easier and considerably less useful. Instead the final deliverable was a governance pack: a responsibility matrix naming an owner and an approver for every workstream, an operating rhythm setting out what needs checking monthly, quarterly and annually, a one-page template for recording those checks, a recommendation to subscribe to out-of-band vulnerability alerts for the platform in use, and a prioritised sequence for the work still outstanding.
The point of that pack is that it does not depend on us. It is written so the client’s own people, or whoever they appoint next, can pick up the remaining work in the right order and know who is accountable for each piece.
That is not a happy ending, but it is an honest one, and it is the reason this is on the site. An audit is worth buying precisely because it will tell you things you did not want to hear, including that you do not need the expensive thing, and occasionally that the person doing the audit is not the right person for the next stage.
Stack used
Full-site mirroring and automated link analysis, WordPress and plugin vulnerability assessment, DNS and email authentication testing, TLS and security header review. Findings delivered as written reports with a prioritised remediation sequence and a governance handover.
This engagement is evidence for Security & Compliance.
Also in the record: Bailey's Sweeper Service, Creative Freight.
Start a conversation