Deutsch | English Header test API About WebForensik

WebForensik

Results for https://bbsovg.de/gesch%C3%BCtzter_Lehrkr%C3%A4ftebereich/lehrer-login.php?redirect=https%3A%2F%2Fbbsovg.de%2FLehrerhandakte%2Fmenue.php

Scan time: 2026-09-01 14:17:17

61

Overall Score

Changes since the last scan -32 declined

Compared with scan from 01.09.2026 14:16 (Score 93 → 61) · View full history

Referrer Policy 100→0 MIME Type Protection 100→0 Clickjacking Protection 100→0 Permissions (Camera, Microphone, etc.) 100→0 Enforced Encryption (HSTS) 80→0 Content Security Policy (CSP) 75→0 Privacy Policy & Legal Notice 80→50

⚠ Protections lost: hsts_present, hsts_maxage_good, csp_found, csp_script_ok, csp_frame_ancestors, csp_default_self, refpol_set, refpol_strict, xcto_ok, xfo_csp, permpol_present, permpol_good

✓ Protections gained: cookies_summary

Score history for this domain View full history →

GDPR Summary

⚠ This website needs improvement regarding data protection.

GDPR Issues Detected (2):

⚠ No Content Security Policy — increased risk of cross-site scripting (XSS) and data theft.

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

Show:
100 HTTPS / Encryption

The website uses an encrypted connection (HTTPS).

Latest encryption active (TLS 1.3 — TLSv1.3).

The security certificate is valid (expires 2027-02-15).

Strong encryption method (TLS_AES_256_GCM_SHA384, 256 bit).

0 Enforced Encryption (HSTS)

No HSTS header set. Browsers are not forced to use the encrypted connection.

☛ Action needed: Enable HSTS so browsers always use the encrypted connection. Ask your hosting provider or add this header to your server configuration: Strict-Transport-Security: max-age=31536000; includeSubDomains
▸ How to fix this — step-by-step guide

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.

Apache server (classic hosting at most providers)

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.

WordPress Special for WordPress: where to add this

Option 1: via .htaccess (recommended — no theme editing)

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

Option 2: via functions.php in the child theme (Advanced alternative)

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

↓ SHOW COMPLETE SOLUTION All missing security headers bundled at the end of the report — ready to copy.
0 Content Security Policy (CSP)

No Content Security Policy (CSP) found. The website has no protection against injected malicious code.

☛ Action needed: Set up a Content Security Policy. This protects your visitors from injected malicious code (Cross-Site Scripting/XSS). Start with a simple policy: Content-Security-Policy: default-src 'self'. Your web developer or hosting provider can help.
▸ How to fix this — step-by-step guide

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.

Apache server (classic hosting at most providers)

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.

WordPress Special for WordPress: where to add this

Option 1: via .htaccess (recommended — no theme editing)

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.

Option 2: via functions.php in the child theme (Advanced alternative)

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.

↓ SHOW COMPLETE SOLUTION All missing security headers bundled at the end of the report — ready to copy.
0 Referrer Policy

No Referrer-Policy set. When clicking external links, the full page URL is shared with other websites.

☛ Action needed: Set a Referrer-Policy to prevent the full URL of your pages from being shared with external websites. GDPR-relevant: URLs can contain personal data (e.g., usernames, search terms). Recommended setting: Referrer-Policy: strict-origin-when-cross-origin
▸ How to fix this — step-by-step guide

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.

Apache server (classic hosting at most providers)

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.

WordPress Special for WordPress: where to add this

Option 1: via .htaccess (recommended — no theme editing)

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.

Option 2: via functions.php in the child theme (Advanced alternative)

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.

↓ SHOW COMPLETE SOLUTION All missing security headers bundled at the end of the report — ready to copy.
0 MIME Type Protection

No MIME type protection (X-Content-Type-Options missing). Browsers may misinterpret files.

☛ Action needed: Add the header X-Content-Type-Options: nosniff. This prevents browsers from misinterpreting files, which can lead to security vulnerabilities. Your hosting provider or web developer can set this up in minutes.
▸ How to fix this — step-by-step guide

Without the "X-Content-Type-Options: nosniff" header the browser guesses file types from content — which attackers can exploit (e.g. a HTML file disguised as .jpg is executed as HTML). The fix is one single line.

Apache server (classic hosting at most providers)

File: .htaccess in the web root

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
</IfModule>

⚠ No side effects expected — considered a safe standard and best practice for years.

WordPress Special for WordPress: where to add this

Option 1: via .htaccess (recommended — no theme editing)

File: .htaccess in the WordPress root

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
</IfModule>

