feat: initial implementation of website integrity scanner
Python-Package zur unabhängigen Überwachung statischer Websites gegen
SEO-Spam und unbefugte Manipulationen. Läuft außerhalb des Hosters.
Kernfunktionen:
- Reiner Python-Crawler (bs4+lxml), kein wget
- Baseline-Management mit manuellem Freigabe-Workflow (niemals automatisch)
- Text-/Link-/Meta-Diff mit Risiko-Scoring (grün/gelb/rot)
- Hidden-Content-Erkennung (CSS inline, noscript, Kommentar-Links)
- Whitelist für externe Domains und interne Pfade
- E-Mail + Webhook Alarmierung
- CLI: init, crawl, check, scan, approve, report, status
- 79 Unit-Tests (pytest), alle grün
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:51:41 +02:00
|
|
|
"""Config loading with deep-merge against defaults."""
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
DEFAULT_CONFIG: dict = {
|
|
|
|
|
"target": "https://bredelar.info",
|
|
|
|
|
"user_agent": "integrity-scanner/1.0 (+security-monitoring)",
|
|
|
|
|
"request_timeout": 20,
|
|
|
|
|
"data_dir": "data",
|
|
|
|
|
"reports_dir": "reports",
|
|
|
|
|
"logs_dir": "logs",
|
|
|
|
|
"config_dir": "config",
|
|
|
|
|
"crawl": {
|
|
|
|
|
"max_pages": 200,
|
|
|
|
|
"delay_seconds": 1.0,
|
|
|
|
|
"respect_robots_txt": False,
|
|
|
|
|
"skip_extensions": [
|
|
|
|
|
".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".ico",
|
|
|
|
|
".pdf", ".zip", ".woff", ".woff2", ".ttf", ".otf", ".eot",
|
|
|
|
|
".mp4", ".mp3", ".webm", ".avi", ".mov",
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
"scoring": {
|
|
|
|
|
"new_external_domain": 50,
|
|
|
|
|
"new_internal_url": 30,
|
|
|
|
|
"missing_internal_url": 20,
|
|
|
|
|
"hidden_content": 40,
|
|
|
|
|
"unexpected_canonical": 35,
|
|
|
|
|
"meta_refresh": 40,
|
|
|
|
|
"unexpected_jsonld": 35,
|
|
|
|
|
"large_text_addition": 20,
|
|
|
|
|
"new_inline_script_suspicious": 30,
|
|
|
|
|
"comment_links": 25,
|
2026-06-12 01:55:19 +02:00
|
|
|
"new_broken_link": 20,
|
2026-06-12 03:20:32 +02:00
|
|
|
"suspicious_filename": 60,
|
2026-06-12 04:02:24 +02:00
|
|
|
"cloaking_extra_link": 60,
|
|
|
|
|
"cloaking_extra_text": 40,
|
|
|
|
|
"cloaking_vary_ua": 25,
|
2026-06-12 09:26:59 +02:00
|
|
|
"changed_script": 40,
|
|
|
|
|
"changed_stylesheet": 30,
|
|
|
|
|
"changed_asset": 20,
|
feat: initial implementation of website integrity scanner
Python-Package zur unabhängigen Überwachung statischer Websites gegen
SEO-Spam und unbefugte Manipulationen. Läuft außerhalb des Hosters.
Kernfunktionen:
- Reiner Python-Crawler (bs4+lxml), kein wget
- Baseline-Management mit manuellem Freigabe-Workflow (niemals automatisch)
- Text-/Link-/Meta-Diff mit Risiko-Scoring (grün/gelb/rot)
- Hidden-Content-Erkennung (CSS inline, noscript, Kommentar-Links)
- Whitelist für externe Domains und interne Pfade
- E-Mail + Webhook Alarmierung
- CLI: init, crawl, check, scan, approve, report, status
- 79 Unit-Tests (pytest), alle grün
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:51:41 +02:00
|
|
|
},
|
|
|
|
|
"thresholds": {
|
|
|
|
|
"yellow": 20,
|
|
|
|
|
"red": 60,
|
|
|
|
|
"large_text_block_chars": 200,
|
|
|
|
|
},
|
feat: Laientauglichkeit — Auto-Modus, Klartext-Ausgabe, einfachere Doku
Ziel: ein einziger täglicher Befehl genügt, jede Meldung ist auch ohne
IT-Wissen verständlich.
Auto-Modus (ein Cron-Job genügt für alles):
- data/state.json merkt sich, wann die Wochen-Prüfungen zuletzt liefen
(baseline.py: load_state/save_state/is_check_due/mark_check_run)
- `scan` führt fällige Zusatzprüfungen (Tarnung/externe Links/Dateien)
automatisch mit aus; Gesamt-Ampel = schlechtestes Teilergebnis;
EIN kombinierter Report + EIN Alert
- neuer Config-Abschnitt periodic_checks (Default: wöchentlich, an)
Klartext (scanner/plain.py):
- Ampel 🟢/🟡/🔴 + Sätze ohne Fachbegriffe, aus den strukturierten Befunden
- Report: Klartext oben, "Technische Details (für Ihren Dienstleister)" unten
- Terminal-Ausgabe und E-Mail (alerter.py) ebenso umgestellt
Komfort:
- approve --all/--rebuild legt die Datei-Überwachung automatisch mit an
(Opt-out: --skip-assets); approve-assets bleibt für den Sonderfall
- status zeigt Ampel zuoberst + wann die Wochen-Prüfungen zuletzt liefen
- Onboarding-Text in einfacher Sprache, wenn noch kein Vergleichsstand existiert
Doku: README + BEDIENUNGSANLEITUNG mit "In 3 Schritten"-Einstieg.
Tests: test_state.py, test_plain.py (Fachbegriff-Assertion), Auto-Asset-
Baseline-Test. 165 Tests grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 11:14:05 +02:00
|
|
|
"periodic_checks": {
|
|
|
|
|
"enabled": True,
|
|
|
|
|
"interval_days": 7,
|
|
|
|
|
"cloak_check": True,
|
|
|
|
|
"ext_links": True,
|
|
|
|
|
"assets": True,
|
|
|
|
|
},
|
feat: initial implementation of website integrity scanner
Python-Package zur unabhängigen Überwachung statischer Websites gegen
SEO-Spam und unbefugte Manipulationen. Läuft außerhalb des Hosters.
Kernfunktionen:
- Reiner Python-Crawler (bs4+lxml), kein wget
- Baseline-Management mit manuellem Freigabe-Workflow (niemals automatisch)
- Text-/Link-/Meta-Diff mit Risiko-Scoring (grün/gelb/rot)
- Hidden-Content-Erkennung (CSS inline, noscript, Kommentar-Links)
- Whitelist für externe Domains und interne Pfade
- E-Mail + Webhook Alarmierung
- CLI: init, crawl, check, scan, approve, report, status
- 79 Unit-Tests (pytest), alle grün
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:51:41 +02:00
|
|
|
"alerting": {
|
|
|
|
|
"min_level": "yellow",
|
|
|
|
|
"email": {
|
|
|
|
|
"enabled": False,
|
|
|
|
|
"smtp_host": "localhost",
|
|
|
|
|
"smtp_port": 587,
|
|
|
|
|
"smtp_tls": True,
|
|
|
|
|
"smtp_user": "",
|
|
|
|
|
"smtp_password_env": "SCANNER_SMTP_PASSWORD",
|
|
|
|
|
"from": "scanner@example.com",
|
|
|
|
|
"to": [],
|
|
|
|
|
},
|
|
|
|
|
"webhook": {
|
|
|
|
|
"enabled": False,
|
|
|
|
|
"url": "",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"normalization": {
|
|
|
|
|
"strip_html_comments": True,
|
|
|
|
|
"collapse_whitespace": True,
|
|
|
|
|
"ignore_selectors": [],
|
|
|
|
|
"ignore_patterns": [],
|
|
|
|
|
},
|
|
|
|
|
"allowed_jsonld_types": [
|
|
|
|
|
"Organization", "WebSite", "WebPage", "Article", "BreadcrumbList",
|
|
|
|
|
"ItemList", "LocalBusiness", "Place", "Person", "Event",
|
|
|
|
|
"FAQPage", "Question", "Answer", "ImageObject", "SiteLinksSearchBox",
|
|
|
|
|
"ContactPage", "AboutPage",
|
|
|
|
|
],
|
|
|
|
|
"security_headers": [
|
|
|
|
|
"Content-Security-Policy",
|
|
|
|
|
"Strict-Transport-Security",
|
|
|
|
|
"X-Content-Type-Options",
|
|
|
|
|
"Referrer-Policy",
|
|
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_config(config_file: str = "config.yaml") -> dict:
|
|
|
|
|
"""Load config from YAML, deep-merged on top of defaults."""
|
|
|
|
|
cfg = _deep_copy(DEFAULT_CONFIG)
|
|
|
|
|
p = Path(config_file)
|
|
|
|
|
if p.exists():
|
|
|
|
|
with p.open(encoding="utf-8") as f:
|
|
|
|
|
user_cfg = yaml.safe_load(f) or {}
|
|
|
|
|
_deep_update(cfg, user_cfg)
|
|
|
|
|
return cfg
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def resolve_paths(cfg: dict, base_dir: Path) -> dict:
|
|
|
|
|
"""Resolve relative paths in config against base_dir."""
|
|
|
|
|
for key in ("data_dir", "reports_dir", "logs_dir", "config_dir"):
|
|
|
|
|
cfg[key] = str(base_dir / cfg[key])
|
|
|
|
|
return cfg
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _deep_copy(d: dict) -> dict:
|
|
|
|
|
import copy
|
|
|
|
|
return copy.deepcopy(d)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _deep_update(base: dict, override: dict) -> None:
|
|
|
|
|
for k, v in override.items():
|
|
|
|
|
if isinstance(v, dict) and isinstance(base.get(k), dict):
|
|
|
|
|
_deep_update(base[k], v)
|
2026-06-12 01:12:09 +02:00
|
|
|
elif v is None and isinstance(base.get(k), list):
|
|
|
|
|
pass # YAML null on a list field = "not set" → keep default
|
feat: initial implementation of website integrity scanner
Python-Package zur unabhängigen Überwachung statischer Websites gegen
SEO-Spam und unbefugte Manipulationen. Läuft außerhalb des Hosters.
Kernfunktionen:
- Reiner Python-Crawler (bs4+lxml), kein wget
- Baseline-Management mit manuellem Freigabe-Workflow (niemals automatisch)
- Text-/Link-/Meta-Diff mit Risiko-Scoring (grün/gelb/rot)
- Hidden-Content-Erkennung (CSS inline, noscript, Kommentar-Links)
- Whitelist für externe Domains und interne Pfade
- E-Mail + Webhook Alarmierung
- CLI: init, crawl, check, scan, approve, report, status
- 79 Unit-Tests (pytest), alle grün
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:51:41 +02:00
|
|
|
else:
|
|
|
|
|
base[k] = v
|