Skip to content

Commit

Permalink
base64ToUtf8(): reject invalid characters (#1277)
Browse files Browse the repository at this point in the history
#1214 changed the implemention of `base64ToUtf8()` from `atob(...)` to `Buffer.from(...)`.  This also introduced a change in behaviour, which did not trigger any test failures.

This commit reverts to behaviour similar to the previous version while continuing to avoid the deprecated `atob()` function.

RFC4648 states:

> Implementations MUST reject the encoded data if it contains characters outside the base alphabet when interpreting base-encoded data, unless the specification referring to this document explicitly states otherwise.

See: https://datatracker.ietf.org/doc/html/rfc4648#section-3.2

`base64ToUtf8()` diverges from `atob()` by rejecting `null` instead of treating it as the string `"null"`
  • Loading branch information
alxndrsn authored Nov 9, 2024
1 parent dfa466e commit db0af6a
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ const pickAll = (keys, obj) => {
return result;
};

const validBase64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/][AQgw]={0,2}|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=?)?$/;
function base64ToUtf8(base64) {
if (!validBase64.test(base64?.trim())) throw new Error('Invalid base64 string.');
return Buffer.from(base64, 'base64').toString('utf8');
}

Expand Down
33 changes: 33 additions & 0 deletions test/unit/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,39 @@ describe('util/util', () => {
const base64 = utf8ToBase64(input);
base64ToUtf8(base64).should.be.eql(input);
});

describe('base64ToUtf8()', () => {
it(`should throw if no arg supplied`, () => {
(() => base64ToUtf8()).should.throw('Invalid base64 string.');
});

[
undefined,
null,
'!',
].forEach(malformed64 => {
it(`should reject malformed input '${malformed64}'`, () => {
(() => base64ToUtf8(malformed64)).should.throw('Invalid base64 string.');
});
});

[
[ '', '' ],
[ ' ', '' ],
[ 'c29tZSB0ZXh0', 'some text' ], // eslint-disable-line no-multi-spaces
[ 'c29tZSB0ZXh0 ', 'some text' ], // eslint-disable-line no-multi-spaces
[ ' c29tZSB0ZXh0 ', 'some text' ],
[ 'c29tZSB0ZXh0IA', 'some text ' ], // eslint-disable-line no-multi-spaces
[ 'c29tZSB0ZXh0IA=', 'some text ' ], // eslint-disable-line no-multi-spaces
[ 'c29tZSB0ZXh0IA==', 'some text ' ],
[ 'c29tZSB0ZXh0IDE=', 'some text 1' ],
[ 'c29tZSB0ZXh0IDEx', 'some text 11' ],
].forEach(([ good64, expected ]) => {
it(`should decode '${good64}' to '${expected}'`, () => {
base64ToUtf8(good64).should.equal(expected);
});
});
});
});
});

0 comments on commit db0af6a

Please sign in to comment.