Website Integrity Scanner für kleine statische Webseiten gegen SEO-Spam
Find a file
Your Name de90dbc19c fix: handle YAML null values for list config fields
PyYAML parst auskommentierte Listen als None statt []. Da der Key
vorhanden ist, greift .get(key, []) nicht. Drei Fixes:
- extractor.py, differ.py: `or []` statt Default-Argument
- config.py: _deep_update überspringt None-Override auf List-Defaults

Tritt auf bei `ignore_selectors` und `ignore_patterns` in config.yaml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 01:12:09 +02:00
config feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
Keller feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
scanner fix: handle YAML null values for list config fields 2026-06-12 01:12:09 +02:00
tests feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
.gitignore feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
CLAUDE.md feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
config.yaml feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
README.md feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00
requirements.txt feat: initial implementation of website integrity scanner 2026-06-12 00:51:41 +02:00

Website Integrity Scanner

Unabhängiges Überwachungswerkzeug für statische Websites gegen SEO-Spam und unbefugte Manipulationen. Läuft im Verantwortungsbereich des Betreibers, nicht beim Webhoster.

Schnellstart

cd integrity_scanner_fuer_statische_Webseiten
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# 1. Erste Baseline anlegen
python -m scanner init

# 2. Ergebnis prüfen, dann freigeben
python -m scanner approve --all --note "Initiale Baseline nach Sichtprüfung"

# 3. Täglicher Betrieb (oder per Cron)
python -m scanner scan

Subcommands

Befehl Funktion
init Erstcrawl + Vorschau, kein Baseline-Update
crawl Crawlt die Website, speichert Snapshot
check Vergleicht letzten Snapshot mit Baseline
scan crawl + check in einem (für Cron)
approve --all Alle Snapshot-URLs als neue Baseline freigeben
approve --url URL Einzelne URL freigeben
approve --rebuild Gesamte Baseline ersetzen (nach großer Änderung)
report Letzten Report anzeigen
status Baseline-Datum, letzter Scan, Risiko-Level

Alle Befehle akzeptieren --config path/to/config.yaml und --verbose.


Workflow: Erstinitialisierung

python -m scanner init

Ausgabe zeigt:

  • alle gefundenen internen URLs
  • alle externen Links (mit Whitelist-Status)
  • potenzielle Auffälligkeiten (Hidden Content, Meta-Refresh, ...)

Wichtig: Die Ausgabe manuell prüfen, bevor die Baseline gesetzt wird. Insbesondere externe Links in config/allowed_external.yaml eintragen.

python -m scanner approve --all --note "Initiale Baseline, geprüft am $(date)"

Workflow: Täglicher Betrieb (Cron)

python -m scanner scan

Exit-Codes:

  • 0 = Grün (keine Auffälligkeiten)
  • 1 = Gelb (Warnung, manuelle Prüfung empfohlen)
  • 2 = Rot (Alarm, sofortige Prüfung notwendig)

Workflow: Legitime Änderung freigeben

# 1. Scan durchgeführt, Warnung auf /impressum/
python -m scanner report               # Report ansehen
python -m scanner approve --url https://bredelar.info/impressum/ --note "Impressum aktualisiert"

# 2. Oder alle Änderungen auf einmal (wenn alles geprüft)
python -m scanner approve --all --note "Redesign vom 2026-06-12 freigegeben"

# 3. Nach großem Redesign: komplette neue Baseline
python -m scanner approve --rebuild --note "Komplettes Redesign, alle Seiten neu"

Workflow: Incident (Alarm)

  1. Report lesen: python -m scanner report
  2. Verdächtige URLs manuell im Browser prüfen
  3. Quelltext der betroffenen Seiten ansehen (insb. display:none-Bereiche)
  4. Dienstleister kontaktieren, Zugriff auf Hosting prüfen
  5. Nach Bereinigung: python -m scanner scan — muss grün sein
  6. Dann: python -m scanner approve --rebuild --note "Nach Incident bereinigt"

Wichtig: Niemals approve auf eine kompromittierte Seite anwenden.


Cron-Setup

# Täglich 03:00 Uhr
0 3 * * * cd /opt/scanner && /opt/scanner/venv/bin/python -m scanner scan >> /opt/scanner/logs/cron.log 2>&1

Log-Rotation (/etc/logrotate.d/scanner):

/opt/scanner/logs/*.log {
    daily
    rotate 30
    compress
    missingok
    notifempty
}

Konfiguration

E-Mail aktivieren

In config.yaml:

alerting:
  email:
    enabled: true
    smtp_host: mail.example.com
    smtp_port: 587
    smtp_user: scanner@example.com
    smtp_password_env: SCANNER_SMTP_PASSWORD
    from: scanner@bredelar.info
    to:
      - admin@bredelar.info

Passwort als Umgebungsvariable setzen (nicht in config.yaml):

export SCANNER_SMTP_PASSWORD="geheimesPasswort"

Webhook aktivieren

alerting:
  webhook:
    enabled: true
    url: "https://hooks.slack.com/services/..."

Externe Domains whitelisten

Nach dem ersten init alle legitimen externen Domains in config/allowed_external.yaml eintragen:

- fonts.googleapis.com
- maps.googleapis.com

Verzeichnisstruktur

data/
  baseline/         Aktuell freigegebene Referenz (NIEMALS automatisch aktualisiert)
    manifest.json   Wer/was/wann freigegeben hat
    pages/          Pro URL eine JSON-Datei
  snapshots/        Zeitgestempelte Crawl-Ergebnisse
    YYYYMMDD_HHMMSS/
reports/            Generierte Reports (JSON + Markdown)
logs/               scanner.log
config/
  allowed_external.yaml
  allowed_paths.yaml
  ignore_rules.yaml

Tests

pytest tests/ -v

Erweiterungen (optional, nicht implementiert)

  • Ollama-Integration: Neue Textblöcke semantisch auf Spam-Kategorien prüfen
  • Telegram-Bot: direkter Alert-Kanal
  • Diff-Anzeige im Terminal: python -m scanner report --diff-only
  • Automatische Archivierung alter Snapshots nach N Tagen