Scan time: 2026-05-26 19:59:42
Overall Score
⚠ This website needs improvement regarding data protection.
GDPR Issues Detected (1):
⚠ Missing or unsafe Referrer-Policy — URLs containing personal data may be leaked to third parties.
Note: This automated analysis does not replace legal advice. For a complete GDPR assessment, consult a data protection officer.
↓ See detailed results for each category below.
The website uses an encrypted connection (HTTPS).
Latest encryption active (TLS 1.3 — TLSv1.3).
The security certificate is valid (expires 2026-07-22).
Strong encryption method (TLS_AES_256_GCM_SHA384, 256 bit).
HSTS is enabled — the browser is instructed to always use the encrypted connection.
HSTS duration: 31536000 seconds (at least 1 year) — very good.
Content Security Policy present (via HTTP-Header).
No restriction for scripts defined (script-src/default-src missing).
Your CSP exists but has no script-src — meaning scripts are unrestricted. Scripts are the most common XSS vector. Add script-src together with the other essential directives.
File: .htaccess in the web root
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' https: data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'"
</IfModule>⚠ Replace the existing CSP line (do not add a second one). This policy is deliberately pragmatic — it allows inline styles and data: URIs for images because almost all themes (especially WordPress!) need this. If you use external scripts (CDN), append the domain to script-src: script-src 'self' https://cdn.example.com. For maximum security later, gradually tighten style-src to 'self' and verify in the browser (F12 → Console) that no inline-style violations appear.
File: .htaccess in the WordPress root
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' https: data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'"
</IfModule>⚠ Replace the existing CSP. IMPORTANT for WordPress: img-src with data: enables emoji + admin-bar SVGs, style-src 'unsafe-inline' allows the many inline styles from themes and plugins — without both, the site will break visually. Common WP script sources to add to script-src: 'self' (own), https://www.googletagmanager.com (GTM), https://www.google-analytics.com (GA) — append after 'self' with a space.
File: functions.php of your CHILD theme
add_action('send_headers', function () {
header("Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' https: data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'");
});⚠ Watch out for existing send_headers hooks — keep only one active. Back up functions.php before editing!
✓ How to verify it works: F12 → Network → Response Header content-security-policy contains "script-src 'self'". Console: no script blocks, no "Refused to load…" messages.
Embedding protection (frame-ancestors) is configured — protects against clickjacking.
No Referrer-Policy set. When clicking external links, the full page URL is shared with other websites.
Without a Referrer-Policy the browser sends the full URL of your current page (incl. search terms, usernames in URL params) on every click to the destination site. Privacy-relevant per Art. 5 GDPR. Recommended safe setting: strict-origin-when-cross-origin.
File: .htaccess in the web root
<IfModule mod_headers.c>
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>⚠ "strict-origin-when-cross-origin" is the modern standard: on cross-domain clicks only your origin (no path/params) is sent — internal clicks include the full URL. Stricter is "no-referrer" (send nothing) but it breaks some analytics tools.
File: .htaccess in the WordPress root
<IfModule mod_headers.c>
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>⚠ WordPress 4.9+ already emits a meta-tag with this policy, but the HTTP header above applies to all resources (images, scripts) — not only the HTML document.
File: functions.php of your CHILD theme
add_action('send_headers', function () {
header('Referrer-Policy: strict-origin-when-cross-origin');
});⚠ Always back up functions.php before edits.
✓ How to verify it works: F12 → Network → first request → Response Headers — "referrer-policy: strict-origin-when-cross-origin" must be present.
MIME type protection active (nosniff) — browsers will not misinterpret files.
Clickjacking protection active via CSP frame-ancestors.
No Permissions-Policy set. Third-party scripts could access camera, microphone, or location.
Permissions-Policy controls whether scripts (including third-party) may access camera, microphone, location, motion sensors etc. GDPR-relevant because sensitive device APIs can otherwise be reached unnoticed.
File: .htaccess in the web root
<IfModule mod_headers.c>
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=()"
</IfModule>⚠ "()" at the end means: no caller (not even your own page) may use this API. If you need geolocation (e.g. a map feature): use geolocation=(self) instead of geolocation=(). "interest-cohort=()" disables Google’s FLoC tracking.
File: .htaccess in the WordPress root
<IfModule mod_headers.c>
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()"
</IfModule>⚠ Standard WordPress needs none of these APIs. If you use a plugin that needs the camera (QR scanner, video upload), set that API to "(self)".
File: functions.php of your CHILD theme
add_action('send_headers', function () {
header('Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()');
});⚠ Back up functions.php before edits.
✓ How to verify it works: F12 → Network → Response Header: "permissions-policy" visible.
No cookies set — exemplary for privacy.
2 localStorage and 0 sessionStorage item(s) found.
| Name | Value |
|---|---|
| i18nextLng | de |
| readabler | {} |
No third-party requests detected — all content comes from the website's own server.
No known trackers detected.
No external scripts or stylesheets loaded.
No CAA records. Any certificate authority could issue a certificate for this domain.
CAA records (Certification Authority Authorization) define in DNS which Certificate Authorities are allowed to issue certificates for your domain. Without a CAA record an attacker could request a fraudulent certificate for your domain at any CA. CAA is pure DNS configuration — set in your registrar/DNS-panel, NOT in WordPress.
Find your host in the table, copy the values to your DNS panel. For multi-CA hosts: one separate CAA record per CA (all with tag issue, flag 0, name @). Additionally recommended: an iodef record with a contact email for abuse reports.
| # | Host | CA(s) used | CAA value(s) — tag issue |
|---|---|---|---|
| 1 | Hetzner Webhosting (basic certificate, free in package) | DigiCert (programme „Encryption Everywhere") | digicert.com |
| 1 | Hetzner Webhosting (Let’s Encrypt, free) | Let’s Encrypt (ISRG) | letsencrypt.org |
| 2 | All-Inkl | Let’s Encrypt + Sectigo (Pro) | letsencrypt.orgsectigo.com |
| 3 | IONOS (1&1) | DigiCert (GeoTrust) + Let’s Encrypt | digicert.comletsencrypt.org |
| 4 | STRATO | Sectigo + Let’s Encrypt | sectigo.comletsencrypt.org |
| 5 | Cloudflare (Universal SSL) | Google Trust Services + DigiCert + Let’s Encrypt | pki.googdigicert.comletsencrypt.org |
| 6 | AWS (ACM / CloudFront) | Amazon Trust Services | amazon.comamazontrust.comawstrust.comamazonaws.com |
| 7 | Mittwald | Let’s Encrypt + Sectigo | letsencrypt.orgsectigo.com |
| 8 | Webgo | Let’s Encrypt + Sectigo | letsencrypt.orgsectigo.com |
| 9 | raidboxes (Managed WordPress) | Let’s Encrypt | letsencrypt.org |
| 10 | Host Europe / DomainFactory | Sectigo + Let’s Encrypt | sectigo.comletsencrypt.org |
Name Type Flag Tag Value
@ CAA 0 issue "digicert.com"
@ CAA 0 issue "letsencrypt.org"
@ CAA 0 iodef "mailto:security@your-domain.com"
The iodef line (last line) is optional but recommended: CAs report abuse attempts to that address. For subdomains (e.g. shop.your-domain.com) create separate records with the subdomain name instead of @ — modern CAs check parent CAA automatically though.
If your host is not on the list: open your current certificate in the browser (padlock → certificate → issuer). The CA name is shown there (e.g. "Sectigo RSA Domain Validation Secure Server CA" → value sectigo.com). Add that as a CAA record, done.
WordPress plugin: CAA records are NOT created in WordPress but in your domain registrar / DNS provider panel (e.g. Hetzner-Robot, IONOS Domains, Cloudflare Dashboard, INWX, etc.). Common label: "CAA record" or under "TXT records" with type selector "CAA". One separate record per CA.
✓ How to verify it works: On https://www.ssllabs.com/ssltest/analyze.html?d=your-domain.com → "DNS CAA" section → all your CAs should be listed. Or via dig: dig CAA your-domain.com.
No IPv6 support (no AAAA record).
Your domain has no IPv6 address (AAAA record). Over 40% of users (especially mobile) reach the internet via IPv6 — they must take the slower IPv4 gateway detour.
WordPress plugin: Pure DNS + server matter. Step 1: check if your host has an IPv6 address for you (hosting panel or support ticket). Step 2: in the DNS panel create an AAAA record pointing to that IPv6. Step 3: test.
✓ How to verify it works: dig AAAA your-domain.com — or online https://ipv6-test.com/validate.php?url=your-domain.com.
No SPF record. Emails can be forged in the name of this domain.
SPF (Sender Policy Framework) defines in DNS which servers may send emails on behalf of your domain. Without SPF any phisher can spoof emails from you — and recipients are more likely to fall for them.
WordPress plugin: DNS matter, not WordPress. Create a TXT record in your DNS panel. Examples: If you send NO emails: v=spf1 -all (reject all senders). If only your host sends: v=spf1 a mx ~all. If Google Workspace: v=spf1 include:_spf.google.com ~all. If Microsoft 365: v=spf1 include:spf.protection.outlook.com -all.
✓ How to verify it works: dig TXT your-domain.com | grep spf — or online https://www.kitterman.com/spf/validate.html.
No DMARC record. The domain is vulnerable to email phishing.
DMARC combines SPF and DKIM into an explicit instruction for receiving mail servers: "What to do if emails claim to come from us but SPF/DKIM fail?" Without DMARC each server decides — usually generously. With DMARC=reject you effectively prevent phishing in your name.
WordPress plugin: DNS matter. TXT record at subdomain _dmarc.your-domain.com. Recommended stages: Observe first: v=DMARC1; p=none; rua=mailto:dmarc-reports@your-domain.com — review reports for weeks. Then tighten: v=DMARC1; p=quarantine; rua=… — suspicious mails go to spam. Final: v=DMARC1; p=reject; rua=… — they’re refused outright.
✓ How to verify it works: dig TXT _dmarc.your-domain.com — or online https://dmarcian.com/dmarc-inspector/.
No security.txt file found (RFC 9116). Security researchers don't know how to report vulnerabilities.
A security.txt (RFC 9116) tells security researchers how to responsibly report vulnerabilities to you. Without it, reports may go to spam or never be sent. A plain text file at the correct path is enough.
File: /.well-known/security.txt (create the folder if it doesn’t exist)
Contact: mailto:security@your-domain.com
Expires: 2027-12-31T23:59:59.000Z
Preferred-Languages: en, de
Canonical: https://your-domain.com/.well-known/security.txt⚠ Replace "security@your-domain.com" with your actual security contact (or a generic info@). "Expires" must be a future date and should be renewed regularly. The file is plain .txt, not PHP.
File: security.txt file in /.well-known/ under your WordPress root
Contact: mailto:security@your-domain.com
Expires: 2027-12-31T23:59:59.000Z
Preferred-Languages: en, de
Canonical: https://your-domain.com/.well-known/security.txt⚠ Via FTP/SFTP create a folder ".well-known" in the WordPress root (the leading dot matters — some FTP tools need "show hidden files" enabled), inside save the file security.txt with the content above. If WordPress redirects the URL: add to .htaccess: RewriteRule ^\.well-known/ - [L]
WordPress plugin: Plugin "security.txt" (search the plugin directory) lets you configure this in the WordPress backend without FTP.
✓ How to verify it works: Open https://your-domain.com/.well-known/security.txt in a browser — content must be visible (no 404).
No external reporting endpoints detected.
Cookie consent system detected: Klaro, klaro.
Consent system detected, but banner does not appear to be visible.
Your consent system is wired up but the banner doesn’t appear visibly — perhaps hidden by another plugin or custom CSS. Risk: without a visible banner, no consent is given.
WordPress plugin: Approach: 1) clear browser cache + cookies, use incognito. 2) In the consent plugin: check display conditions (e.g. "only EU visitors" — and you’re testing from a non-EU server). 3) F12 → Console for red errors from consent scripts. 4) Inspector → search DOM for "cookie", "consent" — element present but display:none? z-index too low? 5) Uninstall conflicting cookie-notice plugins.
✓ How to verify it works: Incognito tab, load page, wait 5 seconds — banner visible centered/bottom, doesn’t fully block main content, is clickable.
Privacy policy linked: "Datenschutz" (/datenschutz).
Legal notice linked: "Impressum" (/impressum).
Privacy policy page is accessible (HTTP 200).
All missing security headers combined into one block. Append this block to the end of your .htaccess — done. 3 headers will be set.
The Content-Security-Policy above deliberately includes 'unsafe-inline' for both style-src and script-src. This does NOT provide full XSS protection — it's a pragmatic trade-off, not a bug.
Why? A typical WordPress setup (theme + 5-15 plugins) emits 10-50 different inline <script> blocks into the HTML: jQuery init, slider init, cookie banner, tracking, GTM, web vitals, lazy-load, speculation rules and so on. A strict script-src 'self' blocks them all — the site becomes visually and functionally broken (blank slider, broken cookie banner, dead plugins).
Consequence for scoring: Sites running WordPress with plugins can score at most ~75-85 points in the CSP category in this app — the full 100% rating is only achievable when inline code is signed via nonce or hash (technically demanding, breaks on every theme/plugin update).
Paths to full XSS protection (in increasing complexity):
Anyone who doesn't take one of these paths lives with 'unsafe-inline' — like about 95% of all production WordPress sites on the web. The other CSP directives still protect: default-src 'self' blocks external resources, object-src 'none' bans Flash/Java, frame-ancestors 'self' prevents clickjacking, base-uri 'self' prevents base-tag hijacking. Not maximum protection, but realistic protection for WP reality.
Append this block to the end of your .htaccess in the web root — done.
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' https: data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'; upgrade-insecure-requests"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
</IfModule>
Insert this block ABOVE the "# BEGIN WordPress" line, otherwise WP overwrites it on permalink changes.
# BEGIN WebForensik Security
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' https: data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'; upgrade-insecure-requests"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
</IfModule>
# END WebForensik Security
If your host disallows .htaccess changes: append this PHP snippet to the end of your CHILD theme's functions.php. Back up first — NEVER edit the parent theme, it gets overwritten on updates.
add_action('send_headers', function () {
header("Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' https: data:; object-src 'none'; frame-ancestors 'self'; base-uri 'self'; upgrade-insecure-requests");
header("Referrer-Policy: strict-origin-when-cross-origin");
header("Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()");
});
| Header | Value |
|---|---|
| accept-ranges | bytes |
| cache-control | max-age=14515 |
| content-encoding | gzip |
| content-language | de-DE |
| content-length | 23222 |
| content-security-policy | frame-ancestors 'self' https://www.decor-union.de |
| content-type | text/html; charset=utf-8 |
| date | Tue, 26 May 2026 17:59:01 GMT |
| expires | Tue, 26 May 2026 22:00:56 GMT |
| last-modified | Tue, 26 May 2026 15:43:55 GMT |
| server | Apache |
| strict-transport-security | max-age=31536000 |
| vary | Accept-Encoding |
| x-content-type-options | nosniff |
| x-frame-options | SAMEORIGIN |
| x-sfc-tags | pages_13704, pages_13754, pages_13765, pages_13764, pages_13763, pages_13762, pages_13761, pages_13760, pages_13759, pages_13758, pages_13757, pages_13756, pages_13755, pages_13743, pages_13753, pages_13752, pages_13751, pages_13750, pages_13749, pages_13748, pages_13747, pages_13746, pages_13745, p |
| x-ua-compatible | IE=edge |