You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+8-4Lines changed: 8 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,9 +12,11 @@ Current implementation:
12
12
- JPEG EXIF, XMP, ICC, Photoshop/IPTC, and comment container detection;
13
13
- shared little- and big-endian TIFF/EXIF decoder;
14
14
- iterative IFD0, ExifIFD, GPSIFD, and next-IFD traversal with cycle and depth protection;
15
-
- common TIFF, EXIF, and GPS field decoding with exact rational values.
15
+
- common TIFF, EXIF, and GPS field decoding with exact rational values;
16
+
- deterministic whole-segment JPEG Privacy Clean with byte-preserving reconstruction;
17
+
- structured JPEG verification for observable container presence or absence.
16
18
17
-
Not implemented: MakerNote or thumbnail decoding, XMP/IPTC/ICC payload parsing, PNG/WebP container parsing, metadata cleaning, and verification.
19
+
Not implemented: MakerNote or thumbnail decoding, XMP/IPTC/ICC payload parsing, PNG/WebP container parsing or cleaning, and PNG/WebP verification.
18
20
19
21
## Format status
20
22
@@ -38,11 +40,13 @@ import {
38
40
39
41
GPS rational components remain exact numerator/denominator pairs; decimal coordinates are not derived. Unknown TIFF tags and MakerNote are represented structurally without dumping or recursively parsing their payloads.
40
42
41
-
`cleanMetadata` and `verifyMetadata` still throw a typed `NotImplementedError`.
43
+
`cleanMetadata` supports JPEG. Its default policy removes complete EXIF, standard/extended XMP, Photoshop/IPTC, and COM segments while preserving ICC, JFIF/JFXX, Adobe APP14, unknown APP segments, structural data, scan bytes, and trailing bytes. It returns a separate output, container-level change evidence, and an inspection report of that output.
44
+
45
+
`verifyMetadata` supports JPEG expectations of `absent`, `present`, or `ignore` for EXIF, XMP, IPTC, comments, and ICC. The default checks the four privacy-clean removal targets. A single-file verification can observe presence or absence; it cannot prove that bytes came from an original file.
42
46
43
47
## Security philosophy
44
48
45
-
Every byte is untrusted. All offsets are interpreted within bounded views, traversal is iterative and limited, repeated IFD offsets are rejected, and malformed entries recover without unchecked access. Unknown structures remain unknown and should be preserved by future cleaning. See the [security model](docs/security-model.md), [architecture](docs/architecture.md), and [cleaning policy](docs/cleaning-policy.md).
49
+
Every byte is untrusted. All offsets are interpreted within bounded views, traversal is iterative and limited, repeated IFD offsets are rejected, and malformed entries recover without unchecked access. Unknown JPEG APP structures remain unknown and are preserved by cleaning. See the [security model](docs/security-model.md), [architecture](docs/architecture.md), and [cleaning policy](docs/cleaning-policy.md).
Copy file name to clipboardExpand all lines: docs/architecture.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,3 +32,17 @@ Unknown tags retain namespace, tag number, TIFF type, count, entry offset, and s
32
32
-`container-partial`: JPEG traversal stopped on corruption, truncation, or a limit.
33
33
-`metadata-partial`: JPEG container traversal completed and common TIFF/EXIF decoding was attempted; XMP/IPTC/ICC and unknown fields remain incomplete.
34
34
-`metadata-inspected`: reserved for future broader decoders.
35
+
36
+
## JPEG clean and verify flow
37
+
38
+
```text
39
+
input JPEG
40
+
→ bounded JPEG parser and existing APP classification
41
+
→ direct keep/remove policy
42
+
→ checked retained ranges
43
+
→ one output allocation and ordered byte copies
44
+
→ inspectMetadata(output)
45
+
→ structured verification checks
46
+
```
47
+
48
+
The parser remains the structural source of truth. Internal rewrite ranges include marker fill bytes associated with a removed marker while public source offsets retain their existing meaning. Cleaning does not invoke TIFF decoding on the source: a structurally bounded EXIF APP1 can be removed even if its TIFF body is malformed. The post-write inspection and verifier use the normal inspection layer.
Cleaning is not implemented in Sprint 0. This document records the intended conservative policy for future work.
3
+
JPEG Privacy Clean removes complete recognized metadata containers. It never rewrites TIFF/EXIF fields, XMP XML, IPTC blocks, comments, or ICC payloads.
4
4
5
-
An initial privacy-clean mode should remove EXIF, GPS, XMP, IPTC, comments, and privacy-relevant textual metadata. It should preserve the encoded image payload, required container structures, ICC and other color profiles, rendering-critical metadata, and unknown structures unless the relevant format specification proves removal is safe.
| Structural markers and image/scan data | Preserve |
17
+
| Data after EOI | Preserve |
6
18
7
-
For v0.1, whole EXIF containers are preferred over selective TIFF rewriting:
19
+
Every recognized instance is handled independently and retained content keeps its original order and bytes. Unknown APP removal is intentionally unavailable in Sprint 4. Callers may override the four removal booleans and ICC preservation; `preserveColorProfiles` remains a deprecated alias for `preserveIcc`.
8
20
9
-
```text
10
-
JPEG APP1 EXIF → remove whole EXIF APP1
11
-
PNG eXIf → remove whole eXIf chunk
12
-
WebP EXIF → remove whole EXIF chunk
13
-
```
21
+
v0.1 removes the entire EXIF APP1, including malformed TIFF bodies whose JPEG segment boundary is valid. Selective GPS or tag rewriting and TIFF reserialization are deferred.
14
22
15
-
Selective EXIF field rewriting is postponed. This reduces offset-rewrite complexity and makes cleaner behavior easier to audit. Unaffected bytes should remain byte-for-byte identical whenever the container format permits it, and output must be re-inspected rather than trusted merely because a write completed.
23
+
`cleanMetadata` returns a new `Uint8Array`, container-level removed/preserved records, diagnostics, and an inspection report of the produced JPEG. A structurally incomplete JPEG is rejected before allocation. PNG, WebP, and unknown inputs return a typed unsupported-format error.
Copy file name to clipboardExpand all lines: docs/format-support.md
+8-1Lines changed: 8 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,8 @@
11
11
| MakerNote decoding | Not supported | Not supported | Not supported |
12
12
| XMP payload decoding | Not yet | Not yet | Not yet |
13
13
| IPTC/ICC payload decoding | Not yet | Not yet | Not yet |
14
-
| Cleaning and verification | Not yet | Not yet | Not yet |
14
+
| Whole-container cleaning | Supported | Not yet | Not yet |
15
+
| Structured verification | Supported | Not yet | Not yet |
15
16
16
17
## TIFF/EXIF subset
17
18
@@ -28,3 +29,9 @@ Unknown tags remain structurally represented without speculative meaning or larg
28
29
## Remaining container support
29
30
30
31
JPEG marker and scan traversal remains supported. XMP, ICC, and Photoshop/IPTC signatures are container-detected only. PNG requires its complete signature and WebP requires `RIFF....WEBP`; their chunks and metadata are not parsed yet.
32
+
33
+
## JPEG cleaning and verification
34
+
35
+
JPEG Privacy Clean removes recognized EXIF, standard/extended XMP, Photoshop/IPTC, and comment segments. ICC, JFIF/JFXX, Adobe APP14, unknown APP segments, structural markers, all scan data, and trailing bytes are retained. Structurally incomplete JPEGs are rejected; malformed TIFF inside a bounded removable EXIF segment does not block cleaning.
36
+
37
+
Verification reports observable container presence or absence for EXIF, XMP, IPTC, comments, and ICC. It does not decode XMP/IPTC/ICC payloads or prove preservation from an original input.
4. Core functions make no network requests and access no filesystem or DOM APIs.
11
11
5. Image pixel payloads are never decoded.
12
12
6. Unknown metadata is not deleted or assigned speculative meaning.
13
-
7.ICC and color data will be preserved by default during future cleaning.
14
-
8. Cleaner output must eventually be independently inspected and verified.
13
+
7.JPEG cleaning preserves ICC, unknown APP, and rendering/container segments by default.
14
+
8. Cleaner output is re-inspected before it is returned.
15
15
9. Metadata absence never proves an image contains no private information.
16
16
10. Steganography detection, malware scanning, visual redaction, and pixel privacy analysis are outside scope.
17
17
@@ -40,3 +40,11 @@ Every traversal or decoding loop has a validated finite count or advances a boun
40
40
## Environment and dependencies
41
41
42
42
Core code is local-only and side-effect-free. It has no network, analytics, telemetry, filesystem, DOM, or pixel-codec behavior. The package has zero runtime dependencies.
43
+
44
+
## JPEG cleaning properties
45
+
46
+
Cleaning proceeds only after bounded traversal reaches EOI. Truncated lengths, invalid marker structure, unterminated scans, and segment-limit failures produce a typed `IncompleteJpegError`; no partial output is returned. TIFF validity is not required to remove a structurally bounded EXIF APP1.
47
+
48
+
Removal uses checked, non-overlapping parser ranges. Output length is a safe integer no larger than input length, one output buffer is allocated, and retained ranges are copied in original order. Entropy-coded bytes, restart markers, retained marker fill, structural segments, and bytes after EOI are neither decoded nor regenerated. Exact `Uint8Array` views are honored and caller input is never mutated.
49
+
50
+
The default policy preserves every ICC and unknown APP segment. Verification proves only the requested observable container state supported by inspection. It does not prove provenance, byte preservation without an original, absence of unknown metadata, or absence of personal information in pixels or unsupported structures.
0 commit comments