⚠ Safe to add alongside other Header set entries.

Option 2: via functions.php in the child theme (Advanced alternative)

File: functions.php of your CHILD theme

add_action('send_headers', function () {
    header('X-Content-Type-Options: nosniff');
});

⚠ Back up functions.php before edits.

✓ How to verify it works: F12 → Network → Response Header: "x-content-type-options: nosniff".

↓ SHOW COMPLETE SOLUTION All missing security headers bundled at the end of the report — ready to copy.
0 Clickjacking Protection

No clickjacking protection. The website could be embedded in other pages to trick users.

☛ Action needed: Add clickjacking protection. Without it, your website could be invisibly embedded in a fraudulent page. Set: X-Frame-Options: SAMEORIGIN or better, use CSP with frame-ancestors.
▸ How to fix this — step-by-step guide

Without clickjacking protection your site can be invisibly embedded into a malicious page ("enter your password here" — the click actually lands on your overlayed login form). Fix: set SAMEORIGIN (only your own domain may embed).

Apache server (classic hosting at most providers)

File: .htaccess in the web root

<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Content-Security-Policy "frame-ancestors 'self'"
</IfModule>

⚠ Use both headers: X-Frame-Options for older browsers, frame-ancestors for modern ones. If you already have a CSP, add "frame-ancestors 'self'" there — don’t duplicate.

WordPress Special for WordPress: where to add this

Option 1: via .htaccess (recommended — no theme editing)

File: .htaccess in the WordPress root

<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>

⚠ If your site is intentionally embedded elsewhere (e.g. booking widget on partner sites): instead of SAMEORIGIN, list allowed domains via CSP: Header always set Content-Security-Policy "frame-ancestors 'self' https://partner.example.com"

Option 2: via functions.php in the child theme (Advanced alternative)

File: functions.php of your CHILD theme

add_action('send_headers', function () {
    header('X-Frame-Options: SAMEORIGIN');
});

⚠ WordPress already tries to set X-Frame-Options — this hook deliberately overrides it.

✓ How to verify it works: F12 → Network → Response Header: "x-frame-options: SAMEORIGIN".

↓ SHOW COMPLETE SOLUTION All missing security headers bundled at the end of the report — ready to copy.
0 Permissions (Camera, Microphone, etc.)

No Permissions-Policy set. Third-party scripts could access camera, microphone, or location.

☛ Action needed: Set a Permissions-Policy to control access to camera, microphone, and location. GDPR-relevant: Without this setting, third-party scripts could silently access sensitive device features. Example: Permissions-Policy: camera=(), microphone=(), geolocation=()
▸ How to fix this — step-by-step guide

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.

Apache server (classic hosting at most providers)

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.

WordPress Special for WordPress: where to add this

Option 1: via .htaccess (recommended — no theme editing)

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

Option 2: via functions.php in the child theme (Advanced alternative)

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.

↓ SHOW COMPLETE SOLUTION All missing security headers bundled at the end of the report — ready to copy.
100 Cookies

1 first-party and 0 third-party cookie(s).

First-party cookies (from the website itself)

Name Domain Encrypted Server only SameSite
PHPSESSID bbsovg.de Yes Yes Lax
100 Local Storage (Web Storage)

No local storage (Web Storage) used — no tracking risk.

100 Third-Party Requests

No third-party requests detected — all content comes from the website's own server.

100 Tracker Detection

No known trackers detected.

100 External Resource Integrity (SRI)

No external scripts or stylesheets loaded.

100 DNS Security

CAA records present: sectigo.com — only specified certificate authorities may issue certificates.

4 nameservers present — good redundancy.

IPv6 support present (AAAA records).

SPF record present: v=spf1 include:_spf-eu.ionos.com ~all — protects against email spoofing.

DMARC record present: v=DMARC1; p=none; — email authentication active.

100 Security Contact (security.txt)

security.txt found: https://bbsovg.de/.well-known/security.txt

Contact field present (required) — security researchers can report vulnerabilities.

Expires field present (required).

Preferred languages specified.

100 External Reporting Endpoints

No external reporting endpoints detected.

80 Cookie Consent

No consent banner needed — no trackers or third-party cookies detected.

50 Privacy Policy & Legal Notice

