fix: truncated ISOBMFF containers still run the C2PA byte-scan fallback (#176)

* fix: truncated ISOBMFF containers still run the C2PA byte-scan fallback

inspect_isobmff returned early when no boxes parse, skipping the
whole-file C2PA byte scan that every sibling inspector (png, jpeg,
gif, tiff) reaches even after a truncation: a first box whose size
field overruns the file — the truncated AVIF/HEIC/MP4 download shape —
reported has_c2pa=False with only a not-a-valid finding while literal
b"c2pa" sat in the file (#167). Also reached for MP4/MOV/M4A through
av_meta._inspect_mp4.

Run the byte scan before reporting the parse failure: a truncated
container with markers byte-scans to has_c2pa=True (finding plus the
parse-failure note, so the truncation isn't hidden); a walkable
container keeps its stronger box-level findings; a markerless
truncated container keeps the plain not-a-valid shape.

* fix: satisfy ruff in isobmff truncated byte-scan tests

- drop the unused # noqa: E402 (already per-file-ignored for tests/**)
- bind the unused has_ai unpacked value to _ (RUF059)

---------

Co-authored-by: yzxcj797 <yzxcj797@users.noreply.github.com>
Co-authored-by: Guillaume Meyer (The Opinionated Man) <1385518+guillaumemeyer@users.noreply.github.com>
Co-authored-by: guillaumemeyer <guillaumemeyer@users.noreply.github.com>
This commit is contained in:
yzxcj797
2026-08-19 12:03:33 -07:00
committed by GitHub
co-authored by yzxcj797 Guillaume Meyer guillaumemeyer
parent 1cf93d0d60
commit 0f41bd3994
2 changed files with 70 additions and 1 deletions
+11 -1
View File
@@ -512,7 +512,17 @@ def inspect_isobmff(data: bytes, fmt: str = "avif") -> tuple[bool, bool, list[st
boxes = _parse_isobmff_boxes(data)
if not boxes:
return False, False, [f"not a valid {fmt.upper()} (no ISOBMFF boxes found)"]
# Box parsing failed (e.g. the first box's size overruns a truncated
# download) — that is exactly when the whole-file byte scan below is
# most useful, and every sibling inspector (png/jpeg/gif/tiff) still
# runs its equivalent after a truncation. Run the fallback, then
# report the parse failure alongside whatever it found (#167).
whole = _contains_any(data, C2PA_MARKERS)
if whole:
findings.append(f"byte-scan C2PA markers: {', '.join(whole[:6])}")
has_c2pa = True
findings.append(f"not a valid {fmt.upper()} (no ISOBMFF boxes found)")
return has_c2pa, has_ai or has_c2pa, findings
for fourcc, payload, _, _ in boxes:
name = fourcc.decode("latin-1", errors="replace")
+59
View File
@@ -0,0 +1,59 @@
"""Truncated ISOBMFF containers still run the whole-file C2PA byte scan (#167).
A first box whose size overruns the file (a truncated AVIF/HEIC/MP4 download)
used to return early with a not-a-valid finding, skipping the byte-scan
fallback every sibling inspector reaches literal b"c2pa" could be present
and the report still said clean.
"""
from __future__ import annotations
import struct
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPTS = ROOT / "service" / "scripts"
sys.path.insert(0, str(SCRIPTS))
import image_meta
def _avif(marker: bytes, first_box_overruns: bool) -> bytes:
ftyp = b"\x00\x00\x00\x14ftypavif" + b"\x00\x00\x00\x00" # 20-byte ftyp
body = marker + b"\x00" * 16
if first_box_overruns:
# First box (ftyp) declares a size larger than the whole file.
size = len(ftyp) + len(body) + 64
head = struct.pack(">I", size) + b"ftypavif" + b"\x00" * 8
return head + body
return struct.pack(">I", len(ftyp)) + b"ftypavif" + b"\x00" * 8 + body
def test_truncated_avif_still_bytescans_for_c2pa():
data = _avif(b"c2pa contentcredentials", first_box_overruns=True)
assert b"c2pa" in data
has_c2pa, _, findings = image_meta.inspect_isobmff(data, fmt="avif")
# The byte-scan fallback fires instead of the early clean-looking return.
assert has_c2pa is True, findings
assert any("byte-scan C2PA markers" in f for f in findings), findings
# The parse failure is still reported.
assert any("no ISOBMFF boxes found" in f for f in findings), findings
def test_intact_avif_box_parse_path_unchanged():
data = _avif(b"c2pa contentcredentials", first_box_overruns=False)
has_c2pa, _, findings = image_meta.inspect_isobmff(data, fmt="avif")
assert has_c2pa is True
# A walkable container finds the C2PA box directly (stronger evidence than
# the byte scan); the parse-failure note must not appear.
assert any("top-level box" in f and "c2pa" in f.lower() for f in findings), findings
assert not any("no ISOBMFF boxes found" in f for f in findings)
def test_truncated_markerless_avif_reports_parse_failure():
data = _avif(b"nothing interesting", first_box_overruns=True)
has_c2pa, _, findings = image_meta.inspect_isobmff(data, fmt="avif")
assert has_c2pa is False
assert findings == ["not a valid AVIF (no ISOBMFF boxes found)"]