Skip to content

Commit 54653c6

Browse files
Add files via upload
1 parent 363843f commit 54653c6

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

scripts/netshield_common.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,3 +1376,61 @@ def write_text_atomic(filepath, content):
13761376
except OSError:
13771377
pass
13781378
raise
1379+
1380+
# ═══════════════════════════════════════════════════════════════
1381+
# Auto-Discovered Feeds: Schema- und URL-Validierung
1382+
# ═══════════════════════════════════════════════════════════════
1383+
1384+
def validate_auto_feeds(auto_data):
1385+
"""Filtert auto_discovered_feeds.json-Eintraege auf safe Schema + URL.
1386+
1387+
Hintergrund (FIX BUG-AUTOFEEDS-VALIDATE): Vorher las
1388+
update_combined_blacklist die Datei direkt mit
1389+
``auto_data.get("feeds", [])`` ohne Schema-/URL-Pruefung. Risiko:
1390+
Ein Angreifer mit Repo-Schreibrechten konnte malicious URLs in
1391+
den Feed-Loop einschmuggeln, ohne den Code-Review-Pfad ueber
1392+
SOURCES zu durchlaufen. fetch_url's SSRF-Schutz blockt zwar
1393+
localhost/RFC1918, aber externe Angreifer-URLs mit boeswilligen
1394+
IP-Listen waeren durch.
1395+
1396+
Akzeptiert:
1397+
- dict-Root mit "feeds"-Liste
1398+
- pro Eintrag: dict mit string-keys "name" und "url"
1399+
- URL muss http:// oder https:// sein
1400+
1401+
Args:
1402+
auto_data: Geparstes JSON aus auto_discovered_feeds.json.
1403+
1404+
Returns:
1405+
tuple[list[dict], int]: (akzeptierte_feeds, anzahl_verworfen)
1406+
1407+
Raises:
1408+
ValueError: Wenn Root nicht dict oder feeds nicht list ist
1409+
(= grundsaetzlich kaputtes Schema, kein partieller
1410+
Restore moeglich).
1411+
"""
1412+
if not isinstance(auto_data, dict):
1413+
raise ValueError(
1414+
f"auto_discovered_feeds Root ist {type(auto_data).__name__}, "
1415+
f"erwartet dict")
1416+
raw_feeds = auto_data.get("feeds", [])
1417+
if not isinstance(raw_feeds, list):
1418+
raise ValueError(
1419+
f"auto_discovered_feeds 'feeds' ist {type(raw_feeds).__name__}, "
1420+
f"erwartet list")
1421+
accepted = []
1422+
rejected = 0
1423+
for feed in raw_feeds:
1424+
if not isinstance(feed, dict):
1425+
rejected += 1
1426+
continue
1427+
name = feed.get("name")
1428+
url = feed.get("url")
1429+
if not isinstance(name, str) or not isinstance(url, str):
1430+
rejected += 1
1431+
continue
1432+
if not (url.startswith("https://") or url.startswith("http://")):
1433+
rejected += 1
1434+
continue
1435+
accepted.append({"name": name, "url": url})
1436+
return accepted, rejected

0 commit comments

Comments
 (0)