diff --git a/README.md b/README.md index 274acff48..28e349a85 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,15 @@ XSS sanitization was removed from the library in [2d5d6999](https://github.com/v For an alternative, have a look at Yahoo's [xss-filters library](https://github.com/yahoo/xss-filters) or at [DOMPurify](https://github.com/cure53/DOMPurify). +### Inclusive Language Aliases + +For compatability with [eslint-plugin-inclusive-language](https://github.com/muenzpraeger/eslint-plugin-inclusive-language), there are aliases for `blacklist` and `whitelist` as `denylist` and `allowlist` throughout, including these parameters: + +- `denylisted_chars` +- `host_allowlist` +- `host_denylist` +- `isAllowlisted` + ## Contributing In general, we follow the "fork-and-pull" Git workflow. diff --git a/src/index.js b/src/index.js index 42e1e8b69..593248085 100644 --- a/src/index.js +++ b/src/index.js @@ -229,6 +229,9 @@ const validator = { isLicensePlate, isVAT, ibanLocales, + allowlist: whitelist, + denylist: blacklist, + isAllowlisted: isWhitelisted, }; export default validator; diff --git a/src/lib/isEmail.js b/src/lib/isEmail.js index c7b7d6e95..5fb4af8a5 100644 --- a/src/lib/isEmail.js +++ b/src/lib/isEmail.js @@ -13,6 +13,8 @@ const default_email_options = { blacklisted_chars: '', ignore_max_length: false, host_blacklist: [], + denylisted_chars: '', + host_denylist: [], }; /* eslint-disable max-len */ @@ -99,6 +101,10 @@ export default function isEmail(str, options) { return false; } + if (options.host_denylist.includes(lower_domain)) { + return false; + } + let user = parts.join('@'); if (options.domain_specific_validation && (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com')) { @@ -172,5 +178,9 @@ export default function isEmail(str, options) { if (user.search(new RegExp(`[${options.blacklisted_chars}]+`, 'g')) !== -1) return false; } + if (options.denylisted_chars) { + if (user.search(new RegExp(`[${options.denylisted_chars}]+`, 'g')) !== -1) return false; + } + return true; } diff --git a/src/lib/isURL.js b/src/lib/isURL.js index 3d2b1df3e..0d278cf4d 100644 --- a/src/lib/isURL.js +++ b/src/lib/isURL.js @@ -153,6 +153,10 @@ export default function isURL(url, options) { return checkHost(host, options.host_whitelist); } + if (options.host_allowlist) { + return checkHost(host, options.host_allowlist); + } + if (host === '' && !options.require_host) { return true; } @@ -167,5 +171,9 @@ export default function isURL(url, options) { return false; } + if (options.host_denylist && checkHost(host, options.host_denylist)) { + return false; + } + return true; } diff --git a/test/sanitizers.js b/test/sanitizers.js index ecb0e128f..4499fe132 100644 --- a/test/sanitizers.js +++ b/test/sanitizers.js @@ -236,6 +236,19 @@ describe('Sanitizers', () => { }); }); + it('should sanitize a string based on an allowlist', () => { + test({ + sanitizer: 'allowlist', + args: ['abc'], + expect: { + abcdef: 'abc', + aaaaaaaaaabbbbbbbbbb: 'aaaaaaaaaabbbbbbbbbb', + a1b2c3: 'abc', + ' ': '', + }, + }); + }); + it('should sanitize a string based on a blacklist', () => { test({ sanitizer: 'blacklist', @@ -249,6 +262,19 @@ describe('Sanitizers', () => { }); }); + it('should sanitize a string based on a denylist', () => { + test({ + sanitizer: 'denylist', + args: ['abc'], + expect: { + abcdef: 'def', + aaaaaaaaaabbbbbbbbbb: '', + a1b2c3: '123', + ' ': ' ', + }, + }); + }); + it('should score passwords', () => { test({ sanitizer: 'isStrongPassword', diff --git a/test/validators.js b/test/validators.js index a02006be9..c1402f207 100644 --- a/test/validators.js +++ b/test/validators.js @@ -309,6 +309,19 @@ describe('Validators', () => { }); }); + it('should not validate email addresses with denylisted chars in the name', () => { + test({ + validator: 'isEmail', + args: [{ denylisted_chars: 'abc' }], + valid: [ + 'emil@gmail.com', + ], + invalid: [ + 'email@gmail.com', + ], + }); + }); + it('should validate really long emails if ignore_max_length is set', () => { test({ @@ -330,7 +343,7 @@ describe('Validators', () => { }); }); - it('should not validate email addresses with denylisted domains', () => { + it('should not validate email addresses with blacklisted domains', () => { test({ validator: 'isEmail', args: [{ host_blacklist: ['gmail.com', 'foo.bar.com'] }], @@ -344,6 +357,20 @@ describe('Validators', () => { }); }); + it('should not validate email addresses with denylisted domains', () => { + test({ + validator: 'isEmail', + args: [{ host_denylist: ['gmail.com', 'foo.bar.com'] }], + valid: [ + 'email@foo.gmail.com', + ], + invalid: [ + 'foo+bar@gmail.com', + 'email@foo.bar.com', + ], + }); + }); + it('should validate URLs', () => { test({ validator: 'isURL', @@ -689,6 +716,24 @@ describe('Validators', () => { }); }); + it('should let users specify a host allowlist', () => { + test({ + validator: 'isURL', + args: [{ + host_allowlist: ['foo.com', 'bar.com'], + }], + valid: [ + 'http://bar.com/', + 'http://foo.com/', + ], + invalid: [ + 'http://foobar.com', + 'http://foo.bar.com/', + 'http://qux.com', + ], + }); + }); + it('should allow regular expressions in the host whitelist', () => { test({ validator: 'isURL', @@ -710,6 +755,27 @@ describe('Validators', () => { }); }); + it('should allow regular expressions in the host allowlist', () => { + test({ + validator: 'isURL', + args: [{ + host_allowlist: ['bar.com', 'foo.com', /\.foo\.com$/], + }], + valid: [ + 'http://bar.com/', + 'http://foo.com/', + 'http://images.foo.com/', + 'http://cdn.foo.com/', + 'http://a.b.c.foo.com/', + ], + invalid: [ + 'http://foobar.com', + 'http://foo.bar.com/', + 'http://qux.com', + ], + }); + }); + it('should let users specify a host blacklist', () => { test({ validator: 'isURL', @@ -728,6 +794,24 @@ describe('Validators', () => { }); }); + it('should let users specify a host denylist', () => { + test({ + validator: 'isURL', + args: [{ + host_denylist: ['foo.com', 'bar.com'], + }], + valid: [ + 'http://foobar.com', + 'http://foo.bar.com/', + 'http://qux.com', + ], + invalid: [ + 'http://bar.com/', + 'http://foo.com/', + ], + }); + }); + it('should allow regular expressions in the host blacklist', () => { test({ validator: 'isURL', @@ -749,6 +833,27 @@ describe('Validators', () => { }); }); + it('should allow regular expressions in the host denylist', () => { + test({ + validator: 'isURL', + args: [{ + host_denylist: ['bar.com', 'foo.com', /\.foo\.com$/], + }], + valid: [ + 'http://foobar.com', + 'http://foo.bar.com/', + 'http://qux.com', + ], + invalid: [ + 'http://bar.com/', + 'http://foo.com/', + 'http://images.foo.com/', + 'http://cdn.foo.com/', + 'http://a.b.c.foo.com/', + ], + }); + }); + it('should allow rejecting urls containing authentication information', () => { test({ validator: 'isURL', @@ -10651,6 +10756,15 @@ describe('Validators', () => { }); }); + it('should validate allowlisted characters', () => { + test({ + validator: 'isAllowlisted', + args: ['abcdefghijklmnopqrstuvwxyz-'], + valid: ['foo', 'foobar', 'baz-foo'], + invalid: ['foo bar', 'fo.bar', 'türkçe'], + }); + }); + it('should error on non-string input', () => { test({ validator: 'isEmpty',