fix: Bugfixes, toten Code entfernt, Cache-Normalisierung & Session
Echte Bugs: - extractor: JSON-LD-Crash bei Nicht-Dict-Items (isinstance-Guard) - baseline/__main__: Crawl-Fehler ins Snapshot-Manifest -> erscheinen im Report - __main__: Whitelist-/Header-/Webshell-Checks nur noch auf status==200 - crawler: Noise-Param-Regex auf Voll-Key (view=/value= nicht mehr verworfen) - differ/__main__: unerwartetes JSON-LD via eigenem Kanal, auch auf unveraenderten Seiten erkannt, kein Re-Alert auf bereits genehmigte Typen Aufgeraeumt: - checker: check_internal_paths, find_broken_pages, canonical_is_hijacked, check_jsonld_types entfernt (nicht verdrahtet) - allowed_paths.yaml-Logik und tote Scoring-Keys entfernt - tote Imports entfernt Neuer aktiver Schutz: - Webshell-/Backdoor-Dateinamen-Check verdrahtet (suspicious_filename: 60). Regex wortgrenzen-verankert gegen Fehlalarm auf PSEMailerAntispam.js Effizienz/Struktur: - crawler nutzt requests.Session (keep-alive) - Cache-Buster-Normalisierung an einer Stelle (Extraktion) -> stabile Snapshots, differ wieder reiner Set-Diff Tests: 111 gruen (neu: test_checker.py + Regressionstests) CLAUDE.md aktualisiert Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b3ef3a90d4
commit
68243a97b9
13 changed files with 323 additions and 153 deletions
|
|
@ -43,7 +43,11 @@ def diff_text(old: str, new: str, context: int = 2) -> list[str]:
|
|||
|
||||
|
||||
def diff_link_set(old_list: list[dict], new_list: list[dict]) -> dict:
|
||||
"""Compare two link lists by URL."""
|
||||
"""Compare two link lists by URL.
|
||||
|
||||
Cache-buster query params are stripped at extraction time
|
||||
(extractor.strip_cache_params), so stored URLs are already stable here.
|
||||
"""
|
||||
old_urls = {l["url"] for l in old_list if isinstance(l, dict) and "url" in l}
|
||||
new_urls = {l["url"] for l in new_list if isinstance(l, dict) and "url" in l}
|
||||
return {
|
||||
|
|
@ -228,6 +232,20 @@ def compare_snapshots(baseline_pages: dict, current_pages: dict, cfg: dict) -> d
|
|||
if url in current_pages
|
||||
]
|
||||
|
||||
# Unexpected JSON-LD @types — independent of page_diffs.
|
||||
# Only flag types that are NOT allowed AND were not already in the baseline
|
||||
# for that URL (avoids re-alerting on a pre-approved page).
|
||||
allowed_jsonld = set(cfg.get("allowed_jsonld_types", []))
|
||||
unexpected_jsonld: list[dict] = []
|
||||
for url, page in current_pages.items():
|
||||
base_types = {
|
||||
j.get("type") for j in baseline_pages.get(url, {}).get("jsonld", [])
|
||||
}
|
||||
for j in page.get("jsonld", []):
|
||||
t = j.get("type")
|
||||
if t not in allowed_jsonld and t not in base_types:
|
||||
unexpected_jsonld.append({"url": url, "type": t})
|
||||
|
||||
return {
|
||||
"new_internal_urls": new_urls,
|
||||
"missing_internal_urls": missing_urls,
|
||||
|
|
@ -235,6 +253,7 @@ def compare_snapshots(baseline_pages: dict, current_pages: dict, cfg: dict) -> d
|
|||
"removed_external_domains": sorted(old_ext - new_ext),
|
||||
"page_diffs": page_diffs,
|
||||
"new_pages_analysis": new_pages_analysis,
|
||||
"unexpected_jsonld": unexpected_jsonld,
|
||||
"new_broken_urls": new_broken,
|
||||
"known_broken_urls": known_broken,
|
||||
"total_pages_checked": len(common_urls),
|
||||
|
|
@ -305,11 +324,6 @@ def score_diff(diff: dict, cfg: dict) -> dict:
|
|||
add(sc.get("new_inline_script_suspicious", 30),
|
||||
f"{u}: Verdächtiges Inline-Script [{', '.join(s.get('patterns', []))}]")
|
||||
|
||||
for j in pd.get("new_jsonld", []):
|
||||
if j.get("unexpected"):
|
||||
add(sc.get("unexpected_jsonld", 35),
|
||||
f"{u}: Unerwartetes JSON-LD @type={j.get('type')}")
|
||||
|
||||
if pd.get("canonical_changed"):
|
||||
add(sc.get("unexpected_canonical", 35),
|
||||
f"{u}: Canonical geändert → {pd.get('new_canonical')}")
|
||||
|
|
@ -326,6 +340,14 @@ def score_diff(diff: dict, cfg: dict) -> dict:
|
|||
f"Neuer kaputte Link: {entry['url']} (HTTP {entry['status']})")
|
||||
# known_broken_urls are reported but not scored — they were already in the baseline
|
||||
|
||||
for entry in diff.get("unexpected_jsonld", []):
|
||||
add(sc.get("unexpected_jsonld", 35),
|
||||
f"{entry['url']}: Unerwartetes JSON-LD @type={entry['type']}")
|
||||
|
||||
for entry in diff.get("suspicious_filenames", []):
|
||||
add(sc.get("suspicious_filename", 60),
|
||||
f"{entry['page']}: Verdächtiger Dateiname {entry['url']}")
|
||||
|
||||
# New pages: immediate suspicious content counts too
|
||||
for npa in diff.get("new_pages_analysis", []):
|
||||
u = npa["url"]
|
||||
|
|
@ -337,8 +359,7 @@ def score_diff(diff: dict, cfg: dict) -> dict:
|
|||
add(sc.get("meta_refresh", 40), f"{u} (neu): Meta-Refresh")
|
||||
if npa.get("comment_links"):
|
||||
add(sc.get("comment_links", 25), f"{u} (neu): Kommentar-Link")
|
||||
if npa.get("unexpected_jsonld"):
|
||||
add(sc.get("unexpected_jsonld", 35), f"{u} (neu): Unerwartetes JSON-LD")
|
||||
# Unexpected JSON-LD on new pages is covered by the unexpected_jsonld channel.
|
||||
|
||||
yellow = thr.get("yellow", 20)
|
||||
red = thr.get("red", 60)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue