mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-19 01:17:18 +02:00
feat: replace gravatar-url with inline function (#5128)
As #4475 says, MD5 is not available in secure places anymore. This PR swaps out gravatar-url with an inline function using crypto:sha256 which is FIPS-140-2 compliant. Since we only used this method for generating avatar URLs the extra customization wasn't needed and we could hard code the URL parameters. fixes: Linear https://linear.app/unleash/issue/SR-112/gh-support-swap-out-gravatar-url-lib closes: #4475
This commit is contained in:
parent
ab390dbaab
commit
c60bca777f
@ -25,7 +25,8 @@
|
|||||||
"suspicious": {
|
"suspicious": {
|
||||||
"noExplicitAny": "off",
|
"noExplicitAny": "off",
|
||||||
"noExtraNonNullAssertion": "off",
|
"noExtraNonNullAssertion": "off",
|
||||||
"noRedeclare": "off"
|
"noRedeclare": "off",
|
||||||
|
"noPrototypeBuiltins": "off"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ignore": [
|
"ignore": [
|
||||||
|
@ -110,7 +110,6 @@
|
|||||||
"express-rate-limit": "^6.6.0",
|
"express-rate-limit": "^6.6.0",
|
||||||
"express-session": "^1.17.1",
|
"express-session": "^1.17.1",
|
||||||
"fast-json-patch": "^3.1.0",
|
"fast-json-patch": "^3.1.0",
|
||||||
"gravatar-url": "^3.1.0",
|
|
||||||
"hash-sum": "^2.0.0",
|
"hash-sum": "^2.0.0",
|
||||||
"helmet": "^6.0.0",
|
"helmet": "^6.0.0",
|
||||||
"http-errors": "^2.0.0",
|
"http-errors": "^2.0.0",
|
||||||
|
@ -531,11 +531,10 @@ export class FeatureEventFormatterMd implements FeatureEventFormatter {
|
|||||||
SEMVER_LT: 'is a SemVer less than',
|
SEMVER_LT: 'is a SemVer less than',
|
||||||
};
|
};
|
||||||
const formatConstraint = (constraint: IConstraint) => {
|
const formatConstraint = (constraint: IConstraint) => {
|
||||||
const val = Object.hasOwn(constraint, 'value')
|
const val = constraint.hasOwnProperty('value')
|
||||||
? constraint.value
|
? constraint.value
|
||||||
: `(${constraint.values?.join(',')})`;
|
: `(${constraint.values?.join(',')})`;
|
||||||
const operator = Object.hasOwn(
|
const operator = constraintOperatorDescriptions.hasOwnProperty(
|
||||||
constraintOperatorDescriptions,
|
|
||||||
constraint.operator,
|
constraint.operator,
|
||||||
)
|
)
|
||||||
? constraintOperatorDescriptions[constraint.operator]
|
? constraintOperatorDescriptions[constraint.operator]
|
||||||
|
@ -1321,7 +1321,7 @@ class FeatureToggleService {
|
|||||||
if (
|
if (
|
||||||
replaceGroupId &&
|
replaceGroupId &&
|
||||||
s.parameters &&
|
s.parameters &&
|
||||||
Object.hasOwn(s.parameters, 'groupId')
|
s.parameters.hasOwnProperty('groupId')
|
||||||
) {
|
) {
|
||||||
s.parameters.groupId = newFeatureName;
|
s.parameters.groupId = newFeatureName;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ test('should create user', () => {
|
|||||||
expect(user.name).toBe('ole');
|
expect(user.name).toBe('ole');
|
||||||
expect(user.email).toBe('some@email.com');
|
expect(user.email).toBe('some@email.com');
|
||||||
expect(user.imageUrl).toBe(
|
expect(user.imageUrl).toBe(
|
||||||
'https://gravatar.com/avatar/d8ffeba65ee5baf57e4901690edc8e1b?size=42&default=retro',
|
'https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674?s=42&d=retro&r=g',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ test('should create user, all fields', () => {
|
|||||||
expect(user.username).toBe('admin');
|
expect(user.username).toBe('admin');
|
||||||
expect(user.email).toBe('some@email.com');
|
expect(user.email).toBe('some@email.com');
|
||||||
expect(user.imageUrl).toBe(
|
expect(user.imageUrl).toBe(
|
||||||
'https://gravatar.com/avatar/d8ffeba65ee5baf57e4901690edc8e1b?size=42&default=retro',
|
'https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674?s=42&d=retro&r=g',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ test('Should create user with only username defined', () => {
|
|||||||
const user = new User({ id: 133, username: 'some-user' });
|
const user = new User({ id: 133, username: 'some-user' });
|
||||||
expect(user.username).toBe('some-user');
|
expect(user.username).toBe('some-user');
|
||||||
expect(user.imageUrl).toBe(
|
expect(user.imageUrl).toBe(
|
||||||
'https://gravatar.com/avatar/140fd5a002fb8d728a9848f8c9fcea2a?size=42&default=retro',
|
'https://gravatar.com/avatar/7e90ac329986624ba9929659913354473c6f965d5b559704409e3f933c0643b7?s=42&d=retro&r=g',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
21
src/lib/util/generateImageUrl.test.ts
Normal file
21
src/lib/util/generateImageUrl.test.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { generateImageUrl } from './generateImageUrl';
|
||||||
|
|
||||||
|
describe('Gravatar image url', () => {
|
||||||
|
it('generates the correct sha-256 hash for gravatars test idents', () => {
|
||||||
|
expect(generateImageUrl({ email: 'MyEmailAddress@example.com' })).toBe(
|
||||||
|
'https://gravatar.com/avatar/84059b07d4be67b806386c0aad8070a23f18836bbaae342275dc0a83414c32ee?s=42&d=retro&r=g',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('lowercases and trims all emails', () => {
|
||||||
|
const upperCaseAndLeadingSpace = ' helloWorld@example.com';
|
||||||
|
const upperCaseAndTrailingSpace = 'helloWorld@exAMPLE.com ';
|
||||||
|
const lowerCaseAndNoSpaces = 'helloworld@example.com';
|
||||||
|
const uCALSHash = generateImageUrl({ email: upperCaseAndLeadingSpace });
|
||||||
|
const uCATSHash = generateImageUrl({
|
||||||
|
email: upperCaseAndTrailingSpace,
|
||||||
|
});
|
||||||
|
const lCANSHash = generateImageUrl({ email: lowerCaseAndNoSpaces });
|
||||||
|
expect(uCALSHash).toBe(uCATSHash);
|
||||||
|
expect(uCATSHash).toBe(lCANSHash);
|
||||||
|
});
|
||||||
|
});
|
@ -1,11 +1,17 @@
|
|||||||
import gravatarUrl from 'gravatar-url';
|
import { createHash } from 'crypto';
|
||||||
|
|
||||||
|
const base: string = 'https://gravatar.com/avatar';
|
||||||
export const generateImageUrl = (user: {
|
export const generateImageUrl = (user: {
|
||||||
email: string;
|
email?: string;
|
||||||
username: string;
|
username?: string;
|
||||||
id: number;
|
id?: number;
|
||||||
}): string =>
|
}): string => {
|
||||||
gravatarUrl(user.email || user.username || String(user.id), {
|
let ident = user.email || user.username || String(user.id);
|
||||||
size: 42,
|
if (ident.indexOf('@')) {
|
||||||
default: 'retro',
|
ident = ident.toLowerCase().trim();
|
||||||
});
|
} else {
|
||||||
|
ident = ident.trim();
|
||||||
|
}
|
||||||
|
const identHash = createHash('sha256').update(ident).digest('hex');
|
||||||
|
return `${base}/${identHash}?s=42&d=retro&r=g`;
|
||||||
|
};
|
||||||
|
25
yarn.lock
25
yarn.lock
@ -1859,11 +1859,6 @@ bluebird@^3.1.1, bluebird@^3.7.2:
|
|||||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||||
|
|
||||||
blueimp-md5@^2.10.0:
|
|
||||||
version "2.19.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.19.0.tgz#b53feea5498dcb53dc6ec4b823adb84b729c4af0"
|
|
||||||
integrity sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==
|
|
||||||
|
|
||||||
body-parser@1.20.1:
|
body-parser@1.20.1:
|
||||||
version "1.20.1"
|
version "1.20.1"
|
||||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
|
||||||
@ -3384,14 +3379,6 @@ graceful-fs@^4.2.10, graceful-fs@^4.2.9:
|
|||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||||
|
|
||||||
gravatar-url@^3.1.0:
|
|
||||||
version "3.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/gravatar-url/-/gravatar-url-3.1.0.tgz#0cbeedab7c00a7bc9b627b3716e331359efcc999"
|
|
||||||
integrity sha512-+lOs7Rz1A051OqdqE8Tm4lmeyVgkqH8c6ll5fv///ncdIaL+XnOFmKAB70ix1du/yj8c3EWKbP6OhKjihsBSfA==
|
|
||||||
dependencies:
|
|
||||||
md5-hex "^3.0.1"
|
|
||||||
type-fest "^0.8.1"
|
|
||||||
|
|
||||||
har-schema@^2.0.0:
|
har-schema@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||||
@ -4684,13 +4671,6 @@ map-stream@~0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
|
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
|
||||||
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
|
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
|
||||||
|
|
||||||
md5-hex@^3.0.1:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c"
|
|
||||||
integrity sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==
|
|
||||||
dependencies:
|
|
||||||
blueimp-md5 "^2.10.0"
|
|
||||||
|
|
||||||
media-typer@0.3.0:
|
media-typer@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||||
@ -6631,11 +6611,6 @@ type-fest@^0.21.3:
|
|||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
|
||||||
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||||
|
|
||||||
type-fest@^0.8.1:
|
|
||||||
version "0.8.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
|
||||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
|
||||||
|
|
||||||
type-fest@^1.0.1, type-fest@^1.2.1, type-fest@^1.2.2:
|
type-fest@^1.0.1, type-fest@^1.2.1, type-fest@^1.2.2:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1"
|
||||||
|
Loading…
Reference in New Issue
Block a user