mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-27 19:42:11 +10:00
113 lines
3.8 KiB
JavaScript
113 lines
3.8 KiB
JavaScript
/**
|
|
* By default, React DOM escapes any values embedded in JSX before rendering them,
|
|
* but sometimes it is necessary to sanitize the user-generated content of received entities.
|
|
* If you use this data in component props without any sanitization or encoding,
|
|
* it might create XSS vulnerabilities.
|
|
*
|
|
* You should especially consider how you are using extended data inside the app.
|
|
*/
|
|
|
|
const ESCAPE_TEXT_REGEXP = /[<>]/g;
|
|
const ESCAPE_TEXT_REPLACEMENTS = {
|
|
//fullwidth lesser-than character
|
|
'<': '\uff1c',
|
|
//fullwidth greater-than character
|
|
'>': '\uff1e',
|
|
};
|
|
|
|
// An example how you could sanitize text content.
|
|
// This swaps some coding related characters to less dangerous ones
|
|
const sanitizeText = str =>
|
|
str == null
|
|
? str
|
|
: typeof str === 'string'
|
|
? str.replace(ESCAPE_TEXT_REGEXP, ch => ESCAPE_TEXT_REPLACEMENTS[ch])
|
|
: '';
|
|
|
|
/**
|
|
* Sanitize user entity.
|
|
* If you add public data, you should probably sanitize it here.
|
|
* By default, React DOM escapes any values embedded in JSX before rendering them,
|
|
* but if you use this data on props, it might create XSS vulnerabilities
|
|
* E.g. you should sanitize and encode URI if you are creating links from public data.
|
|
*/
|
|
export const sanitizeUser = entity => {
|
|
const { attributes, ...restEntity } = entity || {};
|
|
const { profile, ...restAttributes } = attributes || {};
|
|
const { bio, displayName, abbreviatedName, publicData } = profile || {};
|
|
|
|
const sanitizePublicData = publicData => {
|
|
// TODO: If you add public data, you should probably sanitize it here.
|
|
return publicData ? { publicData } : {};
|
|
};
|
|
|
|
const profileMaybe = profile
|
|
? {
|
|
profile: {
|
|
abbreviatedName: sanitizeText(abbreviatedName),
|
|
displayName: sanitizeText(displayName),
|
|
bio: sanitizeText(bio),
|
|
...sanitizePublicData(publicData),
|
|
},
|
|
}
|
|
: {};
|
|
const attributesMaybe = attributes ? { attributes: { ...profileMaybe, ...restAttributes } } : {};
|
|
|
|
return { ...attributesMaybe, ...restEntity };
|
|
};
|
|
|
|
/**
|
|
* Sanitize listing entity.
|
|
* If you add public data, you should probably sanitize it here.
|
|
* By default, React DOM escapes any values embedded in JSX before rendering them,
|
|
* but if you use this data on props, it might create XSS vulnerabilities
|
|
* E.g. you should sanitize and encode URI if you are creating links from public data.
|
|
*/
|
|
export const sanitizeListing = entity => {
|
|
const { attributes, ...restEntity } = entity;
|
|
const { title, description, publicData, ...restAttributes } = attributes || {};
|
|
|
|
const sanitizeLocation = location => {
|
|
const { address, building } = location || {};
|
|
return { address: sanitizeText(address), building: sanitizeText(building) };
|
|
};
|
|
|
|
const sanitizePublicData = publicData => {
|
|
// Here's an example how you could sanitize location and rules from publicData:
|
|
// TODO: If you add public data, you should probably sanitize it here.
|
|
const { location, rules, ...restPublicData } = publicData || {};
|
|
const locationMaybe = location ? { location: sanitizeLocation(location) } : {};
|
|
const rulesMaybe = rules ? { rules: sanitizeText(rules) } : {};
|
|
|
|
return publicData ? { publicData: { ...locationMaybe, ...rulesMaybe, ...restPublicData } } : {};
|
|
};
|
|
|
|
const attributesMaybe = attributes
|
|
? {
|
|
attributes: {
|
|
title: sanitizeText(title),
|
|
description: sanitizeText(description),
|
|
...sanitizePublicData(publicData),
|
|
...restAttributes,
|
|
},
|
|
}
|
|
: {};
|
|
|
|
return { ...attributesMaybe, ...restEntity };
|
|
};
|
|
|
|
/**
|
|
* Sanitize entities if needed.
|
|
* Remember to add your own sanitization rules for your extended data
|
|
*/
|
|
export const sanitizeEntity = entity => {
|
|
const { type } = entity;
|
|
switch (type) {
|
|
case 'listing':
|
|
return sanitizeListing(entity);
|
|
case 'user':
|
|
return sanitizeUser(entity);
|
|
default:
|
|
return entity;
|
|
}
|
|
};
|