Ten security-hygiene gaps we see on almost every UK small-business website — and how to fix them

By Stu Last

← Back to Articles

As part of our IT security, software and compliance consultancy work in Cornwall, Spyced Concepts regularly runs external surface scans on the websites of local businesses. These are passive checks — we read what a browser sees, look up public DNS records, and note what the site returns in its response headers. Nothing intrusive; just the same information a determined attacker has for free, before they choose their target.

Ten patterns come up on almost every scan we run. All ten are fixable — some in ten minutes, some in an afternoon, and a few worth a working day of considered effort. All ten are things a competent hosting provider or web developer will do without being asked; all ten are things that get missed because they never quite become someone's specific job. Here they are.

1. Weak or absent DMARC — your domain can be trivially spoofed

DMARC is a small DNS record that tells email servers what to do when someone tries to send email pretending to be from your domain. The policy is one of p=none (do nothing, just watch), p=quarantine (put suspicious mail in spam), or p=reject (block outright). A rua= field tells receiving servers where to send daily reports on who is trying to spoof you.

What we see. Most small-business domains have DMARC set to p=none with no rua= reporting, or no DMARC record at all. Anyone can send email From: yourname@yourdomain.co.uk to your customers and it will land without a warning. You will never know it happened.

Why it matters. Business email compromise (BEC) and impersonation phishing are consistently among the highest-loss fraud categories reported to UK Action Fraud [1]. A weak DMARC record is what makes that easy.

Fix. Publish a DMARC record with reporting on: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.co.uk;. Watch the reports for a few weeks, confirm nothing legitimate is failing alignment, then tighten to p=quarantine and eventually p=reject. Global Cyber Alliance runs a free step-by-step configurator: dmarcguide.globalcyberalliance.org. NCSC guidance: ncsc.gov.uk/guidance/email-security-and-anti-spoofing.

2. Outdated WordPress core, plugins or theme

For sites running WordPress — still the majority of small-business sites — outdated versions of the core, plugins, or theme are consistently reported as the leading route into a compromised small site [2].

What we see. Sites frozen on a version of WordPress from three or four years ago, still loading a Contact Form 7 build that has a known exploit history, running a theme last updated when Brexit was fresh news.

Why it matters. Every widely-used WordPress plugin has a maintainer whose account can be compromised or whose plugin can be sold to a bad actor. Every unpatched version is a ticket to a known-bad exploit. This is the mundane, unglamorous end of website compromise, and it is the reason most small-site compromises actually happen.

Fix. Update everything — core, plugins, theme — on a staging copy first, then push to production. If a plugin has not been updated in over a year, replace it or remove it. If your site is effectively dormant and you cannot commit to maintaining it, take it offline and put a static holding page in place. WordPress and its plugin ecosystem reward attention; punish neglect.

3. An SPF record that does not match your actual senders

SPF is another DNS record — it lists which mail servers are authorised to send email as your domain. It works alongside DMARC: DMARC tells receivers what to do with unauthorised mail; SPF tells them who is authorised in the first place.

What we see.Two common variants — (a) an SPF record that authorises HubSpot or Mailchimp but not the Google Workspace or Microsoft 365 account you actually use, so your own staff's email fails alignment on strict receivers; or (b) an SPF that still authorises the on-premises mail server you decommissioned three years ago, which now belongs to whoever repurposed the IP.

Why it matters. Case (a) hurts your deliverability — legitimate mail from your team goes to spam. Case (b) is worse — a repurposed IP still on your SPF is a spoofing vector any attacker can use.

Fix.Audit your SPF against what you actually send from today. Remove decommissioned servers. Add the M365 or Google Workspace include if it is missing. Google's SPF setup guide: support.google.com/a/answer/33786.

4. Missing Content-Security-Policy header — your XSS defence-in-depth is off

