second commit
This commit is contained in:
38
app/security/av_scan.py
Normal file
38
app/security/av_scan.py
Normal file
@ -0,0 +1,38 @@
|
||||
"""
|
||||
AV-Scan-Hook fuer Datei-Uploads (Konzept 4.3/6.6).
|
||||
|
||||
Bewusst als duenner Wrapper um ein optionales ClamAV (clamd) gehalten: ist
|
||||
kein Scanner konfiguriert/erreichbar, wird das Ergebnis "skipped" vermerkt
|
||||
statt die Datei stillschweigend als "sauber" zu markieren -- Admins sehen im
|
||||
Audit-/Filetransfer-Log damit ehrlich, ob wirklich gescannt wurde.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import shutil
|
||||
import subprocess # nosec B404 -- benoetigt fuer den optionalen ClamAV-Aufruf, siehe unten
|
||||
|
||||
|
||||
def scan_bytes(data: bytes) -> str:
|
||||
"""Rueckgabe: 'clean', 'infected:<signature>' oder 'skipped:<grund>'."""
|
||||
clamdscan = shutil.which("clamdscan")
|
||||
if not clamdscan:
|
||||
return "skipped:clamdscan_not_installed"
|
||||
try:
|
||||
# Argumentliste ist vollstaendig fest (kein shell=True, keine
|
||||
# Nutzereingabe im Kommando selbst); die hochgeladenen Datei-Bytes
|
||||
# werden ausschliesslich ueber stdin (input=data) uebergeben, nie als
|
||||
# Kommandozeilen-/Pfadargument -- Command-Injection ueber Dateinamen
|
||||
# o.ae. ist damit ausgeschlossen.
|
||||
proc = subprocess.run( # nosec B603
|
||||
[clamdscan, "--stdout", "--no-summary", "-"],
|
||||
input=data, capture_output=True, timeout=30,
|
||||
)
|
||||
except (subprocess.TimeoutExpired, OSError):
|
||||
return "skipped:scan_error"
|
||||
|
||||
output = proc.stdout.decode(errors="replace")
|
||||
if proc.returncode == 0:
|
||||
return "clean"
|
||||
if proc.returncode == 1:
|
||||
return f"infected:{output.strip()}"
|
||||
return "skipped:scan_error"
|
||||
Reference in New Issue
Block a user