Privacy policy linked: "Datenschutzinformationen" (https://bbsovg.de/geschuetzer_lehrkraeftebereich/datenschutz_lehrerportal.html).

No legal notice (Impressum) found — required under German law (§ 5 DDG).

☛ Action needed: Create a legal notice (Impressum) and link it prominently. Required under § 5 DDG for commercial websites. Required information: name, address, email, and where applicable, trade register and VAT ID.
▸ How to fix this — step-by-step guide

No imprint (legal notice) found — mandatory in Germany under § 5 DDG for all business-grade websites (and effectively for many other commercial sites in the EU). Even private blogs with ad or affiliate revenue typically require one. Violations are commonly targeted by warning letters.

WordPress Special for WordPress: where to add this

WordPress plugin: Step 1: create an imprint. Free generator (German law): https://www.e-recht24.de/impressum-generator.html. Mandatory information includes: full legal name, postal address (no P.O. box), phone OR another second contact, email, for companies: trade register + VAT ID, supervisory authority if applicable, professional liability insurance if applicable. Step 2: in WordPress → Pages → Add New → title "Imprint" → publish. Step 3: footer menu → add "Imprint". IMPORTANT: the imprint must be "easily recognizable, directly accessible, permanently available" — a footer link satisfies this, an "About us" → "then imprint" does NOT.

✓ How to verify it works: Footer on every page → link "Imprint" or "Legal notice" visible → opens the imprint page with all mandatory information.

Privacy policy link is broken: HTTP/1.1 503 Service Temporarily Unavailable.

☛ Action needed: The privacy policy link leads to an error. Check the URL and ensure the page is accessible.
▸ How to fix this — step-by-step guide

The privacy policy link returns an error (HTTP HTTP/1.1 503 Service Temporarily Unavailable). Effectively the same as no privacy policy — same legal status as missing.

WordPress Special for WordPress: where to add this

WordPress plugin: Step 1: check the footer menu (Appearance → Menus → Footer menu → which URL does the "Privacy" item link to?). Step 2: does the target page still exist? Pages → All Pages. Step 3: if the page was renamed: update the menu link. Step 4: if deleted: create a new one. Step 5: on permalink issues, visit Settings → Permalinks → Save (no changes — rewrites .htaccess).

✓ How to verify it works: Privacy link in footer → opens the page with status 200, content visible.

⚙ Your ready-to-use security .htaccess

All missing security headers combined into one block. Append this block to the end of your .htaccess — done. 6 headers will be set.

⚠ Why this recommendation does NOT give a 100% score — and why that's how it is with WordPress

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):

  • Plugin "WP Content Security Policy & Headers" — automatically adds nonces to inline scripts (medium effort, cleanest WP solution).
  • Hash-based CSP — whitelist every inline script via SHA-256 in the CSP (fragile, breaks on updates).
  • Externalize inline scripts — rebuild theme/plugins so no inline JS is emitted (huge effort, often impossible).

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.

Apache Standard Apache (any host, without WordPress)

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 Referrer-Policy "strict-origin-when-cross-origin"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
</IfModule>

WordPress WordPress: .htaccess in WP root

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 Referrer-Policy "strict-origin-when-cross-origin"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()"
</IfModule>
# END WebForensik Security

WordPress Alternative for WordPress: functions.php in child theme

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("Referrer-Policy: strict-origin-when-cross-origin");
    header("X-Content-Type-Options: nosniff");
    header("X-Frame-Options: SAMEORIGIN");
    header("Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=(), interest-cohort=(), browsing-topics=()");
});
Dry-run — we re-load your site with the proposed headers and show which resources would be blocked. Takes about 30 seconds.
HTTP Response Headers
HeaderValue
cache-control no-store, no-cache, must-revalidate
content-encoding gzip
content-type text/html; charset=UTF-8
date Tue, 01 Sep 2026 12:17:14 GMT
expires Thu, 19 Nov 1981 08:52:00 GMT
pragma no-cache
server Apache
set-cookie PHPSESSID=5d6068d629d096210b36bc3bb0067afd; path=/; secure; HttpOnly; SameSite=Lax
x-ws-origin available
x-ws-ratelimit-limit 1000
x-ws-ratelimit-remaining 999

New Scan · Compare

Embed your score on your website

Show your WebForensik score publicly. The badge is a lightweight SVG, loads fast, and respects your visitors' privacy (no tracking).

WebForensik Score Badge

HTML code to embed (this specific scan)

<a href="https://webforensik.de/results.php?id=1277" target="_blank" rel="noopener">
  <img src="https://webforensik.de/badge.php?id=1277" alt="WebForensik Score" width="174" height="28">
</a>

Or dynamically — always shows the latest scan of this domain

<a href="https://webforensik.de/?url=https://bbsovg.de" target="_blank" rel="noopener">
  <img src="https://webforensik.de/badge.php?domain=bbsovg.de" alt="WebForensik Score" width="174" height="28">
</a>