Content-Security-Policy (CSP) is a response header your web server sends with every page. It tells the browser exactly which sources of scripts, styles, fonts, and other content are allowed. If a bad actor manages to inject a malicious <script> tag through a compromised plugin, a reused admin password, or a supply-chain attack on a JavaScript dependency, the browser refuses to run it.

What we see. Almost every small-business site we scan has no CSP header at all, or a placeholder value (Content-Security-Policy: upgrade-insecure-requests and nothing else) that looks like a CSP but does not constrain script sources.

Why it matters. CSP is defence-in-depth. If nothing else fails, you do not need it. But everything else does fail sometimes.

Fix. Deploy a report-only CSP first (Content-Security-Policy-Report-Only), watch the reports for a week, refine the policy until the reports come back clean, then switch to enforcing. OWASP CSP Cheat Sheet: cheatsheetseries.owasp.org. MDN reference: developer.mozilla.org/en-US/docs/Web/HTTP/CSP.

5. Legacy tracking scripts still loading — GDPR grey area, dead code, expanded attack surface

What we see. Sites still loading Google Universal Analytics — the tracking tag Google switched off in July 2023 [3]. Sites hot-linking Google Fonts directly from fonts.googleapis.com. Sites embedding Facebook Pixel or a chat widget that has not been updated since 2020.

Why it matters.Universal Analytics stopped collecting data years ago — those tags are dead code doing nothing useful. Hot-linking Google Fonts leaks every visitor's IP address to Google, which is at best a UK GDPR grey area — a German court ruled it a Data Protection Regulation breach in 2022 [4]. And every third-party script you embed is another supply-chain attack surface: the maintainer's account can be compromised, the domain can be sold, the vendor can pivot to malware.

Fix. Audit every third-party script on your site. Remove anything that no longer serves a purpose. Self-host web fonts. If you need analytics, migrate to a GDPR-friendly alternative — Plausible, Fathom, or Matomo (self-hosted or EU-hosted).

6. Missing standard hardening headers — X-Frame-Options, X-Content-Type-Options, Permissions-Policy, Referrer-Policy

Four small HTTP response headers together add up to a meaningful hardening layer:

  • X-Frame-Options: DENYprevents your site being loaded inside another site's <iframe> (clickjacking defence).
  • X-Content-Type-Options: nosniff stops the browser guessing at content types (MIME-sniffing attacks).
  • Permissions-Policy lets you disable browser features you do not use (microphone, camera, geolocation, and so on).
  • Referrer-Policy: strict-origin-when-cross-origin controls what URL data is sent to the sites your visitors click through to.

What we see. Some sites set one or two of these; almost none set all four.

Why it matters. Each one is a small defence, and none of them is expensive to configure. Between them, they close a class of low-effort attacks that automated scanners still probe for.

Fix. Set all four at your web-server, CDN or CMS-template layer. OWASP Secure Headers Project has the canonical reference: owasp.org/www-project-secure-headers. Self-audit your current state at securityheaders.com.

7. HSTS misconfigured — short max-age or absent

HSTS (Strict-Transport-Security) is the header that tells the browser “only ever visit me over HTTPS, for the next N seconds, and remember that”. It closes the downgrade-attack window where a first-time visitor can be silently redirected to plain HTTP.

What we see. Some sites have HSTS set to max-age=2592000 (30 days), which is short — a visitor who does not return within 30 days loses the guarantee. Others have no HSTS at all.

Why it matters. The whole value of HSTS is that it persists. A short max-age is worth less than industry practice suggests, and its absence on a site handling any customer data or logins is a real gap.

Fix. Set Strict-Transport-Security: max-age=31536000; includeSubDomains; preload. That is one year, subdomains covered, and opts into browsers' preload lists. Details and preload submission: hstspreload.org.

8. CMS version disclosed via generator meta tag or readme.html

What we see. WordPress sites carrying <meta name="generator" content="WordPress 6.4.3"> in the HTML head, or leaving /readme.html (which ships with WordPress and discloses the version) publicly accessible.

