Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/lib/isBase64.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,24 @@
const base64UrlWithPadding = /^[A-Za-z0-9_-]+={0,2}$/;
const base64UrlWithoutPadding = /^[A-Za-z0-9_-]+$/;

// When padding is required, the length must be a multiple of 4.
// When padding is omitted, the length must be one of the valid
// unpadded base64 lengths: 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, ...
// i.e. (length % 4) is 0, 2, or 3 — never 1. Lengths of the form
// (4k+1) cannot be produced by any base64 encoding of any byte string.
const validUnpaddedLength = (n) => n % 4 !== 1;

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 12

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 14

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 8

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 18

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 10

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 16

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 24

Unexpected parentheses around single function argument having a body with no curly braces

Check failure on line 14 in src/lib/isBase64.js

View workflow job for this annotation

GitHub Actions / Run tests on Node.js 20

Unexpected parentheses around single function argument having a body with no curly braces

export default function isBase64(str, options) {
assertString(str);
options = merge(options, { urlSafe: false, padding: !options?.urlSafe });

if (str === '') return true;

if (options.padding && str.length % 4 !== 0) return false;
if (options.padding) {
if (str.length % 4 !== 0) return false;
} else if (!validUnpaddedLength(str.length)) {
return false;
}

let regex;
if (options.urlSafe) {
Expand All @@ -21,5 +32,5 @@
regex = options.padding ? base64WithPadding : base64WithoutPadding;
}

return (!options.padding || str.length % 4 === 0) && regex.test(str);
return regex.test(str);
}
44 changes: 44 additions & 0 deletions test/validators/isBase64.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,48 @@ describe('isBase64', () => {
],
});
});


it('should reject strings whose length is not a valid base64 length when padding is off', () => {
// Regression: with padding: false, isBase64 was returning true for
// ANY length that matched the character regex, including 1 char
// ('A'), 5 chars ('AAAAA'), 9 chars, etc. A base64 string without
// padding must have length L where L % 4 is 0, 2, or 3 — never 1.
// A string whose length leaves remainder 1 when divided by 4 has
// no valid decoding.
test({
validator: 'isBase64',
args: [{ urlSafe: false, padding: false }],
valid: [
'',
'TQ',
'TWE',
'TWFu',
'TU0',
'TU1NTQ',
'TU1NTU0',
'TU1NTU1N',
],
invalid: [
'A',
'AAAAA',
'AAAAAAAAA',
'AAAAAAAAAAAAA',
],
});

test({
validator: 'isBase64',
args: [{ urlSafe: true, padding: false }],
valid: [
'PDw_Pz8-Pg',
'bGFkaWVz',
],
invalid: [
'A',
'AAAAA',
'AAAAAAAAA',
],
});
});
});
Loading