Scan time: 2026-10-26 14:21:18
Overall Score
Compared with scan from 19.10.2026 08:17 (Score 60 → 59) · View full history
⚠ Protections lost: privacy_link_accessible
⚠ This website has serious GDPR deficiencies. Immediate action is required.
GDPR Issues Detected (2):
❌ 10 third-party server(s) outside the EU/EEA — data transfers without legal basis may violate Art. 44–49 GDPR.
Affected servers outside the EU:
⚠ No Content Security Policy — increased risk of cross-site scripting (XSS) and data theft.
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 2027-03-11).
Strong encryption method (TLS_AES_256_GCM_SHA384, 256 bit).
No HSTS header set. Browsers are not forced to use the encrypted connection.
HSTS (HTTP Strict Transport Security) tells the browser: "Always use HTTPS for this domain — no matter what." This prevents attackers on the same WLAN from intercepting the first, unprotected request. Prerequisite: your site is already stable on HTTPS.
File: .htaccess in the web root
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>⚠ max-age=31536000 equals 1 year (in seconds). includeSubDomains also covers blog.your-domain.com, shop.your-domain.com etc. — only enable if ALL subdomains support HTTPS, otherwise they become unreachable.
File: .htaccess in the WordPress root
# BEGIN WebForensik HSTS
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>
# END WebForensik HSTS⚠ Insert ABOVE the "# BEGIN WordPress" line. Only enable once HTTPS has been stable for a few days — the header is intentionally hard to roll back (browsers remember the instruction).
File: functions.php of your CHILD theme (Appearance → Theme File Editor → functions.php)
add_action('send_headers', function () {
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
});⚠ NEVER edit the parent theme — changes are lost on update. Back up functions.php first!
✓ How to verify it works: DevTools (F12) → Network tab → reload page → click the first request → "Response Headers" — must contain "strict-transport-security: max-age=31536000…".
No Content Security Policy (CSP) found. The website has no protection against injected malicious code.
A Content Security Policy (CSP) is a doorkeeper rule for the browser: "Scripts and styles may only be loaded from these allowed sources." Without CSP, injected malicious code (XSS) can freely fetch anything. Start with a simple, secure baseline.
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>⚠ This policy is intentionally pragmatic (allows inline styles since many themes/plugins rely on them). If something breaks after enabling: F12 → Console shows "Refused to load…" — add the affected domain after script-src / img-src.
File: .htaccess in the WordPress root
# BEGIN WebForensik CSP
<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>
# END WebForensik CSP⚠ WordPress often loads external scripts (Google Fonts, jQuery CDN, analytics pixel) — if CSP blocks them: open the console, see which domain is blocked, append that domain to "script-src 'self'" separated by 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'");
});⚠ If unsure: start with "Content-Security-Policy-Report-Only" (only monitor, don’t block), watch violations in the console, then switch to enforced mode.
✓ How to verify it works: Open page, F12 → Console — no red "Refused to load…" messages. Network tab → first request → Response Header "content-security-policy" visible.
Referrer-Policy: strict-origin-when-cross-origin (via HTTP-Header).
Strict setting "strict-origin-when-cross-origin" — no path leak, no HTTP downgrade leak. Best practice.
MIME type protection active (nosniff) — browsers will not misinterpret files.
Clickjacking protection active: X-Frame-Options = SAMEORIGIN.
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.
1 first-party and 0 third-party cookie(s).
1 of 1 cookie(s) without SameSite protection — sent with requests from other websites.
Without "SameSite" cookies are sent on requests from foreign sites — the basis of CSRF attacks (a foreign page silently triggers actions in your name because the login cookie travels along). Set SameSite=Lax as a minimum.
File: .htaccess in the web root
<IfModule mod_headers.c>
Header always edit Set-Cookie "^(.*)$" "$1; SameSite=Lax" "expr=!(resp('Set-Cookie') -strmatch '*SameSite*')"
</IfModule>⚠ SameSite=Lax is a good default. Strict is safer but breaks external links (user clicks from Google to your site — cookies are NOT sent, login is lost). None allows cross-site but requires "; Secure".
File: wp-config.php (above "/* That’s all, stop editing! */")
@ini_set('session.cookie_samesite', 'Lax');
@ini_set('session.cookie_secure', '1');
@ini_set('session.cookie_httponly', '1');⚠ Sets SameSite/Secure/HttpOnly for PHP session cookies. WordPress login cookies have been SameSite=Lax since WP 6.2. Update older versions!
✓ How to verify it works: F12 → Application → Cookies → "SameSite" column should show "Lax" or "Strict" everywhere, not empty.
| Name | Domain | Encrypted | Server only | SameSite |
|---|---|---|---|---|
| 460020e1c62a4b504205adf41ac08df2 | hohenzollern-schloss.de | Yes | Yes | None |
No local storage (Web Storage) used — no tracking risk.
113 request(s) to 24 different third-party servers.
10 third-party server(s) outside the EU/EEA — potentially problematic for GDPR compliance.
GDPR-relevant: visitor data (at least IP + User-Agent) is transmitted to servers outside the EU/EEA. Since the Schrems-II ruling (2020) this requires Standard Contractual Clauses + supplementary technical measures AND prior consent. Best fix: replace with EU alternatives where possible.
WordPress plugin: Common culprits and EU alternatives: Google Fonts → Bunny Fonts or self-host (plugin "OMGF — Host Google Fonts Locally"). Google Analytics → Matomo (self-hosted) or Plausible (EU servers). Google reCAPTCHA → hCaptcha (EU) or Friendly Captcha. Google Maps → OpenStreetMap. YouTube embeds → plugin "WP YouTube Lyte" loads only after click. CDN: Cloudflare → BunnyCDN (EU) or KeyCDN.
✓ How to verify it works: Load in incognito mode, F12 → Network → list all requests → check "Domain" column for non-EU servers. After migration no unrequested US domains should load.
14 third-party server(s) within the EU/EEA.
Requested URLs:
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/thumbnail_ca3867da.jpg
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/playlist.m3u8
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video.m3u8
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/240p/video.m3u8
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video0.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/240p/video0.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video1.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video2.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video3.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video4.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video5.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video6.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video7.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video8.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video9.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video10.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video11.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video12.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video13.ts
https://vz-28d911f9-bca.b-cdn.net/9c5a0456-42a8-4590-9eae-21954ee06cf8/1080p/video14.ts
... and 21 more request(s)
Requested URLs:
https://rum-metrics.bunny.net/trackperformance?zone=no&latency=62
https://rum-metrics.bunny.net/trackperformance?zone=ec&latency=167
https://rum-metrics.bunny.net/trackperformance?zone=tw&latency=205
https://rum-metrics.bunny.net/trackperformance?zone=it&latency=15
https://rum-metrics.bunny.net/trackperformance?zone=id&latency=184
https://rum-metrics.bunny.net/trackperformance?zone=isr&latency=57
https://rum-metrics.bunny.net/trackperformance?zone=brb&latency=300
https://rum-metrics.bunny.net/trackperformance?zone=ph&latency=193
https://rum-metrics.bunny.net/trackperformance?zone=se&latency=43
https://rum-metrics.bunny.net/trackperformance?zone=ga&latency=109
https://rum-metrics.bunny.net/trackperformance?zone=la&latency=154
https://rum-metrics.bunny.net/trackperformance?zone=hou&latency=135
https://rum-metrics.bunny.net/trackperformance?zone=mx&latency=146
... and 2 more request(s)
Requested URLs:
https://player.mediadelivery.net/embed/736026/9c5a0456-42a8-4590-9eae-21954ee06cf8?autoplay=true&loop=true&muted=true&preload=true&responsive=true
https://player.mediadelivery.net/assets/1.3.36/player.es.css
https://player.mediadelivery.net/assets/1.3.36/player.es.js
https://player.mediadelivery.net/video/736026/9c5a0456-42a8-4590-9eae-21954ee06cf8/thumbnails.vtt?referer=https%3A%2F%2Fhohenzollern-schloss.de%2F
... and 4 more request(s)
Requested URLs:
https://fonts.bunny.net/css?family=Rubik
https://fonts.bunny.net/rubik/files/rubik-latin-400-normal.woff2
... and 2 more request(s)
Requested URLs:
https://edgezone-no.bunnyinfra.net/500b.jpg?s=1793020862537
https://edgezone-no.bunnyinfra.net/500b.jpg?s=1793020862487
... and 2 more request(s)
Requested URLs:
https://edgezone-ph.bunnyinfra.net/500b.jpg?s=1793020866525
https://edgezone-ph.bunnyinfra.net/500b.jpg?s=1793020867497
... and 2 more request(s)
Requested URLs:
https://video.bunnycdn.com/.metrics/track-session
... and 3 more request(s)
Requested URLs:
https://consentcdn.cookiebot.com/consentconfig/98809f97-70f7-4c82-bf30-8cf7989a0f09/settings.json
https://consentcdn.cookiebot.com/consentconfig/98809f97-70f7-4c82-bf30-8cf7989a0f09/hohenzollern-schloss.de/configuration.js
https://consentcdn.cookiebot.com/sdk/bc-v5.min.html
Requested URLs:
https://consent.cookiebot.com/uc.js
https://consent.cookiebot.com/98809f97-70f7-4c82-bf30-8cf7989a0f09/cc.js?renew=false&referer=hohenzollern-schloss.de&dnt=false&init=false
Requested URLs:
https://metrics-bunny.net/test/register
... and 1 more request(s)
Requested URLs:
https://edgezone-ec.bunnyinfra.net/500b.jpg?s=1793020863268
... and 1 more request(s)
Requested URLs:
https://edgezone-tw.bunnyinfra.net/500b.jpg?s=1793020863267
... and 1 more request(s)
Requested URLs:
https://edgezone-it.bunnyinfra.net/500b.jpg?s=1793020864628
... and 1 more request(s)
Requested URLs:
https://edgezone-id.bunnyinfra.net/500b.jpg?s=1793020864479
... and 1 more request(s)
Requested URLs:
https://edgezone-isr.bunnyinfra.net/500b.jpg?s=1793020865218
... and 1 more request(s)
Requested URLs:
https://edgezone-brb.bunnyinfra.net/500b.jpg?s=1793020865758
... and 1 more request(s)
Requested URLs:
https://edgezone-se.bunnyinfra.net/500b.jpg?s=1793020867850
... and 1 more request(s)
Requested URLs:
https://edgezone-ga.bunnyinfra.net/500b.jpg?s=1793020868385
... and 1 more request(s)
Requested URLs:
https://edgezone-la.bunnyinfra.net/500b.jpg?s=1793020868556
... and 1 more request(s)
Requested URLs:
https://edgezone-hou.bunnyinfra.net/500b.jpg?s=1793020869722
... and 1 more request(s)
Requested URLs:
https://edgezone-mx.bunnyinfra.net/500b.jpg?s=1793020870063
... and 1 more request(s)
Requested URLs:
https://edgezone-rs.bunnyinfra.net/500b.jpg?s=1793020872056
... and 1 more request(s)
Requested URLs:
https://36d49a30.metrics-bunny.net/test/hello
Requested URLs:
https://478d3fc4.metrics-bunny.net/test/hello
No known trackers detected.
0 of 3 external resource(s) use integrity verification (SRI).
Only some of your external resources (0 of 3) are protected by SRI. Add integrity attributes to the remaining ones too.
WordPress plugin: Approach: view page source → all <script src="https://…"> and <link href="https://…"> without integrity attribute → generate hash at https://www.srihash.org/ → add integrity="sha384-…" crossorigin="anonymous". Plugin "WP-SRI" automates many cases.
✓ How to verify it works: F12 → Console on page load: no "Failed to find a valid digest" messages. Source: all external <script>/<link> have an integrity attribute.
No external resources use integrity verification. Tampered files would not be detected.
SRI (Subresource Integrity) is a checksum in HTML that defines what an externally loaded file MUST look like. If someone tampers with the external file (e.g. a CDN gets compromised), the browser refuses to load it. You add the "integrity" attribute on the script/link tag.
WordPress plugin: In WordPress you can rarely add SRI hashes manually (scripts are queued via wp_enqueue_script()). Plugin "WP-SRI" (in the plugin directory) adds integrity hashes automatically for external scripts/styles. For statically embedded resources in your theme: generate the hash at https://www.srihash.org/, add integrity="sha384-…" and crossorigin="anonymous" on the <script>/<link> tag.
✓ How to verify it works: F12 → Network → requests with status 200 from CDN domains (cdn.jsdelivr.net, cdnjs.cloudflare.com etc.) → in HTML source the tag must contain "integrity=\"sha384-…\" crossorigin=\"anonymous\"".
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.
2 nameservers present — good redundancy.
IPv6 support present (AAAA records).
SPF record present: v=spf1 include:secureserver.net -all — protects against email spoofing.
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: Cookiebot, cookiebot.com.
Consent banner is visible to visitors.
Privacy policy linked: "Learn more about this provider" (https://www.cookiebot.com/goto/privacy-policy/).
Legal notice linked: "Impressum" (/de/impressum).
All missing security headers combined into one block. Append this block to the end of your .htaccess — done. 4 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.
On Hetzner-Konsoleh webhosting (and comparable shared hosts like All-Inkl, IONOS, Strato, 1blu, …), Apache throws a 500 Internal Server Error as soon as Header always edit Set-Cookie … expr=… appears in .htaccess. The Apache error log says:
Can't parse envclause/expression: syntax error, unexpected T_OP_STR_EQ, expecting $end
This is not a WebForensik bug and not a typo — the shared host has blocked the mod_headers expr= subset via AllowOverride limits (for security, because Header edit could also manipulate cookies of other tenants).
☛ For Hetzner-Konsoleh users: use the variant below marked with the red "Hetzner / Shared" badge. It consists of two files (.htaccess + wp-config.php) instead of one, but avoids the 500 error reliably. Cookie flags go into wp-config.php instead of .htaccess.
Append this block to the end of your .htaccess in the web root — done.
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
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 Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
# Fehlende Cookie-Flags konditional ergänzen (nur wenn nicht schon gesetzt)
Header always edit Set-Cookie "^(.*)$" "$1; SameSite=Lax" "expr=!(resp('Set-Cookie') -strmatch '*SameSite*')"
</IfModule>
This variant avoids the 500 Internal Server Error on Hetzner-Konsoleh and similar shared hosts (All-Inkl, IONOS, Strato, 1blu …): the .htaccess only contains the header directives (no "Header edit"), cookie flags move into wp-config.php. Two files to edit instead of one, but guaranteed to run.
# BEGIN WebForensik Security
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
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 Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
</IfModule>
# END WebForensik Security
Insert ABOVE the line "/* That's all, stop editing! */". Back up wp-config.php first!
// === WebForensik: Cookie-Hardening (Hetzner-Konsoleh-tauglich) ===
// Bitte OBERHALB der Zeile "/* That's all, stop editing! */" einfügen.
// Wirkt auf PHP-Session- und WordPress-Login-Cookies.
// Plugin-eigene Cookies (z.B. WooCommerce, Cookie-Banner) müssen in den
// Plugin-Einstellungen separat auf "Secure" gestellt werden.
@ini_set('session.cookie_samesite', 'Lax');
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 Strict-Transport-Security "max-age=31536000; includeSubDomains"
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 Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
# Fehlende Cookie-Flags konditional ergänzen
Header always edit Set-Cookie "^(.*)$" "$1; SameSite=Lax" "expr=!(resp('Set-Cookie') -strmatch '*SameSite*')"
</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("Strict-Transport-Security: max-age=31536000; includeSubDomains");
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("Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()");
});
// Cookie-Flags für PHP-Session-Cookies — wirkt nur auf $_SESSION,
// NICHT auf von Plugins/Themes per setcookie() gesetzte Cookies.
// Für umfassende Cookie-Absicherung die .htaccess-Variante oben verwenden.
add_action('init', function () {
if (headers_sent()) return;
@ini_set('session.cookie_samesite', 'Lax');
}, 1);
| Header | Value |
|---|---|
| cache-control | no-store, no-cache, must-revalidate, post-check=0, pre-check=0 |
| connection | keep-alive |
| content-type | text/html; charset=utf-8 |
| date | Mon, 26 Oct 2026 13:21:01 GMT |
| expires | Wed, 17 Aug 2005 00:00:00 GMT |
| last-modified | Mon, 26 Oct 2026 13:21:01 GMT |
| pragma | no-cache |
| server | Apache |
| transfer-encoding | chunked |
| x-content-type-options | nosniff |
| cross-origin-opener-policy | same-origin |
| referrer-policy | strict-origin-when-cross-origin |
| x-frame-options | SAMEORIGIN |