Why it matters. An attacker choosing targets automates this: fetch the site, extract the version, look up CVEs for that version, decide whether to spend effort. Suppressing the version disclosure does not make you safer — the vulnerabilities remain — but it does move you out of the low-effort target set.

Fix. Suppress the generator meta tag (most themes have a filter for this, or add one line to functions.php). Restrict access to /readme.html, /license.txt, and similar disclosure files at the web-server layer or via a plugin such as WPS Hide Login. Consider a WordPress-hardening plugin (iThemes Security, Wordfence, or similar) that closes several of these disclosures at once.

9. Statutory trading disclosures missing from the website — a UK-legal compliance gap

What we see. UK-registered limited companies whose websites do not display their registered name (with Limited), company number, place of registration, or registered office address. This is not a security issue; it is a legal compliance issue.

Why it matters. Section 82 of the Companies Act 2006 [5] empowers regulations requiring companies to disclose their registered particulars in specified places. The Companies (Trading Disclosures) Regulations 2008[6] implement that duty on business letters, order forms, and websites. Failure is a criminal offence under section 84, prosecutable against the company and every officer in default. Enforcement is rare in practice, but a Companies House complaint or an alert client's compliance function can turn a rare risk into a real one.

Fix. Add a two-line footer to your site displaying: registered name in full (Your Company Limited), company number, place of registration (England and Wales, Scotland, or Northern Ireland), and registered office address. One CMS footer edit covers the site.

10. No /.well-known/security.txt — no clear route for a researcher to report a vulnerability

security.txt (RFC 9116 [7]) is a short file you place at https://yourdomain.co.uk/.well-known/security.txt. It tells any security researcher who spots a problem how to reach you: a Contact: line, an Expires: date, and optionally Preferred-Languages:.

What we see. Almost none of the small-business sites we scan publish one. Of the few that do, many have let the Expires: date lapse, which by RFC 9116 makes the file invalid — arguably worse than not having one.

Why it matters. When a security researcher finds a real vulnerability on your site, they need to be able to tell you. Without a security.txt their options are: give up, guess at an inbox you may not read, or post about it publicly. None of that is what you want.

Fix. Go to securitytxt.org — the official RFC 9116 site — and use the built-in generator. Upload the resulting file to /.well-known/security.txt. Set a calendar reminder to renew the Expires: date every 12 months. Ten minutes, plus the standing reminder.

The pattern behind the ten symptoms

Ten items above. Ten specific technical fixes. Every one of them a one-off remediation somebody can implement in an afternoon.

Look at the list as a set and a different picture emerges. Every item is something that would have been part of a properly-scoped build if security had been considered at the same time as the feature list — not something a competent developer failed to know about, but something that never made it onto the ticket because it was invisible and its cost was borne later.

That is the habit under all ten: security treated as an afterthought and an inconvenience, rather than baked into the development lifecycle from the start.

This is not a criticism of any individual developer or hosting provider. Small-business web work runs on tight budgets and tight timelines; security features get skipped because they are invisible until something breaks, and by the time something breaks the developer has usually moved on to the next project. The result is the same across almost every site we scan — small businesses, mid-sized SaaS, security-adjacent suppliers alike: technically-competent people delivered a technically-competent product, and the security hygiene was left as a retrofit that never happened.

The way out is not to fix these ten items and stop scanning. It is to change the point at which security enters the conversation. If you work with a developer or agency, ask them to add a security acceptance criterion to every feature ticket you sign off. If you run your own site, pick a hosting provider whose defaults are secure and whose CMS updates itself. Both approaches move security from afterthought to default — and every one of the ten items above stops being a scan finding worth writing about.

Senior technology expertise —
security-first, AI-aware.

From architecture and outsourced development to compliance, AI integration, and tooling setup — Spyced Concepts delivers senior-level expertise across the full stack.

Get in touch