Skip to content

Eval: check E2, saved files segment by segment - #15

Merged
06pratyush merged 4 commits into
mainfrom
eval-files
Oct 28, 2026
Merged

06pratyush merged 4 commits into
mainfrom
eval-files

Conversation

@shashwat-deep

@shashwat-deep shashwat-deep commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

First of the privacy checks (protocol part E): E2, the structure of saved files. Stacked on #14, which is stacked on #13, #12, #10, #9 and #2; merge those first.

What is in it

  • eval/check_files.py FILES_OR_FOLDERS… [--out report.json] parses every saved JPEG and PNG with a parser of its own, independent of the app's stripJpeg and of the privacy suite's JPEG helper. It applies the protocol's E2 rule:

    • no APP1 (EXIF, XMP), APP11 (C2PA, JUMBF) or APP13 (IPTC) segment;
    • no thumbnail (JFIF thumbnail bytes or a JFXX extension);
    • an ICC profile only if every file checked in the run has the very same one. A profile that only some files carry fails too, since it came from the input;
    • nothing after the end-of-image marker.

    For PNG, the same rule rules out eXIf, tEXt, zTXt, iTXt, tIME and caBX (C2PA) chunks and anything after IEND, and chunk CRCs are checked. Other segments (a comment, an Adobe or MPF segment) are listed for us to judge. A broken file fails without stopping the run, and the script exits with an error if any file fails. The report holds segment names and sizes, never pixels or metadata values.

  • 13 tests on files made to carry each kind of hidden data (91 eval tests in total).

  • I saved three images from the draw through the deployed app on GitHub Pages in headless Chromium and checked the copies: all three pass, with segments JFIF, DQT, DQT, SOF0, DHT ×4, SOS, no ICC profile and nothing after the end.

    • Those three images had not been reviewed. Running the app on them went against part B, which says one of us looks at every sampled image before any detector runs on it. The copies were kept only in a temporary folder and no longer exist. Until the review is done, checks like this use synthetic images or our own photos.

After Pratyush's review

  • The tests name files with Path(...).name, so they pass on Windows (15 E2 tests, 93 eval tests).
  • A JFIF segment passes only at exactly the 14 bytes of a plain header. Anything longer, where bytes could hide, or shorter fails, as in the privacy suite.

For both of us

  • Part E of the protocol now spells out the PNG equivalents of the rule, and that the ICC comparison runs over all the saved files of a run together.
  • E2 also covers "every saved file … from the privacy suite". @06pratyush, the suite currently keeps its saved copies only in Playwright's temporary downloads. Keeping them, for example under tests/test-results/, would let us run check_files.py on them in CI. That's your call, since tests/ is yours.

E1 (exiftool on our own phone photos) needs exiftool, which isn't installed on my machine yet. E3 (perceptual-hash distance) comes next.

🤖 Generated with Claude Code

shashwat-deep and others added 2 commits October 28, 2026 10:28
check_files.py parses each saved JPEG or PNG with a parser of its own and
applies the protocol's E2 rule: no EXIF, XMP, IPTC or C2PA, no thumbnail, an
ICC profile only if every file of the run has the same one, and nothing
after the end of the image. Other segments are listed for the authors to
judge. Part E of the protocol now gives the PNG equivalents of the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An ICC profile now passes only if every file of the run carries the very same
one, so a profile that only some saved files have (one taken from the input)
fails too. PNG chunk CRCs are checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@06pratyush
06pratyush changed the base branch from eval-luma to main October 28, 2026 10:27

@06pratyush 06pratyush left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two fixes before this can merge, and one question. #2 to #14 are merged; this PR now sits on main.

  1. 12 of the 13 new tests fail on Windows (79 passed, 12 failed for pytest eval/tests here). eval/tests/test_check_files.py:35 indexes the report by e['file'].rsplit('/', 1)[-1], but on Windows str(path) uses backslashes, so every lookup ('plain.png', 'exif.jpg', …) raises KeyError. Path(e['file']).name fixes it; the checker itself is fine. CI runs only the app's tests, which is why this didn't show up there.
  2. The JFIF check lets extra bytes through. jpeg_name() marks an APP0 JFIF segment clean when its thumbnail size bytes are 0, whatever the segment's length, so bytes appended inside the JFIF header pass E2. A clean JFIF header is exactly 14 bytes plus 3 per thumbnail pixel; failing any other length closes this. The privacy suite in tests/ checks it the same way.
  3. Question. The description says three test images were saved through the deployed app, one of them stored turned, so they came from the Open Images draw. Part B says one author looks at every sampled image "before any detector runs on it", and eval/manifest/review.csv is still empty. Were those three reviewed first? If not, please note it, and let's use synthetic images or our own photos for checks like this until the review is done.

🤖 Review written with Claude Code

shashwat-deep and others added 2 commits October 28, 2026 16:15
The tests name files with Path(...).name, so they pass on Windows too. A JFIF
segment now passes only at exactly the 14 bytes of a plain header; a longer
one, where bytes could hide, or a shorter one fails. The AI-use row now says
that the three images saved through the deployed app came from the draw
before it was reviewed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shashwat-deep
shashwat-deep marked this pull request as ready for review October 28, 2026 12:05

@06pratyush 06pratyush left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix does what I asked: the JFIF segment must now be exactly 14 bytes, and the new cases cover one with bytes after it (jfif-extra.jpg) and one cut short (jfif-short.jpg). The eval tests pass on Windows at the top of the stack (104, none skipped). Approving.

@06pratyush
06pratyush merged commit f7ae92b into main Oct 28, 2026
2 checks passed
@06pratyush
06pratyush deleted the eval-files branch October 28, 2026 16:37
06pratyush added a commit that referenced this pull request Oct 28, 2026
Resolves the conflict in docs/ai-use.md, where both sides added a row:
keeps both, Shashwat's row for check_files.py (#15, merged first) before
this branch's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
06pratyush added a commit that referenced this pull request Oct 28, 2026
Resolves the conflict in docs/ai-use.md, where main added the rows for
#15, #17, #18 and #19 and this branch has its own: keeps all five,
main's rows first. The merge brings in only eval/ and docs changes;
nothing under app/ or tests/ changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants