Secure website operation

A checklist for people and AI agents. Outside check, inside check and fixes.

One page to check your website yourself, hand it to an AI agent, or hand it to us. Every item says what should hold, how to verify it and when it passes.

Vladimír NeporAuthorVladimír Nepor
Published
The outside check sees the website as an attacker does, from the address only: encryption, headers, DNS and e-mail, public files. The inside check with read-only access sees accounts and 2FA, code and dependencies, the server and backups. The result is a list of findings by severity and a fix.OutsideURLHTTPS and TLSheadersDNS and e-mailpublic filesyour websitedomain · hosting · codeInsideaccounts and 2FAcode and depsserverbackupsfindings by severity → fix → handover01 · Yourself

I will go through it myself

The checklist →
02 · AI agent

I will hand it to an AI agent

Prompts for the agent →
03 · Service

I will hand it to you

Service options →
On this page

00 · How to use this page

Three ways to the same result

The checklist is the same for everyone. Only who goes through it differs.

  • 01 · Yourself

    I will go through it myself

    Items are grouped by area. Each has a command or tool to verify it.

    The checklist →

  • 02 · AI agent

    I will hand it to an AI agent

    Send the agent the page address and one of the prepared prompts. Ground rules and output format are part of the checklist.

    Prompts for the agent →

  • 03 · Service

    I will hand it to you

    Outside check, inside check, or straight to fixes. We take over access only for the time of the work.

    Service options →

For AI agents, the page is also available as plain text (markdown): https://vrealmatic.com/web/security.md

01 · Outside and inside

From outside you see what an attacker sees. From inside, how they would get in.

The outside check needs only the website address. The inside check needs access, but finds weaknesses that are invisible from outside.

outside Outsideinside Inside
What it needsOnly the website address.Read-only access: accounts, repository, server.
Point of viewAn attacker who knows nothing about the site.An administrator who sees the settings.
What it findsEncryption, security headers, DNS and e-mail, publicly reachable files, cookies.Accounts and 2FA, permissions and API tokens, dependencies, secrets in code, the server, backups.
What it missesA former colleague with valid access, a backup that cannot be restored, an outdated plugin in the admin.Nothing extra. The inside check also covers every outside item.
Who can do itAnyone, including an AI agent with web access only.You, an AI agent in the website repository, or us with your permission.

An attacker often needs no clever attack. A leaked password without 2FA, a forgotten plugin or a key in the repository is enough. These are exactly the items you cannot see from outside.

02 · Checklist

Secure operation checklist

Every item has a code, a scope and a severity. Outside items need only the website address, inside items need access. Replace your-site.com with your domain.

Severity: high = fix now, medium = within a month, low = at the next maintenance.

01HTTPS and encryption

An encrypted connection protects logins, forms and content from eavesdropping and tampering.

TLS-1outsideSeverity: high

The website runs on HTTPS only, and HTTP permanently redirects to HTTPS.

How to verify
curl -sI http://your-site.com and the same for the www variant.
Passes when
A 301 or 308 response with Location: https://… for every variant of the domain.
TLS-2outsideSeverity: high

The certificate is valid, covers every variant of the domain and renews automatically.

How to verify
SSL Labs or openssl s_client -connect your-site.com:443 -servername your-site.com
Passes when
The certificate matches the domain including www, the browser shows no error, renewal needs no manual step.
TLS-3outsideSeverity: medium

The server offers TLS 1.2 and 1.3 only.

How to verify
SSL Labs, the Configuration section.
Passes when
TLS 1.0 and 1.1 are disabled, grade A or A+.
TLS-4outsideSeverity: medium

Responses send the HSTS header.

How to verify
curl -sI https://your-site.com, look for Strict-Transport-Security.
Passes when
max-age of at least 31536000 (one year). preload only after checking that every subdomain supports HTTPS.
TLS-5insideSeverity: high

The connection between the CDN and the server is encrypted and verified too.

How to verify
In Cloudflare: SSL/TLS → Overview. For another CDN, the equivalent origin setting.
Passes when
Full (strict) mode. Flexible mode sends data to the server unencrypted.

02Security headers

Headers tell the browser what the page may load and how it may be displayed. They block injected scripts and framing of the page by another site.

HDR-1outsideSeverity: medium

The page has a Content-Security-Policy.

How to verify
Mozilla HTTP Observatory or curl -sI https://your-site.com
Passes when
The policy exists, restricts script sources and includes frame-ancestors. No unsafe-inline for scripts where avoidable.
HDR-2outsideSeverity: medium

The page cannot be embedded in another site (clickjacking protection).

How to verify
frame-ancestors in the CSP, or the X-Frame-Options header.
Passes when
frame-ancestors 'self' or 'none', alternatively X-Frame-Options: DENY.
HDR-3outsideSeverity: low

The browser does not guess file types.

How to verify
The X-Content-Type-Options header.
Passes when
X-Content-Type-Options: nosniff
HDR-4outsideSeverity: low

The site does not send full URLs to other sites and limits access to device features.

How to verify
The Referrer-Policy and Permissions-Policy headers.
Passes when
strict-origin-when-cross-origin or stricter. Camera, microphone and location off unless the site needs them.
HDR-5outsideSeverity: low

Responses do not reveal software and versions.

How to verify
The Server and X-Powered-By headers, the generator meta tag.
Passes when
No version numbers. Attackers use them to look up known vulnerabilities.

03Public files and leaks

The most common leak is not an attack. A file stays on the server that should not be there, or a key ends up in browser code.

EXP-1outsideSeverity: high

Configuration, repository and backups are not reachable from the web.

How to verify
Try /.env, /.git/config, /backup.zip, /dump.sql, /phpinfo.php. For example curl -s -o /dev/null -w "%{http_code}" https://your-site.com/.env
Passes when
All return 404 or 403. Watch for a 200 response with a “not found” page and check the content.
EXP-2outsideSeverity: high

Browser code contains no secret keys.

