Skip to content

Commit 4300501

Browse files
committed
fix(shared): also encode file names that already look like an encoded-word
A literal ASCII file name such as "=?UTF-8?B?SGVsbG8=?=" was stored verbatim but unwrapped to "Hello" when read back from S3 metadata. Encode such values too so decodeS3MetadataValue can never misinterpret a literal name.
1 parent d29822d commit 4300501

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

packages/shared/s3MetadataEncoding.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ describe("S3 metadata value encoding", () => {
3333
}
3434
});
3535

36+
it("round-trips a literal value that looks like an encoded word", () => {
37+
const literal = "=?UTF-8?B?SGVsbG8=?=";
38+
const encoded = encodeS3MetadataValue(literal);
39+
expect(encoded).not.toBe(literal);
40+
expect(encoded).toMatch(/^[\x20-\x7e]*$/);
41+
expect(decodeS3MetadataValue(encoded)).toBe(literal);
42+
});
43+
3644
it("passes through values that are not encoded words", () => {
3745
expect(decodeS3MetadataValue("photo.jpg")).toBe("photo.jpg");
3846
expect(decodeS3MetadataValue("=?not-an-encoded-word")).toBe(

packages/shared/s3MetadataEncoding.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ const ASCII_ONLY = /^[\x20-\x7e]*$/;
99
const ENCODED_WORD = /^=\?UTF-8\?B\?([A-Za-z0-9+/=]*)\?=$/;
1010

1111
export function encodeS3MetadataValue(value: string): string {
12-
if (ASCII_ONLY.test(value)) {
12+
// A literal value that already looks like an encoded-word must be encoded
13+
// too, otherwise decodeS3MetadataValue would unwrap it on the way back.
14+
if (ASCII_ONLY.test(value) && !ENCODED_WORD.test(value)) {
1315
return value;
1416
}
1517
return `=?UTF-8?B?${Buffer.from(value, "utf8").toString("base64")}?=`;

0 commit comments

Comments
 (0)