integrity_scanner_fuer_stat.../README.md

341 lines
12 KiB
Markdown
Raw Normal View History

# Website Integrity Scanner
## Was macht dieses Programm?
Es überwacht Ihre Website und meldet Ihnen, wenn sich etwas verändert hat —
besonders heimliche Manipulationen wie versteckten Spam, fremde Links oder
ausgetauschte Dateien. So merken Sie früh, wenn jemand unbefugt in Ihre Seite
eingegriffen hat.
Das Programm läuft bei Ihnen, nicht beim Webhoster. Sie brauchen kein IT-Wissen:
Es zeigt eine **Ampel** (🟢 / 🟡 / 🔴) und erklärt jeden Fund in einfachen Worten.
## In 3 Schritten startklar
```bash
# Einmalig: Programm einrichten
cd integrity_scanner_fuer_statische_Webseiten
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Optional: scanner.sh in ~/bin/ verlinken für systemweiten Aufruf
ln -s "$PWD/scanner.sh" ~/bin/scanner
```
```bash
# Schritt 1: Erste Prüfung — Scanner legt das Zielverzeichnis automatisch an:
python -m scanner https://ihre-website.de init
# Schritt 2: Wenn die Website in Ordnung ist, Zustand als Referenz speichern:
python -m scanner https://ihre-website.de approve --all --note "Erststand geprüft"
# Schritt 3: Ab jetzt täglich prüfen (am besten automatisch, siehe unten):
python -m scanner https://ihre-website.de scan
# Bei Gelb/Rot den Bericht ansehen:
python -m scanner https://ihre-website.de report
```
Das Verzeichnis `ihre-website.de/` wird beim ersten Aufruf automatisch angelegt.
**Gut zu wissen:** Die selteneren Prüfungen (Tarnung, externe Links, Dateien)
laufen **automatisch einmal pro Woche** beim täglichen `scan` mit. Sie brauchen
dafür **nichts** extra einzurichten — ein täglicher Aufruf genügt für alles.
---
## 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 |
| `report --diff-only` | Nur Textdiffs geänderter Seiten (farbig, kompakt) |
| `status` | Baseline-Datum, letzter Scan, Risiko-Level |
| `test-alert` | Test-E-Mail senden, ohne echten Scan (SMTP-Check) |
feat: KI-gestützte Inhaltsanalyse via OpenRouter (hash-gegated) Optionale semantische Prüfung von Text und Bildern (inkl. OCR) auf problematische Inhalte ohne Link-Signal: Pornografie, Propaganda, diffamierende/strafbare Texte, versteckter Spam, themenfremde Werbung, widersprüchliche Aussagen. Bewertet die thematische Passung zum deklarierten site_context — eingestreute Heimat-Begriffe täuschen die Erkennung nicht. Kern: - scanner/ai_analyzer.py: run_ai_analysis + score_ai_findings. Hash-Gate über data/ai_ledger.json → unveränderte Inhalte = Cache- Treffer = kein API-Call. Nur neue/geänderte Inhalte kosten etwas. - Modell-Kette mit zweifacher Eskalation (Stufe 1+2 free, Stufe 3 günstig bezahlt); eskaliert bei Fehler ODER Timeout (attempt_timeout). Erfolgreiches Modell wird im Ledger vermerkt. - KI-Funde sind auf GELB gedeckelt — ROT bleibt harten Integritäts- Signalen vorbehalten. Graceful degradation: ohne Key/bei Fehler wird übersprungen, Scan läuft unverändert weiter. Integration: - baseline.py: load/save_ai_ledger, dismiss_ai_entries. - config.py: ai_analysis-Block + ai_* Scoring-Schlüssel. - __main__.py: Einhängung in cmd_scan/cmd_check, ai-dismiss-Subcommand, approve quittiert zugehörige Funde, status-Anzeige, diff-only + report. - alerter.py + __main__.py: beanstandete Dateien erscheinen mit URL, Begründung und Quittier-Fingerprint in E-Mail UND Markdown-Report. - plain.py: laienverständliche KI-Sätze. API-Key nur aus Umgebungsvariable (OPENROUTER_API_KEY). Audio/Video als abschaltbare Hooks vorbereitet (default aus). Modelle live gegen OpenRouter verifiziert; Demo auf bredelar.info zeigte korrekte Erkennung (echter Inhalt clean, eingeschleuster Casino-Spam mit Heimat-Begriffen als hidden_spam erkannt). Tests: 227 grün (+26 für ai_analyzer, +1 für E-Mail-KI-Abschnitt). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:04:33 +02:00
| `ai-dismiss --all` | KI-Funde als geprüft/akzeptiert quittieren (Fehlalarm) |
Alle Befehle akzeptieren `--config path/to/config.yaml` und `--verbose`.
---
## Workflow: Erstinitialisierung
```bash
python -m scanner https://ihre-website.de 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 `ihre-website.de/config/allowed_external.yaml` eintragen.
```bash
python -m scanner https://ihre-website.de approve --all --note "Initiale Baseline, geprüft am $(date +%Y-%m-%d)"
```
---
## Workflow: Täglicher Betrieb (Cron)
```bash
python -m scanner https://ihre-website.de 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
```bash
# 1. Scan durchgeführt, Warnung auf /impressum/
python -m scanner https://ihre-website.de report --diff-only # Nur Diffs ansehen
python -m scanner https://ihre-website.de report # Vollständiger Report
python -m scanner https://ihre-website.de approve --url https://ihre-website.de/impressum/ --note "Impressum aktualisiert"
# 2. Oder alle Änderungen auf einmal (wenn alles geprüft)
python -m scanner https://ihre-website.de approve --all --note "Redesign vom 2026-06-12 freigegeben"
# 3. Nach großem Redesign: komplette neue Baseline
python -m scanner https://ihre-website.de approve --rebuild --note "Komplettes Redesign, alle Seiten neu"
```
---
## Workflow: Incident (Alarm)
1. Diffs sichten: `python -m scanner https://ihre-website.de report --diff-only`
2. Vollständigen Report lesen: `python -m scanner https://ihre-website.de report`
3. Verdächtige URLs manuell im Browser prüfen
4. Quelltext der betroffenen Seiten ansehen (insb. `display:none`-Bereiche)
5. Dienstleister kontaktieren, Zugriff auf Hosting prüfen
6. Nach Bereinigung: `python -m scanner https://ihre-website.de scan` — muss grün sein
7. Dann: `python -m scanner https://ihre-website.de approve --rebuild --note "Nach Incident bereinigt"`
**Wichtig**: Niemals `approve` auf eine kompromittierte Seite anwenden.
---
## Cron-Setup
Einrichten mit `crontab -e`, folgende Zeilen einfügen — je eine pro überwachter Website,
mit **Zeitversatz von mindestens 15 Minuten**. Ein Scan lädt alle Seiten einer Website herunter;
laufen mehrere Scans gleichzeitig, konkurrieren sie um Netzwerk und CPU und können die
überwachten Server unnötig belasten.
```cron
# Täglich 03:00 — bredelar.info
0 3 * * * cd /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten && python -m scanner --config bredelar.info/config.yaml scan >> bredelar.info/logs/cron.log 2>&1
# Täglich 03:15 — jamulix.de
15 3 * * * cd /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten && python -m scanner --config jamulix.de/config.yaml scan >> jamulix.de/logs/cron.log 2>&1
# Täglich 03:30 — www.bergbauspuren-bredelar.de
30 3 * * * cd /home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten && python -m scanner --config www.bergbauspuren-bredelar.de/config.yaml scan >> www.bergbauspuren-bredelar.de/logs/cron.log 2>&1
```
**Wichtig:** Der `cd`-Befehl ist nötig, damit `python -m scanner` das Paket findet.
Das Log landet je Site in `<site>/logs/cron.log`.
Nach dem Einrichten prüfen: `crontab -l`
### Neue Website hinzufügen
```bash
# Zielverzeichnis + config.yaml werden automatisch aus dem Template angelegt:
python -m scanner https://neue-domain.de init
# Externe Domains prüfen und in neue-domain.de/config/allowed_external.yaml eintragen
python -m scanner https://neue-domain.de approve --all --note "Erststand geprüft"
# Weiteren Cron-Eintrag ergänzen — mit 15 Minuten Abstand zum vorherigen
# neue-domain.de/ in .gitignore eintragen (data/, reports/, logs/)
```
Log-Rotation (`/etc/logrotate.d/scanner`):
```
/home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/*/logs/*.log {
daily
rotate 30
compress
missingok
notifempty
}
```
---
## Konfiguration
### E-Mail aktivieren
In `config.yaml`:
```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):
```bash
export SCANNER_SMTP_PASSWORD="geheimesPasswort"
```
### Webhook aktivieren
```yaml
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:
```yaml
- fonts.googleapis.com
- maps.googleapis.com
```
---
feat: KI-gestützte Inhaltsanalyse via OpenRouter (hash-gegated) Optionale semantische Prüfung von Text und Bildern (inkl. OCR) auf problematische Inhalte ohne Link-Signal: Pornografie, Propaganda, diffamierende/strafbare Texte, versteckter Spam, themenfremde Werbung, widersprüchliche Aussagen. Bewertet die thematische Passung zum deklarierten site_context — eingestreute Heimat-Begriffe täuschen die Erkennung nicht. Kern: - scanner/ai_analyzer.py: run_ai_analysis + score_ai_findings. Hash-Gate über data/ai_ledger.json → unveränderte Inhalte = Cache- Treffer = kein API-Call. Nur neue/geänderte Inhalte kosten etwas. - Modell-Kette mit zweifacher Eskalation (Stufe 1+2 free, Stufe 3 günstig bezahlt); eskaliert bei Fehler ODER Timeout (attempt_timeout). Erfolgreiches Modell wird im Ledger vermerkt. - KI-Funde sind auf GELB gedeckelt — ROT bleibt harten Integritäts- Signalen vorbehalten. Graceful degradation: ohne Key/bei Fehler wird übersprungen, Scan läuft unverändert weiter. Integration: - baseline.py: load/save_ai_ledger, dismiss_ai_entries. - config.py: ai_analysis-Block + ai_* Scoring-Schlüssel. - __main__.py: Einhängung in cmd_scan/cmd_check, ai-dismiss-Subcommand, approve quittiert zugehörige Funde, status-Anzeige, diff-only + report. - alerter.py + __main__.py: beanstandete Dateien erscheinen mit URL, Begründung und Quittier-Fingerprint in E-Mail UND Markdown-Report. - plain.py: laienverständliche KI-Sätze. API-Key nur aus Umgebungsvariable (OPENROUTER_API_KEY). Audio/Video als abschaltbare Hooks vorbereitet (default aus). Modelle live gegen OpenRouter verifiziert; Demo auf bredelar.info zeigte korrekte Erkennung (echter Inhalt clean, eingeschleuster Casino-Spam mit Heimat-Begriffen als hidden_spam erkannt). Tests: 227 grün (+26 für ai_analyzer, +1 für E-Mail-KI-Abschnitt). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:04:33 +02:00
## KI-Inhaltsanalyse (optional)
Der Integritäts-Kern erkennt strukturelle Manipulationen (fremde Links, Hidden Content,
Webshells). Die optionale KI-Analyse ergänzt ihn um **semantische** Prüfung von Text und
Bildern: Pornografie, Propaganda, diffamierende/strafbare Inhalte, versteckter Spam,
thematisch unpassende Werbung, widersprüchliche Aussagen — auch ohne Link-Signal und
inklusive Text in Bildern (OCR).
**Kostengate:** Jeder Inhalt bekommt einen Hash. Unveränderte Inhalte liegen mit ihrem
Verdikt im Cache (`data/ai_ledger.json`) → **kein API-Call**. Nur neue oder geänderte
Inhalte lösen eine (günstige) OpenRouter-Abfrage aus. Dadurch läuft die Analyse bei jedem
Scan mit und kostet an den meisten Tagen 0 €.
KI-Funde sind **auf Gelb gedeckelt** — sie lösen nie allein ROT aus (das bleibt harten
Integritäts-Signalen vorbehalten). Fehlt der API-Key oder schlägt eine Abfrage fehl, wird
die Analyse übersprungen und der Scan läuft unverändert weiter.
**„Nicht geprüft" ≠ „sauber":** Kann ein Inhalt trotz Modell-Eskalation und Wiederholung
(`max_retries`) nicht geprüft werden, wird er nicht still als unbedenklich gewertet, sondern
als **ungeprüft** mit URL in Terminal/Report/E-Mail ausgewiesen. Mit `unchecked_level: "yellow"`
hebt ein nicht prüfbarer Inhalt das Level auf mindestens Gelb an (Default `"warn"` = nur Hinweis).
feat: KI-gestützte Inhaltsanalyse via OpenRouter (hash-gegated) Optionale semantische Prüfung von Text und Bildern (inkl. OCR) auf problematische Inhalte ohne Link-Signal: Pornografie, Propaganda, diffamierende/strafbare Texte, versteckter Spam, themenfremde Werbung, widersprüchliche Aussagen. Bewertet die thematische Passung zum deklarierten site_context — eingestreute Heimat-Begriffe täuschen die Erkennung nicht. Kern: - scanner/ai_analyzer.py: run_ai_analysis + score_ai_findings. Hash-Gate über data/ai_ledger.json → unveränderte Inhalte = Cache- Treffer = kein API-Call. Nur neue/geänderte Inhalte kosten etwas. - Modell-Kette mit zweifacher Eskalation (Stufe 1+2 free, Stufe 3 günstig bezahlt); eskaliert bei Fehler ODER Timeout (attempt_timeout). Erfolgreiches Modell wird im Ledger vermerkt. - KI-Funde sind auf GELB gedeckelt — ROT bleibt harten Integritäts- Signalen vorbehalten. Graceful degradation: ohne Key/bei Fehler wird übersprungen, Scan läuft unverändert weiter. Integration: - baseline.py: load/save_ai_ledger, dismiss_ai_entries. - config.py: ai_analysis-Block + ai_* Scoring-Schlüssel. - __main__.py: Einhängung in cmd_scan/cmd_check, ai-dismiss-Subcommand, approve quittiert zugehörige Funde, status-Anzeige, diff-only + report. - alerter.py + __main__.py: beanstandete Dateien erscheinen mit URL, Begründung und Quittier-Fingerprint in E-Mail UND Markdown-Report. - plain.py: laienverständliche KI-Sätze. API-Key nur aus Umgebungsvariable (OPENROUTER_API_KEY). Audio/Video als abschaltbare Hooks vorbereitet (default aus). Modelle live gegen OpenRouter verifiziert; Demo auf bredelar.info zeigte korrekte Erkennung (echter Inhalt clean, eingeschleuster Casino-Spam mit Heimat-Begriffen als hidden_spam erkannt). Tests: 227 grün (+26 für ai_analyzer, +1 für E-Mail-KI-Abschnitt). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:04:33 +02:00
### Aktivieren
In `config.yaml`:
```yaml
ai_analysis:
enabled: true
api_key_env: "OPENROUTER_API_KEY"
site_context: "Heimat- und Vereinswebsite über die Bergbaugeschichte in Bredelar."
ai_confidence_min: 0.7
attempt_timeout: 30 # Zeitlimit je Modell-Versuch → eskaliert bei Langsamkeit
text:
enabled: true
models: # Kette: Stufe 1+2 free, Stufe 3 günstig bezahlt
- "qwen/qwen3-next-80b-a3b-instruct:free"
- "meta-llama/llama-3.3-70b-instruct:free"
- "google/gemini-2.5-flash-lite"
image:
enabled: true
models: # multimodal: Inhalt + OCR
- "google/gemma-4-31b-it:free"
- "nvidia/nemotron-nano-12b-v2-vl:free"
- "google/gemini-2.5-flash-lite"
```
Die Modelle werden als **Kette mit zweifacher Eskalation** abgearbeitet: Stufe 1 und 2 sind
kostenlose Modelle, Stufe 3 ein günstiges Bezahlmodell. Schlägt ein Modell fehl oder antwortet
es langsamer als `attempt_timeout`, wird automatisch zur nächsten Stufe eskaliert. Im Report
und Ledger wird festgehalten, welche Stufe das Verdikt geliefert hat.
`site_context` ist entscheidend: Die KI bewertet die **thematische Passung** zur
deklarierten Beschreibung, nicht einzelne Schlüsselwörter — eingestreute Heimat-Begriffe
machen Spam so nicht unauffällig.
API-Key als Umgebungsvariable setzen (nie in config.yaml):
```bash
export OPENROUTER_API_KEY="sk-or-..."
```
### Fehlalarm quittieren
Stuft die KI legitimen Inhalt fälschlich als auffällig ein:
```bash
python -m scanner https://ihre-website.de ai-dismiss --all # alle offenen Funde
python -m scanner https://ihre-website.de ai-dismiss --hash <fingerprint>
```
Ein `approve --all` / `--url` quittiert die zugehörigen KI-Funde automatisch mit.
### Modelle (OpenRouter)
Pro Modalität eine Kette mit zweifacher Eskalation (Stufe 1+2 free, Stufe 3 bezahlt):
| Zweck | Stufe 1 (free) | Stufe 2 (free) | Stufe 3 (bezahlt) |
|---|---|---|---|
| Text/Semantik | `qwen3-next-80b-a3b-instruct:free` | `llama-3.3-70b-instruct:free` | `gemini-2.5-flash-lite` |
| Bild + OCR | `gemma-4-31b-it:free` | `nemotron-nano-12b-v2-vl:free` | `gemini-2.5-flash-lite` |
Audio/Video sind als abschaltbare Hooks vorbereitet (`ai_analysis.audio/video`,
default aus).
---
## Verzeichnisstruktur
```
scanner.sh Wrapper-Script (ausführbar, startet python -m scanner)
meine-seite.de/ Template für neue Targets (config.yaml + config/)
ihre-website.de/ Automatisch angelegtes Zielverzeichnis
config.yaml Konfiguration für diese Site
config/
allowed_external.yaml Whitelist erlaubter externer Domains
ignore_rules.yaml Kommentierte Beispiele für Rausch-Unterdrückung
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
reports/ Generierte Reports (JSON + Markdown)
logs/ scanner.log + cron.log
scanner/ Python-Paket (Quellcode)
tests/ Automatisierte Tests
```
---
## Tests
```bash
pytest tests/ -v
```
---
## Erweiterungen (optional, nicht implementiert)
- KI-Analyse von Audio-/Video-Dateien (Hooks sind vorbereitet, default aus — siehe `ai_analysis.audio/video`)
- Telegram-Bot: direkter Alert-Kanal
- Automatische Archivierung alter Snapshots nach N Tagen