Skip to content
WebInsights

Security on a public site: what you actually have to own

A public site is a door. The plugin in the corner is not the lock.

Website security is not a plugin. It is headers, updates, secrets, and the admin window you forgot to close.

11 min read
Stylised browser window with performance graphs and a clear padlock layer in front of a public site.

Web & operations

If you are searching for website security or WordPress security, you have typically had one of three approaches: an agency selling a "security plugin", an email that your admin is open at /wp-admin, or an uneasy feeling after reading about a hack on a site that looked like yours. None of those tells you what you actually have to own.

We build and clean up public sites — Next.js, WordPress, shops. Security here is not a SOC 2 programme and not pentest theatre. It is the boring stack that decides whether a stranger can write in your CMS, read your .env, or redirect your visitors. It is also what most plugins promise to fix without touching the cause.

TL;DR

The main takeaways

  • A security plugin is a net. It is not a threat model, and it does not fix a theme from 2019 or a leaked deploy key.
  • The attacks that hit a marketing site are boring: exploited plugins, open admin paths, stolen secrets, open redirects.
  • Headers (HTTPS, HSTS, an honest CSP, Referrer-Policy) are what the browser can refuse for you. Set them. Measure them. Do not turn them into a badge.
  • WordPress and Next.js have the same duties and different places they break. Updates versus secrets in git — both are yours.
  • Admin, previews and staging must not look like production with a weaker lock. That is where most "small" sites get taken.
  • An afternoon with a checklist beats a yearly slide about "we have security". If you cannot explain your door, you have not locked it.

Why this matters at all

A public site is interesting to attackers because it is easy. Not because you are interesting. Automated scans look for known plugin holes, default admin paths, open .git folders and keys someone committed two years ago. They do not need to know you. They need a site still running what everyone else has patched.

When it goes wrong on a marketing site, it is rarely a cinematic break-in. It is a spam page in your CMS, a redirect to a shop you do not own, or a script in a theme header that steals forms. SEO dies afterwards — Google is quick to mark a compromised site, and slow to forget it. That is also why security and SEO sit together here, without being the same thing.

Teams overreact or underreact. Over: a WAF subscription, three plugins and a feeling that the topic is off the table. Under: "we are just a brochure." The brochure has a login, a contact-form endpoint and often a preview that shows the next campaign. That is enough. You do not need to be a bank to have a door someone will try.

This is not a pentest report and not a promise that you are "secure". It is the engineering conversation you should have before you buy the next plugin: what can a stranger do to this site in an afternoon, and what have you put in the way?

The threat model that actually applies to a public site

Do not start with nation-state. Start with what happens to sites like yours. One: known vulnerabilities in CMS, theme and plugins — especially WordPress, especially things you no longer use but have not turned off. Two: credential stuffing against /wp-admin, /login, /studio or the CMS you forgot to put 2FA on. Three: secrets in git, in a screenshot, in a Vercel log, in an old .env on a staff laptop.

Four: open previews and staging with real data and weak auth. Five: a contact-form endpoint with no rate limit that becomes a spam cannon or a place to try injection. Six: an open redirect or an old subdomain pointing at a bucket you no longer own. That is the list. It is boring. It is also the one that takes sites.

What you typically should not start with: writing a forty-page policy, buying an overlay that promises a "malware scan", or asking for a full pentest of a brochure before you have turned unused plugins off. Pentest is right when you have something to test — a login, a checkout, an API. First: close the doors you can see yourselves.

The GDPR conversation is a different one. That is about what you send, and whether the user said yes. This one is about what a stranger can do, regardless of consent. A site can have a tidy cookie banner and still an open admin. The two checklists should not be mixed. They should both be done.

Headers, TLS and what the browser can refuse for you

HTTPS is the floor. HSTS tells the browser it must not go back to HTTP. Without HSTS a network you do not control can still try to downgrade the first hop. Set it when you are sure you do not have an older HTTP-only endpoint you depend on. That is a one-line header choice, not a project.

Content-Security-Policy is what limits which scripts and embeds the page may load. An honest CSP is tight and breaks when someone drops in a new pixel. That is the point. A CSP with 'unsafe-inline' and a dozen wildcard domains is a badge. Start with default-src 'self', allow what you actually use, and run Report-Only for a week before you enforce. If you cannot list your script domains, you have a different problem — the same inventory the GDPR post asks for.

Referrer-Policy, X-Content-Type-Options, Permissions-Policy and a frame-ancestors that does not allow you to be iframed on a foreign site are next. None of them make you interesting at a conference. All of them remove a whole class of "someone embedded us and stole a click". On Next.js you set them in next.config or at your edge. On Cloudflare you can set them there. On WordPress the theme or the server has to do it — a plugin that promises "all the headers" is fine if you check that they are actually sent.

The TLS certificate should renew itself. If a human has to remember it, it will expire on a Saturday. Let's Encrypt via your host, or the cert management your edge already has, is the right answer. A screenshot of a padlock icon on a slide is the wrong one.

Plugin theatre versus what you can demonstrate

What teams typically buy

What looks like security on a slide.

  • A WordPress plugin with a green badge and a weekly email
  • A WAF turned on without anyone reading what it blocks
  • "We have 2FA" — on one login, not on CMS, host and git
  • A feeling that the topic is off the table

What actually decides the matter

What you can show a colleague in an afternoon.

  • Admin, preview and staging require real auth — and 2FA
  • Unused plugins and themes are gone, the rest is updated
  • No secrets in git; rotate anything that has been there
  • Headers you can see in a response, not only in a plugin panel

An afternoon review before you buy anything

