Skip to content

feat(validator): add inclusive language aliases #2006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ const validator = {
isLicensePlate,
isVAT,
ibanLocales,
allowlist: whitelist,
denylist: blacklist,
isAllowlisted: isWhitelisted,
};

export default validator;
10 changes: 10 additions & 0 deletions src/lib/isEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const default_email_options = {
blacklisted_chars: '',
ignore_max_length: false,
host_blacklist: [],
denylisted_chars: '',
host_denylist: [],
};

/* eslint-disable max-len */
Expand Down Expand Up @@ -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')) {
Expand Down Expand Up @@ -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;
}
8 changes: 8 additions & 0 deletions src/lib/isURL.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
26 changes: 26 additions & 0 deletions test/sanitizers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
Expand Down
116 changes: 115 additions & 1 deletion test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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'] }],
Expand All @@ -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',
Expand Down Expand Up @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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',
Expand Down