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.
- 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.
- 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.
- 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.
- 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.
- 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.
