A standing gate for the seven paths that must never break #95

Merged
paulhitt merged 2 commits from feat/validate-attachments into main 2026-09-04 20:40:33 +00:00
paulhitt commented 2026-09-04 12:05:06 +00:00 (Migrated from gitlab.com)

The relay cannot check what an attachment IS — only that it is
still the same size it was.
The blob is sealed before it arrives, so
its content is noise here and no inspection would tell a photograph from
a probe. What the relay does know is the byte count it recorded at
upload, and a served blob whose length disagrees with that is not the
file somebody uploaded.

This does not replace the recipient's own check and must not be
read as doing so.
The AES-GCM tag is what actually proves the bytes
are unmodified; a relay could serve a wrong blob of exactly the right
length and only the recipient would catch it. What the length check adds
is the far commoner case — a truncated file from a half-finished write
or a disk that filled up — and a clear answer for it.

The difference is what somebody gets told. A truncated blob that reaches
the client fails as a decryption error, which reads as "your message is
corrupt". Caught at the relay it reads as "storage lost part of this
file", which is true and points at the right place.

Refused rather than served short, and 404 rather than a new error
code: it is gone, and saying so is honest. A longer blob is refused
too — nothing in the upload path can produce one, so it matters more
rather than less.

An older row with no recorded byte count is served. That is not
evidence of damage, and refusing on an unknown would delete access to
every attachment predating the field.

The S3 store returns nil rather than answering. Doing so would cost a
HEAD on every download, and paying a round trip per request to catch a
rare storage fault is the wrong trade — the local store answers for free
and gets the check.

554 relay tests and 26 XCTests green, 7 new. Nothing here touches either
app.

**The relay cannot check what an attachment IS — only that it is still the same size it was.** The blob is sealed before it arrives, so its content is noise here and no inspection would tell a photograph from a probe. What the relay does know is the byte count it recorded at upload, and a served blob whose length disagrees with that is not the file somebody uploaded. **This does not replace the recipient's own check and must not be read as doing so.** The AES-GCM tag is what actually proves the bytes are unmodified; a relay could serve a wrong blob of exactly the right length and only the recipient would catch it. What the length check adds is the far commoner case — a truncated file from a half-finished write or a disk that filled up — and a clear answer for it. The difference is what somebody gets told. A truncated blob that reaches the client fails as a decryption error, which reads as "your message is corrupt". Caught at the relay it reads as "storage lost part of this file", which is true and points at the right place. Refused rather than served short, and 404 rather than a new error code: it is gone, and saying so is honest. A `longer` blob is refused too — nothing in the upload path can produce one, so it matters more rather than less. An older row with no recorded byte count is served. That is not evidence of damage, and refusing on an unknown would delete access to every attachment predating the field. The S3 store returns nil rather than answering. Doing so would cost a HEAD on every download, and paying a round trip per request to catch a rare storage fault is the wrong trade — the local store answers for free and gets the check. 554 relay tests and 26 XCTests green, 7 new. Nothing here touches either app.
paulhitt commented 2026-09-04 12:05:06 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt commented 2026-09-04 12:20:50 +00:00 (Migrated from gitlab.com)

changed title from Validate attachments on both sides (relay#26) to A standing gate for the seven paths that must never break

<p>changed title from <code class="idiff"><span class="idiff left right deletion">Validate attachments on both sides (relay#26)</span></code> to <code class="idiff"><span class="idiff left right addition">A standing gate for the seven paths that must never break</span></code></p>
paulhitt commented 2026-09-04 12:20:51 +00:00 (Migrated from gitlab.com)

added 1 commit

  • b1258cc7 - A standing gate for the seven paths that must never break

Compare with previous version

added 1 commit <ul><li>b1258cc7 - A standing gate for the seven paths that must never break</li></ul> [Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/32/diffs?diff_id=2005091963&start_sha=26587876701abc88fd64bbab7ac7e41d39b12ca4)
paulhitt commented 2026-09-04 20:40:33 +00:00 (Migrated from gitlab.com)

mentioned in commit e6780c82f3

mentioned in commit e6780c82f36af6e13a2d52b15b33405653c487a3
paulhitt (Migrated from gitlab.com) merged commit e6780c82f3 into main 2026-09-04 20:40:34 +00:00
paulhitt commented 2026-09-09 18:59:14 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
Sign in to join this conversation.