Skip to content

Commit

Permalink
fix(base64): Reject too-short encodings (merge #1991)
Browse files Browse the repository at this point in the history
  • Loading branch information
gibson042 authored Jan 24, 2024
2 parents f17b785 + 01c06d4 commit 5b2537c
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
8 changes: 5 additions & 3 deletions packages/base64/src/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ export const jsDecodeBase64 = (string, name = '<unknown>') => {
i += 1;
}

while (i < string.length && quantum % 8 !== 0) {
if (string[i] !== padding) {
while (quantum > 0) {
if (i === string.length || string[i] !== padding) {
throw Error(`Missing padding at offset ${i} of string ${name}`);
}
// We MAY reject non-zero padding bits, but choose not to.
// https://datatracker.ietf.org/doc/html/rfc4648#section-3.5
i += 1;
quantum += 6;
quantum -= 2;
}

if (i < string.length) {
Expand Down
37 changes: 37 additions & 0 deletions packages/base64/test/test-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,40 @@ test('bytes conversions', t => {
t.is(atob(btoa(str)), str, `${str} round trips with atob(btoa)`);
}
});

test('invalid encodings', t => {
const badInputs = [
['%', /Invalid base64 character %/],
['=', undefined], // this input is bad in multiple ways

['Z%', /Invalid base64 character %/],
['Z', /Missing padding at offset 1/],
['Z=', /Missing padding at offset 2/],
['Z=%', /Missing padding at offset 2/],
['Z==%', /Missing padding at offset 3/],
['Z==m', /Missing padding at offset 3/],

['Zg%', /Invalid base64 character %/],
['Zg', /Missing padding at offset 2/],
['Zg=', /Missing padding at offset 3/],
['Zg=%', /Missing padding at offset 3/],
['Zg==%', /trailing garbage %/],
['Zg==m', /trailing garbage m/],

['Zm8%', /Invalid base64 character %/],
['Zm8', /Missing padding at offset 3/],
// not invalid: 'Zm8='
['Zm8=%', /trailing garbage %/],
['Zm8==%', /trailing garbage =%/],
['Zm8==m', /trailing garbage =m/],

// non-zero padding bits (MAY reject): ['Qf==', ...],
];
for (const [badInput, message] of badInputs) {
t.throws(
() => decodeBase64(badInput),
message && { message },
`${badInput} is rejected`,
);
}
});

0 comments on commit 5b2537c

Please sign in to comment.