Without this sequence you buy the wrong thing — either a plugin or a pentest you are not ready for.

  1. 01

    Find admin, preview and staging

    Try /wp-admin, /login, /studio, /admin, your CMS URL and the staging domain you used last year. If they answer without a real login wall — or with the default user — that is the job. Not a plugin.

  2. 02

    List what the site runs

    CMS, theme, plugins, Next.js version, the services you call. Turn off what you do not use. Update what you use. An abandoned form plugin is a door you forgot. Do not count. Remove.

  3. 03

    Search for secrets you put there yourselves

    git log and your host dashboard: API keys, database URLs, webhook secrets. If they have been in a repo, rotate them. Deleting the file in a new commit does not kill the history.

  4. 04

    Read response headers on the homepage and on login

    HTTPS, HSTS, a CSP that is not a wildcard poem, X-Content-Type-Options, a frame policy. If you cannot see them, you have not set them — whatever a plugin panel says.

  5. 05

    Submit one form and watch what happens

    Rate limit, captcha or another boring guard. Where does the mail land? Who can read it? An endpoint that takes 200 without hesitation from a script is a cannon. Close it before you talk about WAF rules.

A public site is not taken by a cinematic attacker. It is taken by the plugin you forgot and the admin path you never hid.

WordPress and Next.js — the same duties, different breaks

On WordPress the typical break is the plugin and theme surface. You have an ecosystem that is easy to extend and easy to forget. Security here is hygiene: fewer plugins, automatic updates you actually watch, a theme you can explain, and an admin that is not open to the internet's credential lists. A "security plugin" can help hide /wp-admin and block some paths. It cannot save a theme that no longer gets patches.

On Next.js and a hosted CMS the typical break is secrets and preview. A NEXT_PUBLIC_ variable that should not have been public. A preview URL with no auth. A server action that trusts what the browser sends. Deploy keys in a GitHub Actions log. You have fewer plugins and more places where you are the platform. That is not safer by itself. It is safer if you treat env and preview as production.

Both stacks owe you the same thing on the outside: HTTPS, headers, a form endpoint that is not an open hose, and an admin you can defend. Both can sit behind Cloudflare and get a WAF and bot controls. The WAF is a net. It is useful. It is not an excuse to run a CMS you do not update, or a preview you share in Slack without login.

If you are considering moving from WordPress to Next.js for security reasons alone, be honest: you are moving the place the boring failures can sit. You remove the plugin surface. You get the env and pipeline surface. Move if you also have other reasons — editing, performance, SEO control. Do not move because a slide said Jamstack is secure. Static files are hard to infect. Your build and your CMS are not.

What you should typically do in the situation you are in

The left is what you typically say. The right is the next step we typically recommend.

  • Situation

    You installed a security plugin and call yourselves done

    Next step

    Turn the plugin panel off and run the afternoon checklist. What the panel does not show is the job

  • Situation

    Admin or staging answers without a real login

    Next step

    Close it today. Do not buy a WAF as a substitute for a door

  • Situation

    You do not know which plugins you still run

    Next step

    List, turn off, delete. Update what you keep. Do not count "we have 20, it is fine"

  • Situation

    You have a Next.js app and "no WordPress, so we are safe"

    Next step

    Check env, preview auth, server actions and keys in git. The stack moved. The duty did not

  • Situation

    Someone wants to pentest the brochure before you have done the boring work

    Next step

    Do the boring work first. Pentest a login and a checkout when they exist — not a plugin catalogue

Checklist before you say "the site is locked"

If you are missing several of these, the claim is early — whatever badge a plugin shows.

  • Admin, preview and staging require real auth, and 2FA sits on the accounts that can publish
  • Unused plugins, themes and services are gone; the rest get updates you see
  • No deploy keys or database URLs in git — and anything that has been there has been rotated
  • Homepage and login send HSTS and a CSP you can explain, not a wildcard poem
  • The contact form has a boring guard and a place the mail lands that you control
  • You can point at who gets told if the host or CMS refuses a login

Questions we get again and again

  • Is a WordPress security plugin enough?

    Almost never as the only thing. It can hide admin, block some paths and remind you about updates. It does not fix an abandoned theme, a plugin you do not use, or a key in git. Treat it as a net. Do the hygiene. If the panel is green and /wp-admin still takes password guesses from the whole internet without 2FA, you are not done.

  • Is Next.js or a static site "secure enough" without that kind of thing?

    Static files are hard to infect at runtime. Your CMS, preview, build and env are not. A leaked deploy key or a preview with no auth is the same class of door as an open /wp-admin. You moved the surface. You did not delete the duty. Headers, secrets and login still apply.

  • Do we need a WAF — Cloudflare or something else?

    An edge layer that can rate-limit, block known bots and set headers is sensible on a public site. It is a net. It is not a reason to drop updates or leave staging open. We often use Cloudflare for that kind of thing, because it sits in front regardless of origin. Buy it to get a net. Do not buy it as a substitute for closing admin.

  • What about GDPR and cookies — is that the same as security?

    No. GDPR is what you send, and whether the user said yes. Security is what a stranger can do to the site. A tidy banner and an open admin can live side by side. Do both checklists. Do not mix them so you think a cookie plugin is also a lock.

  • When does a pentest make sense on a marketing site?

    When there is a login, a checkout or an API someone can abuse — and when you have already done the boring work. A pentest of a brochure with three abandoned plugins is an expensive document about something you could see yourselves. Close the doors. Then test what you cannot see yourselves: auth flows, uploads, the endpoints you built.

If you can only point at a plugin when someone asks

Let us walk the doors the site actually has.

An afternoon of admin, headers and secrets beats a badge you bought to get peace.

Why we wrote this

This is how we think — and it's what we build.

Our insights are about the work we actually do. If this hit something you're working on, there's a concrete service that lines up.