Originally published in German on next-levels.de. The free Security Check referenced below is our own tool; the six checks are the ones it runs.
Direct answer: The fastest way to check website security is from the outside, the way an attacker does: HTTPS and certificate, security headers, cookie flags, publicly reachable files such as
.gitor.env, mixed content and scripts without integrity protection, plus SPF, DKIM and DMARC in DNS. These six checks take seconds, need no login and show what every visitor can see.
The first attack on your website isn't an attack. It's a handful of harmless requests: a GET /, a look at the response headers, a TLS connection, three DNS queries. Nobody breaks in, nobody tries passwords. And yet, afterwards, the other side knows more about your server than most operators know themselves.
That's division of labour. Anyone attacking websites at scale scans at scale first. Server search engines like Shodan or Censys, mass scanners like Nuclei, home-grown scripts: all of them start by reading only what a server hands out voluntarily, then sort. A domain with an expired certificate, missing headers and a publicly reachable .env file lands on the shortlist. A domain whose basic configuration is in order is uninteresting at this stage, because the next candidate is easier.
You can replay that triage yourself. Our free Security Check does exactly that: it fetches your homepage like a browser, follows the redirects, opens a TLS connection and queries public DNS. No exploits, no credentials, read-only. The six categories it grades are the same six things an attacker checks first. This article walks through them in that order, each time with a look at what the finding looks like in the check.
At a glance
- Attackers scan before they attack. The six checks here are the part everyone can see from outside: HTTPS & TLS, security headers, cookie flags, info leaks, content & scripts, email senders.
- Most findings are configuration, not rebuilds: a few lines of nginx, one cookie attribute, three DNS records.
- A single error such as a public .env file or missing HTTPS caps the grade in the check at C, however good the rest is.
- A good score means the basic configuration is right. Logins, APIs and shop logic are only covered by a penetration test.
Check 1: HTTPS & TLS. Do your visitors see a browser warning?
Encryption has long been the baseline assumption. The browser punishes every deviation immediately and visibly: the padlock is missing, the page is flagged "Not secure", and an invalid certificate produces a warning page most visitors won't click past. For a shop that's not a security problem, it's a revenue problem.
From the outside, what matters most are the gaps in the encryption. If the server also answers on port 80 with content instead of a redirect, the first connection on open Wi-Fi can be diverted to a copy. If the certificate doesn't match the hostname or expires in a few days, that reveals an operations team that isn't paying attention.
If DNS has no CAA record, any certificate authority in the world may issue a certificate for your domain. Whoever fools one of them gets a valid certificate in your name, and every browser would accept it.
Certificate expiry is turning into a permanent issue. In 2025 the CA/Browser Forum decided to shorten the maximum lifetime of public TLS certificates in steps: to 200 days as of 15 March 2026, to 100 days from March 2027, to 47 days from March 2029 (schedule at DigiCert). Anyone still renewing certificates by hand won't keep that up past 2027. Automation via ACME is therefore the only configuration that will still work in two years.
The target configuration is unspectacular: HTTPS on all hostnames, HTTP redirects with a 301 straight to the final HTTPS address, the certificate covers www and the bare domain and renews itself. Germany's federal security agency BSI recommends TLS 1.3 in its TR-02102-2 and accepts TLS 1.2 only with restrictions; TLS 1.0 and 1.1 should be switched off. Add a one-line CAA record, such as your-domain.com. CAA 0 issue "letsencrypt.org", which specifies which certificate authority is allowed to issue certificates for it at all.
What this looks like in the check
Five signals, one note: HTTPS reachable, HTTP redirects cleanly, certificate valid, hostname matches, expiry not within seven days. The CAA record runs as a note. The check connects read-only to your public host on port 443 and additionally fetches the HTTP variant. No HTTPS, or an invalid certificate, or one about to expire, is an error. A missing HTTP redirect is a warning. If anything here is red, the order of the rest of the report no longer matters: this comes first.
Check 2: Security headers. Is your site protected against injected code and clickjacking?
Security headers are instructions from your server to the browser: load this page only over HTTPS, run scripts only from these sources, don't allow embedding in third-party frames, don't guess file types. They cost nothing, every browser has understood them for years, and they're still missing in many setups. For a scanner that's the first hint that nobody with a security mindset has been through the configuration.
Six headers count, and they differ enormously in cost. Five of them take ten minutes to set and change nothing about your site. The sixth, the Content Security Policy, takes a few days. It's also the only one that can mitigate a real application vulnerability.
The quick five: Strict-Transport-Security (HSTS) tells the browser to access the domain over HTTPS only for a set period, even if someone types http://. Without HSTS the first request may happen unencrypted, and that first request is the moment a redirect on open Wi-Fi succeeds. The browsers' HSTS preload list only accepts domains with a max-age of at least one year, includeSubDomains and preload; shorter lifetimes count as too weak.
X-Content-Type-Options: nosniff stops the browser guessing file types and executing an uploaded file as a script. X-Frame-Options or the CSP directive frame-ancestors prevent clickjacking, the invisible embedding of your page in a third-party page where a visitor thinks they're clicking somewhere else; MDN now recommends frame-ancestors.
Referrer-Policy limits how much of the referring URL is passed to third-party sites, strict-origin-when-cross-origin is the sensible default. Permissions-Policy switches off camera, microphone or geolocation, which a shop doesn't need anyway.
The Content Security Policy (CSP) defines which sources scripts, styles, images and frames may be loaded from. A clean CSP defuses cross-site scripting even when the application has a vulnerability, because injected code simply isn't executed. The most common mistake is script-src 'unsafe-inline'. With it, the policy allows exactly what XSS needs and is practically useless. Many shop and CMS setups do this because plugins ship inline scripts. The fix is nonces or hashes, not switching the protection off.
A starting point for nginx that works without a rebuild and deliberately leaves the CSP in report-only mode, so you see what it would block before it does:
# Baseline security headers, nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# Observe the CSP first, enforce later
add_header Content-Security-Policy-Report-Only "default-src 'self'; frame-ancestors 'self'; report-uri /csp-report" always;
One nginx quirk that regularly causes confusion: add_header isn't inherited once a location block has its own add_header. All the headers set higher up are then suddenly missing on exactly that path. If it hits the block serving the homepage, the check sees it immediately; in the configuration file it doesn't stand out.
What this looks like in the check
What's counted is what your homepage actually delivers after all redirects; the check doesn't read configuration files. Each of the six headers is its own test; if one is missing, that's a warning. Typical weaknesses are also flagged as warnings: unsafe-inline or unsafe-eval in the CSP, placeholder policies and an HSTS lifetime that's too short. The newer isolation headers COOP, CORP and COEP run as notes with no effect on the score. This is not a full analysis of your CSP, and the report says so.
Check 3: Cookie flags. Can session cookies be stolen?
The session cookie is the key to the logged-in state. Whoever has it is you, without a password, without a two-factor code. That's why the three attributes this cookie is set with matter more than the length of your password.
Secure makes the browser send the cookie exclusively over HTTPS. Without the flag it goes over the wire in plain text on the first unencrypted request to any subpage. HttpOnly removes JavaScript's access to the cookie. If an XSS attack does succeed, the injected script at least can't read the session and phone it home, the classic goal of such an attack. SameSite controls whether the cookie is sent with requests triggered by a third-party site, and is thus the browser's defence against cross-site request forgery.
Since Chrome 80 in February 2020, Chrome and other Chromium browsers have treated cookies without a SameSite attribute as Lax by default and required Secure for SameSite=None (summary of the change). Firefox and Safari don't do this in the same way. So "the browser takes care of it" is not a configuration. A session cookie should be set explicitly like this: Set-Cookie: session=…; Path=/; Secure; HttpOnly; SameSite=Lax.
A detail that regularly surprises shop operators: often the application's session cookie sets all three flags, and the problem is the six cookies from tracking, chat and A/B-testing scripts that set their own attributes. Which of those you may set before consent at all is a topic of its own; we broke it down in the article on cookies, consent and the TDDDG.
What this looks like in the check
Only the homepage's Set-Cookie headers, only the three flags Secure, HttpOnly and SameSite. The check stores no cookies and never reuses them; what's reported are the attributes. A missing flag is a warning. It doesn't see cookies that are only set after login or in the checkout. You check those in your browser's developer tools, "Application" or "Storage" tab, and that's worth doing on every shop at least once per release.
Check 4: Info leaks. Are source code or credentials exposed on the web?
This category holds the attacks that need no exploit. A deployment via git pull on the web server, a vhost whose document root is the repository, and /.git/HEAD is public. Whoever finds it downloads the complete repository with freely available tools, history included. In there: database credentials, API keys, sometimes private keys.
Truffle Security measured how often that happens in 2023: of the top 1 million websites, 4,500 had a publicly reachable .git directory, among them hundreds of valid credentials, 45 percent of them AWS and GitHub credentials. One site served the private key of its TLS certificate. The same logic applies to .env files, which Laravel, Symfony, Node and Shopware projects use for configuration and secrets: if it sits in the webroot and the server isn't told to block hidden files, it answers with HTTP 200 and the database password.
Then there are the quieter leaks. A Server: nginx/1.18.0 or X-Powered-By: PHP/7.4 tells a scanner which known vulnerabilities to try. An active directory listing shows folder contents never meant for visitors, backups and uploads included. And the HTTP method TRACE echoes the request back, headers included; it has no business on a production server.
The fix is a few lines in any web server. For nginx:
# Block all hidden files and directories, keep .well-known reachable
location ~ /\.(?!well-known) { deny all; }
# Strip the version number from the Server header
server_tokens off;
# X-Powered-By comes from PHP itself: in php.ini set expose_php = Off
After that, every credential that ever sat in a publicly reachable file needs rotating. Blocking alone doesn't help if the file was already fetched, and you have to assume it was.
Two files in this category are welcome. Everyone knows robots.txt. /.well-known/security.txt per RFC 9116 is the standardised place where you say where security researchers should report a vulnerability they've found; mandatory fields are Contact and Expires. Whoever has this file gets tip-offs before they turn into incidents.
What this looks like in the check
An HTTP 200 on /.git/HEAD or /.env is an error. Only the status code is evaluated; the content is never fetched. Also an error: an open directory listing. Server and X-Powered-By banners and active TRACE are warnings, robots.txt and security.txt run as info. If you unlock the report, you also get a plain connection test on 16 common ports, from SSH and FTP to MySQL and RDP, but it is only sent to an email address on the checked domain, so nobody can probe other people's servers.
Check 5: Content & scripts. Does your page load insecure or tamper-prone files?
Your page is only as secure as what it loads. Two things sit in the delivered HTML for anyone to read: resources included over http:// although the page runs on HTTPS, and external scripts arriving from third-party servers without integrity protection.
Mixed content is the older of the two mistakes. An image over HTTP is annoying, a script over HTTP is dangerous, because anyone sitting on the network path can swap it, and it then runs with all the rights of your page. Modern browsers now block active mixed-content resources, which means the function fails silently. Both are reasons to fix how the resource is included.
The newer mistake is trusting third-party CDNs. In June 2024 the company Sansec documented that over 100,000 websites were serving malicious code. The domain polyfill.io, from which they had loaded a compatibility library for years, had changed hands in February 2024, and the new operator tampered with the code. The operators of the affected sites hadn't changed anything. They had trusted a script tag someone had added at some point.
The defence against that is Subresource Integrity (SRI). You specify the hash of the expected file in the tag, and the browser only executes the script if the content matches:
<script src="https://cdn.example.com/lib.min.js"
integrity="sha384-…"
crossorigin="anonymous"></script>
If someone changes the file on the CDN, the hash no longer matches and the script doesn't run. SRI only works for files that aren't supposed to change, i.e. versioned libraries. For tag managers, analytics loaders or chat widgets that continually update themselves, it doesn't work. There, all you can do is keep the number of such scripts small and restrict them in the CSP to exactly those hosts. Or you host the library yourself, which for a versioned file is the better solution anyway.
What this looks like in the check
What's analysed is your homepage's HTML, without fetching the included files. Every http:// resource on an HTTPS page is a warning. External scripts without an integrity attribute run as a note, because not every script can sensibly be secured with SRI. You get the list of affected sources. Treat it as an inventory: every script nobody on the team can still account for gets removed before you think about hashes.
Check 6: Email senders. Can someone send phishing emails in your name?
On the face of it, this check has nothing to do with your website, yet it's the one where the damage lands most directly on your customers. Without three DNS records, any mail server in the world can send an email with invoice@your-domain.com as the sender, and to the recipient it looks genuine. Fake invoices, changed bank details, "your account has been locked": the pattern is well known, and the domain in whose name it happens carries the reputational damage.
Presumably that's why no other finding stays unnoticed as long as this one: the forged emails arrive at your customers and never reach you.
SPF (RFC 7208) is a TXT record listing which servers may send for your domain. DKIM (RFC 6376) cryptographically signs every outgoing email, the public key sits in DNS under a selector. DMARC ties the two together with a policy: what should a recipient do with emails that fail SPF and DKIM? p=none means deliver and only report. Only p=quarantine or p=reject filters forgeries out.
Since May 2026, DMARC is a Proposed Standard on the IETF Standards Track with RFC 9989, replacing the informational RFC 7489 from 2015. Existing records remain valid.
The big mailbox providers have turned this from a should into a must. Since February 2024, Google and Yahoo require bulk senders of 5,000 or more emails a day to have SPF, DKIM and at least a DMARC with p=none, and Google has been enforcing the rules with rejections since late 2025 (Google sender guidelines). Microsoft followed in May 2025 for Outlook.com and rejects non-compliant mail from bulk senders with 550 5.7.15 Access denied (Microsoft Tech Community).
A shop with a newsletter and order confirmations hits that threshold faster than most people think. And below it, the same three records still decide whether your order confirmation lands in the inbox or in spam.
Three records that establish the state "nobody may send in my name except my mail provider":
# SPF: only Google Workspace may send, hard-fail everything else
your-domain.com. TXT "v=spf1 include:_spf.google.com -all"
# DKIM: public key under the provider's selector
google._domainkey.your-domain.com. TXT "v=DKIM1; k=rsa; p=…"
# DMARC: quarantine forgeries, reports to you
_dmarc.your-domain.com. TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@your-domain.com"
The right order: set SPF and DKIM, create DMARC with p=none and a reporting address, read the reports for two to four weeks until every legitimate sender (shop, newsletter tool, CRM, ticket system) authenticates cleanly, then move to quarantine and later to reject. Whoever goes straight to reject without knowing the reports tends to block their own invoicing system.
What this looks like in the check
Three warnings are possible here: missing SPF, missing DMARC and a DMARC with p=none, because it only reports forgeries. Everything is read from your domain's public DNS. DKIM is searched under the three common selectors default, google and selector1; if your provider uses a different one, it shows as a note. If you only want to check the domain and not the whole website, use the leaner SPF, DKIM and DMARC check. DNSSEC and actual deliverability are checked by neither.
What the grade means
The score is deliberately simple: the share of passed tests among all graded ones, with no hidden weighting. Notes don't count. From that comes the grade: A from 90 points, B from 80, C from 65, D from 50, below that F. Then there's a second rule: a single error caps the grade at C, even if everything else is fine. A website with perfect headers and a public .env file is not a B website, because an attacker doesn't look for the average of your configuration but for the one spot that's enough.
The report also states what an external check fundamentally can't see. It only checks the homepage: subpages, login areas, checkout and APIs stay out of scope. It doesn't match shop, CMS or plugin versions against known vulnerabilities. And it attacks nothing. Logins, APIs, permissions and business logic are only covered by a penetration test, and for shops, customer portals and anything with sensitive data, that belongs on the list as well.
The order is still clear: basic configuration first, then the pentest. Whoever orders a penetration test on a website whose .git is public already knows the first twenty minutes of the report.
Legally, all of this is mandatory. Art. 32 GDPR requires technical measures in line with the state of the art, and encrypted connections plus a maintained server configuration are indisputably part of that. Your website's privacy policy describes what your server does with data, and should therefore match the findings.
From finding to fix: three routes
Depending on who looks after your server and DNS, there are three realistic routes. If your company has its own admins or a hosting provider with access to the configuration, the report is enough: every finding comes with its recommendation, headers and redirects are a few lines, DNS records three lines, and afterwards you simply check again. If a CDN with a page cache sits in front of your site, it may briefly still serve the old response.
If you don't have an ops team of your own, we implement the fixes on web server, CDN, shop and DNS and document the result with a fresh check. That's part of our work in maintenance and support and in hosting and scaling. And where a shop or customer portal with real data sits behind it, we bring in a specialised partner for the penetration test, agree the scope and close the gaps found afterwards.
The first step takes seconds: check your website, look at the score, and then you know what the other side already knows.
FAQ: website security check
Which finding is the most urgent?
Everything that shows as an error in the check: no HTTPS, an invalid certificate, an open directory listing, or a publicly reachable .git or .env file. For the last two, every credential that ever sat in them needs rotating afterwards.
How can I check my website security for free?
With an external check that only reads what your server delivers to every visitor: HTTPS and certificate, security headers, cookie flags, open files, mixed content and the DNS records SPF, DKIM and DMARC. Our Security Check does exactly that in seconds, without login and without attacking anything.
Is a website security check the same as a penetration test?
No. A penetration test deliberately attacks an application: logins, APIs, permissions, inputs. A security check grades the public configuration. The two complement each other, and the basic configuration should be right before the pentest.
How often should I check website security?
After every deployment that touches server, CDN or DNS, and otherwise at least quarterly. Certificates now run shorter, plugins add cookies and scripts without asking, and DNS records change whenever a new newsletter or CRM tool is added.
Questions about one of the six checks, or a finding you can't place? Drop it in the comments. Next in this series: a 30-minute guide to HSTS, CSP and the other five headers.
Top comments (0)