fix: audit hardening — input validation, error handling, and robustness (#25)
* fix: audit hardening — input validation, error handling, and robustness - immich_api: guard person["id"] with .get() + early return on missing field - immich_api: include page number in pagination exception log - immich_api: validate faces response is a list before indexing - executor: wrap Image.open() in try/except for non-image HTTP responses - executor: strip leading 'v' from Frigate version before parsing (v0.16.0 was misread) - config: wrap FRIGATE_SCORE_CEILING float() parse in try/except with warning - config: warn when both DATA_DIR and legacy CWD config files exist simultaneously - scheduler: wrap PID file write in try/except so /tmp failures don't crash startup - scheduler: clamp sleep to 60s max to bound recovery time after NTP clock jumps - frigate_api: log unexpected non-list type in get_frigate_person_files at DEBUG * fix: LIMIT env var crash and symlink guard on person output dir - jobs: wrap int(LIMIT) parse in try/except — bad value (e.g. "30.5", "all") now logs a warning and falls back to the default instead of crashing - executor: check for symlink before shutil.rmtree on person_dir — prevents following a symlink out of OUTPUT_DIR on a shared volume * chore: bump version to 0.5.3
This commit is contained in:
+12
-2
@@ -100,6 +100,9 @@ def execute_jobs(jobs: list[dict]) -> None:
|
||||
logger.error(str(e))
|
||||
continue
|
||||
# Face crops are transient (uploaded then discarded); wipe before each run.
|
||||
if os.path.islink(person_dir):
|
||||
logger.error("person_dir %s is a symlink — refusing to remove", person_dir)
|
||||
continue
|
||||
if os.path.isdir(person_dir):
|
||||
shutil.rmtree(person_dir)
|
||||
os.makedirs(person_dir, exist_ok=True)
|
||||
@@ -137,7 +140,14 @@ def execute_jobs(jobs: list[dict]) -> None:
|
||||
headers=get_headers(),
|
||||
timeout=30,
|
||||
)
|
||||
img = Image.open(BytesIO(resp.content)) if resp.ok else None
|
||||
if resp.ok:
|
||||
try:
|
||||
img = Image.open(BytesIO(resp.content))
|
||||
except Exception:
|
||||
logger.warning("Invalid image data for asset %s", asset["id"])
|
||||
img = None
|
||||
else:
|
||||
img = None
|
||||
|
||||
if img is None:
|
||||
progress.console.print(f"[red]Failed download {asset['id']}[/red]")
|
||||
@@ -208,7 +218,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
_frigate_version = get_frigate_version()
|
||||
if _frigate_version is not None:
|
||||
try:
|
||||
parts = [int(x) for x in _frigate_version.split("-")[0].split(".") if x.isdigit()]
|
||||
parts = [int(x) for x in _frigate_version.lstrip("v").split("-")[0].split(".") if x.isdigit()]
|
||||
if len(parts) >= 2 and (parts[0], parts[1]) < (0, 16):
|
||||
rprint(
|
||||
f" [yellow]⚠ Frigate {_frigate_version} detected — "
|
||||
|
||||
Reference in New Issue
Block a user