fix(server): encode Unicode attachment filenames in response headers - #2374
fix(server): encode Unicode attachment filenames in response headers#2374roytrack wants to merge 2 commits into
Conversation
|
All contributors are covered by the First Tree CLA. |
|
I have read the CLA Document and I hereby sign the CLA |
yuezengwu
left a comment
There was a problem hiding this comment.
Approved at exact head 3fcdc3012b1a362205118d956c4628689d6e0f2a.
I reviewed the complete PR context, diff, upload/download contract, and current comments/checks. The change keeps the existing quoted filename="..." wire shape while encoding the stored semantic filename to ASCII. Unicode, spaces, literal %, quotes, backslashes, slashes, CR/LF, and control characters cannot escape the quoted header; the existing client performs one decodeURIComponent, so names round-trip without double encoding.
Exact-head verification:
attachments-route.test.ts: 25/25- client
sdk-comprehensive.test.ts: 13/13 - full Server suite: 3488/3489; the unrelated rendezvous-bound test passed 10/10 in isolation
pnpm check,pnpm typecheck,pnpm build, andgit diff --check: pass- mutation check: the new regression test fails on base with Node/Fastify
ERR_INVALID_CHARand passes on this head - CLA passed; no unresolved review threads
No blocking correctness, header-injection, compatibility, identity, CLA, copyright, or license finding.
Blocking local validation finding:
|
Dismissed after exact-head local validation found a blocking Content-Disposition header overflow regression. See issue comment #5487849382; a fresh review is required after the author pushes a fix.
|
Addressed the blocking header-overflow finding in commit Changes:
Local validation: changed-file Biome, four package typechecks, Shared 2/2, Client 14/14, Web 9/9, and Shared/Server/Client/Web builds passed. Please run a fresh exact-head validation; GitHub CI is the authoritative Server suite because the local Server global setup was blocked by the workstation pnpm dependency self-repair loop. |
PR: Encode Unicode attachment filenames in response headers
Suggested title
fix(server): encode Unicode attachment filenames in response headersSummary
Content-Dispositionresponse header.filename="..."wire shape and the currentclient-side
decodeURIComponentbehavior.Server ingress contract, keeping worst-case percent-encoded values well
below Node's default 16 KiB header limit.
response time so pre-limit rows cannot overflow clients.
literal percent sign, and full-width punctuation.
fetchboundary regressions for the maximum accepted filenameand a historical 5,500-character filename.
Root cause
The attachment download route only percent-encoded CR, LF, quotes, and
backslashes. A filename containing characters outside Latin-1 was therefore
passed directly to Node's HTTP response implementation. Node rejects that
header value with
ERR_INVALID_CHARwhile Fastify is sending the attachmentstream, which can terminate the server process.
Web uploads already transported filenames with
encodeURIComponent, whilethe Client SDK sent the raw value. Both paths now validate and percent-encode
the filename before transport; the Server decodes it and applies the same
shared validation before storage. The client already decodes percent-encoded
filename="..."values, so the download wire shape remains compatible.Complete percent-encoding can expand accepted ASCII punctuation by 3x. Without
an ingress bound, a long stored name can exceed Node's 16 KiB response-header
limit. The shared 255-byte UTF-8 limit caps the filename parameter at 765
characters in the worst case, and the response-time legacy bound covers rows
created before this validation existed.
Scope
The issue is not specific to attachment size or MIME type. It affects any
consumer of
GET /api/v1/attachments/:idwhen the stored filename containsnon-ASCII characters. That includes chat files and images as well as other
features backed by the shared attachment store, such as Team Skill bundles.
Verification
biome checkfor all ten changed files: passed.git diff --check: passed.ERR_INVALID_CHAR;patched implementation is ASCII-only and round-trips the original filename.
database clone: multiple Unicode filenames and an ASCII control file all
returned HTTP 200 with matching decoded names, byte lengths, and SHA-256
content hashes, with zero Server restarts or severe errors.
through real Node
fetch, legacy overlong-row response bounding, andingress rejection. Local execution was blocked by the workstation pnpm
dependency self-repair loop inside test global setup; GitHub CI is the
authoritative exact-head Server run.