# ============================================================ # Integrity Scanner — Konfigurationsvorlage # ============================================================ # Verwendung: # 1. Dieses Verzeichnis kopieren: # cp -r meine-seite.de neue-domain.de # 2. In neue-domain.de/config.yaml alle Stellen mit # "meine-seite.de" durch die echte Domain ersetzen. # 3. Verzeichnis in .gitignore eintragen (data/reports/logs). # 4. Erste Einrichtung: # python -m scanner --config neue-domain.de/config.yaml init # ============================================================ # --- Ziel-Website --- target: "https://meine-seite.de" # User-Agent, mit dem der Scanner sich bei der Website meldet. # Bitte nicht auf einen Browser-Agent ändern — der Scanner soll erkennbar sein. user_agent: "integrity-scanner/1.0 (+security-monitoring)" # Timeout in Sekunden pro HTTP-Anfrage request_timeout: 20 # --- Verzeichnisse (müssen absolut angegeben werden) --- # Pfad zum Projektverzeichnis anpassen! data_dir: "/home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/meine-seite.de/data" reports_dir: "/home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/meine-seite.de/reports" logs_dir: "/home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/meine-seite.de/logs" config_dir: "/home/dschlueter/Python_Programs/integrity_scanner_fuer_statische_Webseiten/meine-seite.de/config" # --- Crawl-Einstellungen --- crawl: # Maximale Anzahl Seiten pro Crawl (Schutz vor endlosen Websites) max_pages: 200 # Wartezeit zwischen zwei Seitenanfragen in Sekunden (Server schonen) delay_seconds: 1.0 respect_robots_txt: false # Sitemap lesen, um nicht verlinkte Seiten (Orphan Pages) zu entdecken. # Der Scanner liest sitemap.xml (bzw. robots.txt → Sitemap:) und fügt alle # dort aufgeführten URLs in die Crawl-Queue ein. sitemap: true # Pfade, die vom Scan ausgeschlossen werden sollen. # Nützlich für Bereiche mit gewollt häufig wechselnden Inhalten, # z. B. RSS-Feeds, News-Archive, Nutzerprofile. # Beispiel: ["/rss/", "/feed/", "/news/archiv/", "/user/"] exclude_paths: [] # Dateiendungen, die nicht gecrawlt werden (Binärdateien) skip_extensions: - ".jpg" - ".jpeg" - ".png" - ".gif" - ".webp" - ".svg" - ".ico" - ".pdf" - ".zip" - ".woff" - ".woff2" - ".ttf" - ".otf" - ".eot" - ".mp4" - ".mp3" - ".webm" - ".avi" - ".mov" # --- Bewertungsgewichte --- # Jedes Ereignis erhöht den Score. Ab 20 = gelb, ab 60 = rot. # Die Werte können hier für diese Website angepasst werden. scoring: new_external_domain: 50 # Neuer Verweis auf fremde Domain new_internal_url: 30 # Neue interne Seite aufgetaucht missing_internal_url: 20 # Bekannte Seite verschwunden hidden_content: 40 # Unsichtbarer Text/Link (display:none) unexpected_canonical: 35 # Canonical-Tag geändert meta_refresh: 40 # Automatische Weiterleitung eingebaut unexpected_jsonld: 35 # Unbekannter JSON-LD-Typ large_text_addition: 20 # Großer neuer Textblock (>200 Zeichen) new_inline_script_suspicious: 30 # Verdächtiges inline JavaScript comment_links: 25 # Link in HTML-Kommentar versteckt new_broken_link: 20 # Neuer kaputt interner Link suspicious_filename: 60 # Webshell-typischer Dateiname verlinkt cloaking_extra_link: 60 # Nur für Google-Bot sichtbarer Link cloaking_extra_text: 40 # Nur für Google-Bot sichtbarer Text cloaking_vary_ua: 25 # Server sendet verschiedene Inhalte je UA changed_script: 40 # JavaScript-Datei verändert changed_stylesheet: 30 # CSS-Datei verändert changed_asset: 20 # Bild/PDF/sonstige Datei verändert thresholds: yellow: 20 # Ab diesem Score: Warnung (gelb) — Bitte prüfen red: 60 # Ab diesem Score: Alarm (rot) — Sofort prüfen large_text_block_chars: 200 # --- Wöchentliche Zusatzprüfungen --- # Laufen automatisch beim täglichen `scan` mit — kein separater Aufruf nötig. periodic_checks: enabled: true interval_days: 7 cloak_check: true # Prüft ob Google andere Inhalte sieht als Besucher ext_links: true # Prüft ob externe Links noch erreichbar sind assets: true # Prüft ob CSS/JS/Bilder sich verändert haben # --- E-Mail-Benachrichtigung --- # Passwort NIEMALS hier eintragen — nur als Umgebungsvariable: # export SCANNER_SMTP_PASSWORD="geheimesPasswort" alerting: min_level: "yellow" # "yellow" = bei Gelb und Rot mailen; "red" = nur bei Rot email: enabled: false # Auf true setzen wenn SMTP konfiguriert smtp_host: "mail.meine-seite.de" smtp_port: 587 smtp_tls: true smtp_user: "scanner@meine-seite.de" smtp_password_env: "SCANNER_SMTP_PASSWORD" from: "scanner@meine-seite.de" to: - "admin@meine-seite.de" webhook: enabled: false url: "" # z.B. Slack-Webhook oder Telegram-Bot-URL # --- KI-gestützte Inhaltsanalyse (optional, OpenRouter) --- # Prüft Text und Bilder semantisch auf problematische Inhalte (Pornografie, # Propaganda, Spam, themenfremde Werbung, strafbare/widersprüchliche Aussagen). # Kostengate: nur NEUE/GEÄNDERTE Inhalte lösen einen API-Call aus (Hash-Cache). # KI-Funde sind auf GELB gedeckelt. API-Key NUR als Umgebungsvariable setzen: # export OPENROUTER_API_KEY="sk-or-..." ai_analysis: enabled: false api_key_env: "OPENROUTER_API_KEY" # Themenbeschreibung der Website — die KI bewertet die Passung dazu, nicht # einzelne Schlüsselwörter. Bitte ausfüllen, wenn enabled: true. site_context: "" ai_confidence_min: 0.7 # KI-Funde sind auf Gelb gedeckelt — AUSSER diese schwerwiegenden Kategorien lösen # bei hoher Schwere + hoher Konfidenz ROT aus. Leere Liste [] = immer max. Gelb. red_categories: ["pornography", "defamation_illegal"] red_min_severity: "high" red_min_confidence: 0.9 attempt_timeout: 20 # HARTES Wanduhr-Limit je Modell-Versuch (Sek.) → Eskalation max_retries: 1 # Wiederholungen der ganzen Modell-Kette bei Komplettausfall retry_backoff_seconds: 2.0 # Parallelität: gleichzeitige API-Requests. I/O-gebunden → an die Rate-Limits der API # gebunden, NICHT an CPU-Kerne (vhost mit 4 Kernen wie 24-Kern-Rechner gleich steuerbar). max_concurrency: 8 # Adaptiver Router: ausgefallene/rate-limited Modelle nach so vielen Fehlern für die # Cooldown-Dauer überspringen; das schnellste gesunde Modell zuerst. breaker_failure_threshold: 2 breaker_cooldown_seconds: 120 refresh_models: true # tote Modell-Slugs failsafe über OpenRouter /models aussortieren # Verhalten, wenn Inhalte trotz Retry NICHT geprüft werden konnten (KI nicht erreichbar): # "warn" = sichtbarer Hinweis (Level bleibt unberührt) # "yellow" = zusätzlich Gesamt-Level auf mindestens Gelb anheben (für hohe Sicherheit) unchecked_level: "warn" # Modell-Kette mit zweifacher Eskalation: Stufe 1+2 free, Stufe 3 günstig bezahlt. # Schlägt ein Modell fehl oder antwortet zu langsam, wird zur nächsten Stufe eskaliert. text: enabled: true models: - "qwen/qwen3-next-80b-a3b-instruct:free" # Stufe 1: free - "meta-llama/llama-3.3-70b-instruct:free" # Stufe 2: free - "google/gemini-2.5-flash-lite" # Stufe 3: günstig bezahlt, zuverlässig min_chars: 200 # Drossel NUR für den Altbestand; 0 = unbegrenzt (volle Abdeckung im ersten Scan). # Geänderte/neue Seiten werden IMMER geprüft. Positiver Wert nur für sehr große Sites. max_pages_per_scan: 0 image: enabled: true models: - "google/gemma-4-31b-it:free" # Stufe 1: free, multimodal + OCR - "nvidia/nemotron-nano-12b-v2-vl:free" # Stufe 2: free, Vision - "google/gemini-2.5-flash-lite" # Stufe 3: günstig bezahlt, Vision # Drossel NUR für den Bild-Altbestand; 0 = unbegrenzt. Geänderte/neue/geflaggte # Bilder werden IMMER geprüft. Positiver Wert nur für sehr große Bildbestände. max_images_per_scan: 0 # Audio/Video: vorbereitet, default aus (Medien auf statischen Seiten selten). audio: enabled: false models: ["google/gemini-2.5-flash"] video: enabled: false models: ["google/gemini-2.5-flash"] # --- Normalisierung --- # Elemente, die vor dem Vergleich aus dem HTML entfernt werden # (z. B. dynamische Datums-/Zeitanzeigen die sich täglich ändern). normalization: strip_html_comments: true collapse_whitespace: true ignore_selectors: # - "#last-modified" # Element mit dieser ID ignorieren # - ".timestamp" # Alle Elemente mit dieser CSS-Klasse ignorieren ignore_patterns: # - '\d{1,2}\.\d{1,2}\.\d{4}' # Datumsangaben im Text ignorieren # - 'Stand:\s+\S+' # --- Erlaubte JSON-LD-Typen --- # Alles, was hier nicht steht und auf der Website auftaucht, löst Alarm aus. allowed_jsonld_types: - "Organization" - "WebSite" - "WebPage" - "Article" - "BreadcrumbList" - "ItemList" - "LocalBusiness" - "Place" - "Person" - "Event" - "FAQPage" - "Question" - "Answer" - "ImageObject" - "SiteLinksSearchBox" - "ContactPage" - "AboutPage" # --- Erwartete Security-Header --- # Fehlen diese Header, erscheint ein Hinweis im Report (kein Score-Einfluss). security_headers: - "Content-Security-Policy" - "Strict-Transport-Security" - "X-Content-Type-Options" - "Referrer-Policy"