How to verify
Go through the loaded JavaScript files and search for patterns such as sk_live_, service_role, secret, api_key, Bearer.
Passes when
Only public keys that are meant for the browser (e.g. a payment gateway's publishable key).
EXP-3outsideSeverity: medium

Source maps of production code are not public, or are public on purpose.

How to verify
End of a JS file: //# sourceMappingURL=…, then try to download the .map.
Passes when
Maps are not reachable, or contain nothing sensitive (comments with passwords, internal addresses).
EXP-4outsideSeverity: medium

Error pages show no error dump, paths or versions.

How to verify
Open a non-existent address and an address with a nonsense parameter, e.g. /?id='.
Passes when
A generic error page without a stack trace, SQL query or server paths.
EXP-5outsideSeverity: medium

Test and preview versions are not publicly accessible.

How to verify
Subdomains such as staging., dev., test., hosting preview addresses (*.workers.dev, *.vercel.app, *.netlify.app).
Passes when
They require login or are not public. They are not in Google.
EXP-6outsideSeverity: low

Directory listing is off.

How to verify
Open a folder without an index, e.g. /uploads/ or /wp-content/uploads/.
Passes when
403 or 404, no list of files.

04Domain, DNS and e-mail

Whoever controls the domain controls the website and the e-mail. Poorly configured e-mail lets others send fraudulent messages in your name.

DNS-1outsideSeverity: high

The domain's e-mail is protected by SPF, DKIM and DMARC.

How to verify
dig TXT your-site.com, dig TXT _dmarc.your-site.com or Internet.nl.
Passes when
SPF ends with -all or ~all, DKIM signs outgoing mail, DMARC has p=quarantine or p=reject.
DNS-2outsideSeverity: high

A domain that sends no e-mail says so explicitly.

How to verify
The same queries as DNS-1, for domains without mail.
Passes when
v=spf1 -all and DMARC p=reject. Otherwise it can be abused as a sender.
DNS-3outsideSeverity: high

No DNS record points to a cancelled service.

How to verify
Go through the subdomains' CNAME records. Does any point to deleted hosting, a bucket or an app?
Passes when
Every record leads to a service you control. Otherwise anyone can register it and take over the subdomain.
DNS-4outsideSeverity: medium

A CAA record limits who may issue certificates.

How to verify
dig CAA your-site.com
Passes when
It lists only the authorities you actually use.
DNS-5outsideSeverity: low

DNSSEC is enabled for the domain.

How to verify
Internet.nl or dig +dnssec your-site.com
Passes when
The signature is valid.
DNS-6insideSeverity: high

The registrar account is secured and the domain will not expire.

How to verify
Account settings at the domain registrar.
Passes when
2FA on, auto-renewal, transfer lock, the contact e-mail works and does not belong to a former supplier.

05Forms and inputs

Every form is an entry into the application. From outside it is checked passively only; real input handling shows only in the code.

FRM-1outsideSeverity: medium

Public forms are protected against bots.

How to verify
Check whether the form uses Turnstile, reCAPTCHA or a honeypot. Do not submit anything.
Passes when
Protection is in place and the result is verified on the server (only FRM-2 confirms that).
FRM-2insideSeverity: high

The server validates and sanitizes every input.

How to verify
Form and API handler code: validation, parameterized database queries, output escaping.
Passes when
No SQL built from strings, no unescaped HTML output, bot protection verified on the server.
FRM-3insideSeverity: medium

Login, forms and API are rate limited.

How to verify
Rate limiting in the application or the CDN (Cloudflare: Security → WAF → Rate limiting rules).
Passes when
Repeated attempts from one address are slowed down or blocked.
FRM-4insideSeverity: medium

File uploads are restricted.

How to verify
Upload code or CMS settings.
Passes when
Allowed types and size, files outside any folder the server executes code from, new file names.

06Accounts, login and permissions

Most website administration rests on accounts: hosting, CDN, domain, repository, CMS. Each one is a way into the website.

ACC-1insideSeverity: high

Every account with access to the website has two-factor authentication (2FA).

How to verify
Member lists in hosting, Cloudflare, the registrar, the repository, the CMS and e-mail.
Passes when
2FA for everyone, ideally enforced by the account or organization settings.
ACC-2insideSeverity: high

Everyone has their own account and former collaborators have no access.

How to verify
Go through the member lists and compare them with the people working on the site today.
Passes when
No shared credentials, no unknown or inactive accounts.
ACC-3insideSeverity: high

Permissions and API tokens are as narrow as possible.

How to verify
Member roles and API token lists (Cloudflare: My Profile → API Tokens, GitHub: Settings → Developer settings).
Passes when
A token only for the needed zone and action, with an expiry. No Global API Key in apps and scripts.
ACC-4outsideSeverity: medium

The admin interface is not openly exposed.

How to verify
Try common addresses: /admin, /wp-admin, /wp-login.php, /administrator.
Passes when
The admin sits behind extra verification (Cloudflare Access, IP restriction, 2FA), or at least limits login attempts.
ACC-5insideSeverity: medium

User passwords are stored safely.

How to verify
Registration and login code, structure of the users table.
Passes when
Hashed with bcrypt, scrypt or Argon2. Never in plain text, MD5 or SHA-1.

07Cookies and sessions

A login cookie is the key to an account. It must travel encrypted only and must not be readable by scripts.

CK-1outsideSeverity: medium

Login cookies have the Secure, HttpOnly and SameSite flags.

How to verify
Browser developer tools → Application → Cookies, or Set-Cookie in the response.
Passes when
Secure, HttpOnly, SameSite=Lax or Strict.
CK-2outsideSeverity: medium

Analytics and advertising cookies are set only after consent.

How to verify
Open the site in a private window and check cookies and network requests before clicking the consent bar.
Passes when
Before consent, only necessary cookies and no requests to measurement or ad services.

08Code and dependencies

A website largely runs on other people's code: libraries, plugins, themes. Their vulnerabilities are the website's vulnerabilities.

DEP-1insideSeverity: high

Dependencies, the CMS and plugins have no known vulnerabilities.

How to verify
npm audit, OSV-Scanner, Dependabot, for WordPress the updates overview in the admin.
Passes when
No critical or high vulnerability without a fix. Unused plugins are deleted, not just deactivated.
DEP-2insideSeverity: high

There are no secrets in the repository or its history.

How to verify
Gitleaks or GitHub secret scanning over the whole history.
Passes when
Keys live only in environment variables or a secrets manager. .env is in .gitignore. Any key that ever appeared in the history has been rotated.
DEP-3insideSeverity: medium

The build is reproducible and comes from trusted sources.

How to verify
Lockfile in the repository, CI installs via npm ci (or equivalent), who may change CI and deployment.
Passes when
The lockfile is committed, deploys run only from the main branch, CI secrets have only the needed permissions.
DEP-4insideSeverity: medium

Custom code has had an in-depth security audit.

How to verify
A coding agent with the cloudflare/security-audit-skill skill, or a manual review against OWASP ASVS.
Passes when
Findings are verified and the high-severity ones are fixed.
DEP-5outsideSeverity: low

Libraries visible in the browser are not outdated.

How to verify
Versions in file names and code (jQuery, Bootstrap, CMS), or a browser extension such as Wappalyzer.
Passes when
No library with a known, unpatched vulnerability.

09Server, hosting and CDN

With managed hosting, the provider is responsible for most of this. With your own server and CDN, the settings are up to you.

SRV-1insideSeverity: high

The server is hardened and up to date.

How to verify
SSH settings (/etc/ssh/sshd_config), firewall, automatic updates.
Passes when
Login by SSH key only, no direct root login, only the necessary ports open, security updates install automatically.
SRV-2insideSeverity: medium

The server behind the CDN cannot be reached directly.

How to verify
Find the origin IP and try to open it directly, or check the origin firewall.
Passes when
The origin accepts traffic only from the CDN (Cloudflare IP ranges, Cloudflare Tunnel or authenticated origin pulls).
SRV-3insideSeverity: medium

The CDN filters malicious traffic.

How to verify
Cloudflare: Security → WAF and Bots; for another CDN, the equivalent settings.
Passes when
Managed WAF rules and bot protection are on, rules for sensitive paths exist.
SRV-4insideSeverity: high

The database and internal services are not reachable from the internet.

How to verify
Database configuration, firewall, access settings of a managed database.
Passes when
The database accepts connections only from the application or a private network. Tools like phpMyAdmin are not public.

10Backups and recovery

A backup is worth something only if the website can be restored from it, and only if an attacker cannot delete it together with the website.

BAK-1insideSeverity: high

Data and code are backed up automatically and outside production.

How to verify
Backup settings of the hosting, database and file storage.
Passes when
Regular backups, stored somewhere other than the website (another account or provider), with several versions of history.
BAK-2insideSeverity: high

Restore has been tested.

How to verify
When was the last test restore, and how long did it take?
Passes when
A restore was done in the last year, and you know how much data and time you would lose.
BAK-3insideSeverity: medium

Backups are protected.

How to verify
Who can access the backups, and whether they can be deleted from the same account as the website.
Passes when
Encrypted, with restricted access, ideally immutable for the retention period.

11Monitoring and response

A problem you learn about right away is a smaller problem. A few alerts and a clear procedure are enough.

MON-1outsideSeverity: low

The website has a security.txt file with a contact for reporting issues.

How to verify
curl -s https://your-site.com/.well-known/security.txt
Passes when
Contains Contact: and a valid Expires: (RFC 9116).
MON-2insideSeverity: medium

Uptime and the expiry of the certificate and domain are monitored.

How to verify
An uptime monitoring service and alerts at the registrar.
Passes when
An outage or an upcoming expiry alerts a specific person.
MON-3insideSeverity: medium

Logins and changes are logged.

How to verify
Audit logs in Cloudflare, hosting, the repository and the CMS. How long are logs kept?
Passes when
You know who changed which setting and when. Logs are kept for at least several weeks.
MON-4insideSeverity: low

There is a procedure for a security incident.

How to verify
A short document: who to call, where to revoke access, how to rotate keys, where to restore from.
Passes when
The procedure is written down and the people involved know about it.

03 · For AI agents

Checking with an AI agent

Send the AI agent the address of this page's markdown version and one of the prompts. An agent with web access only can handle the outside items. An agent running in the website repository with read-only access can handle the inside items too.

Prompt: outside check

For an agent with web access (search and page fetching, optionally a terminal with curl and dig).

Prompt
Check the security of https://your-site.com against this checklist:
https://vrealmatic.com/web/security.md

Scope: only items labelled "outside". You have the public address only, no access.
Follow the "Ground rules for the agent".
Output: a table as described in "Output format", most severe issues first.

Prompt: inside check

For a coding agent (e.g. Claude Code) running in the website repository, optionally with a read-only token for Cloudflare or the hosting.

Prompt
Check the security of https://your-site.com against this checklist:
https://vrealmatic.com/web/security.md

Scope: all items. Verify "inside" items in this repository and in the access
you have. Mark anything you cannot verify as "cannot verify" and say which access is missing.
Change nothing. Never print secret values, give only the file and line.
Follow the "Ground rules for the agent".
Output: a table as described in "Output format", most severe issues first.

Ground rules for the agent

  • Passive only. Ordinary GET and HEAD requests, like a website visitor. No port scanning, password guessing, fuzzing, load testing or intrusion attempts.
  • Submit nothing. No forms, sign-ups or orders, not even with made-up data.
  • Change nothing. Neither in the repository nor in service settings. Fixing is a separate step after approval.
  • Never print secret values. For a found key, password or token, give only its location (URL, file, line) and type.
  • Authorized targets only. Check only the domains, repositories and accounts the website owner explicitly named.
  • Do not guess. Mark anything you cannot verify as "cannot verify" and say why.
  • Report leaks first. A publicly reachable key, backup or personal data goes on the first row of the output, regardless of order.

Output format

One row per item. Status: pass, issue, cannot verify or not applicable. Severity is taken from the checklist. Below the table, a short summary: the three most important steps.

Markdown
| Item  | Status        | Severity | Finding and evidence             | Fix                     |
|-------|---------------|----------|----------------------------------|-------------------------|
| EXP-1 | issue         | high     | /.env returns 200 with DB_*      | Block, rotate passwords |
| TLS-4 | issue         | medium   | No Strict-Transport-Security     | Add HSTS                |
| BAK-2 | cannot verify | high     | No access to the hosting         | Test restore            |

Kits and tools

The checklist above covers everyday website operation. For a deeper look at code and the application, these kits help.

Terminal
npx skills add https://github.com/cloudflare/security-audit-skill \
  --skill security-audit

Installing the cloudflare/security-audit-skill skill. The agent then audits the code of the repository it runs in (e.g. “security audit this codebase”). It belongs to the inside check, not the outside one.

04 · Service

Check and fix by us

You can go through the checklist yourself. If you lack the time or want certainty, we go through it for you. In three options, depending on how deep you want to go.

  • Option 1

    Outside check

    No access, the website address is enough

    • All outside items
    • Encryption, headers, DNS and e-mail, public files, cookies
    • Verified manually and with tools

    A report with findings by severity and proposed fixes.

  • Option 2

    Inside check

    Read-only access for an agreed period

    • Every checklist item
    • Accounts, 2FA, permissions and API tokens
    • Code, dependencies and secrets in the repository
    • Server, CDN, backups and logs

    A report and a fix plan: what now, what within a month, what ongoing.

  • Option 3

    Check and fix

    Temporary write access, only for the fixes

    • Everything from the inside check
    • Fixes according to the approved plan
    • Verification that each fix works

    A change report with steps to revert. Access revoked at the end.

How we work together

  1. Intro call

    We agree on the option, scope and date. We find out where the website runs and who has access to what.

  2. Access

    None for the outside check. For the inside check you create our own read-only account, for fixes temporarily with write access.

  3. Check and fix

    We go through the checklist. We fix only after you approve the plan, and log every change.

  4. Handover

    You receive the report. Access is revoked, and keys we saw during the work are rotated.

05 · Access

How we handle access to your website

Taking over access is a matter of trust. That is why it follows fixed rules you can verify at any time.

  • Our own account with 2FA. No shared password, no logging in as you.
  • Read-only wherever the platform supports it. Write access only for the fix option and only where we fix.
  • Time window. Access is valid only for the agreed period. Where possible, we set an automatic expiry.
  • Change log. What, where, why and how to revert. You get it in the report.
  • We copy no secrets. Keys we see during the work are rotated afterwards.
  • Access is revoked at the end. You can check it yourself in the member list.

What access we need where

WhereInside checkCheck and fix
CloudflareAccount member with the Administrator Read Only roleA role scoped to the given domain (zone)
GitHub / GitLabRead access to the repositoryWrite to a branch, changes via a pull request you approve
Server (SSH)Own user with an SSH key, no sudoTemporary sudo rights
Hosting and CMSThe lowest role that shows the settings. Where none exists, screen sharing.A temporary administrator account
Domain registrarScreen sharing or screenshots of the settings, no access neededYou make the changes following our steps
DatabaseRead-only userWrite access only if a fix targets the data
The platform has no read-only role?

Then we use screen sharing: you click, we watch. It takes longer, but access stays with you only.

06 · Summary

Summary

Key takeaways
  • From outside you see what an attacker sees: encryption, headers, DNS and public files.
  • From inside you see how they would get in: accounts, 2FA, tokens, code and backups.
  • An AI agent needs only this page's address and one prompt. Ground rules and output format are part of the checklist.
  • Access for a check: our own account, read-only, for an agreed period and revoked at the end.

Sources

Sources and further reading

Want your website checked and fixed?

We agree on the scope, access and date. You can start with an outside check, which needs no access at all.

Arrange a check