diff --git a/.eslintrc.js b/.eslintrc.js index e898a214..18dd567c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -12,7 +12,7 @@ module.exports = { 'plugin:import/recommended', 'plugin:import/typescript', // 'plugin:promise/recommended', - // 'plugin:security/recommended-legacy', + 'plugin:security/recommended-legacy', 'plugin:react/recommended', ], parserOptions: { @@ -24,7 +24,7 @@ module.exports = { '@typescript-eslint', 'import', 'promise', - // 'security', + 'security', 'no-catch-all', 'react', 'react-hooks', diff --git a/package-lock.json b/package-lock.json index 2bcdfc11..20bb3464 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.31.8", "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-security": "^3.0.1", "eslint-plugin-yml": "^1.14.0", "postcss": "^8.4.21", "prettier": "^3.3.3", @@ -2499,6 +2500,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-plugin-security": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz", + "integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-regex": "^2.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-plugin-yml": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.14.0.tgz", @@ -6103,6 +6120,16 @@ "node": ">=8.10.0" } }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", @@ -6416,6 +6443,16 @@ "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", "dev": true }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", diff --git a/package.json b/package.json index 0584bc53..094a2e55 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.31.8", "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-security": "^3.0.1", "eslint-plugin-yml": "^1.14.0", "postcss": "^8.4.21", "prettier": "^3.3.3", diff --git a/src/Components/Input/Autocomplete.tsx b/src/Components/Input/Autocomplete.tsx index 6dc4bdde..b39bce94 100644 --- a/src/Components/Input/Autocomplete.tsx +++ b/src/Components/Input/Autocomplete.tsx @@ -70,6 +70,7 @@ export const Autocomplete = ({ break case 'Enter': if (filteredSuggestions.length > 0) { + // eslint-disable-next-line security/detect-object-injection onSelected(filteredSuggestions[heighlightedSuggestion]) setHeighlightedSuggestion(0) } diff --git a/src/Components/Map/Layer.tsx b/src/Components/Map/Layer.tsx index 4d09b729..74337fff 100644 --- a/src/Components/Map/Layer.tsx +++ b/src/Components/Map/Layer.tsx @@ -196,6 +196,7 @@ export const Layer = ({ } else { if (window.location.pathname.split('/')[1]) { const id = window.location.pathname.split('/')[1] + // eslint-disable-next-line security/detect-object-injection const ref = leafletRefs[id] if (ref?.marker && ref.item.layer?.name === name) { ref.marker && @@ -261,20 +262,27 @@ export const Layer = ({ ) .map((item: Item) => { if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) { + // eslint-disable-next-line security/detect-object-injection if (getValue(item, itemTextField)) item[itemTextField] = getValue(item, itemTextField) + // eslint-disable-next-line security/detect-object-injection else item[itemTextField] = '' if (item.tags) { + // eslint-disable-next-line security/detect-object-injection item[itemTextField] = item[itemTextField] + '\n\n' item.tags.map((tag) => { + // eslint-disable-next-line security/detect-object-injection if (!item[itemTextField].includes(`#${encodeTag(tag)}`)) { + // eslint-disable-next-line security/detect-object-injection return (item[itemTextField] = item[itemTextField] + `#${encodeTag(tag)} `) } + // eslint-disable-next-line security/detect-object-injection return item[itemTextField] }) } if (allTagsLoaded && allItemsLoaded) { + // eslint-disable-next-line security/detect-object-injection item[itemTextField].match(hashTagRegex)?.map((tag) => { if ( !tags.find( diff --git a/src/Components/Map/Subcomponents/Controls/SearchControl.tsx b/src/Components/Map/Subcomponents/Controls/SearchControl.tsx index d84fbf62..5e77d29c 100644 --- a/src/Components/Map/Subcomponents/Controls/SearchControl.tsx +++ b/src/Components/Map/Subcomponents/Controls/SearchControl.tsx @@ -332,6 +332,7 @@ export const SearchControl = () => { function isGeoCoordinate(input) { const geokoordinatenRegex = + // eslint-disable-next-line security/detect-unsafe-regex /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/ return geokoordinatenRegex.test(input) } diff --git a/src/Components/Profile/Subcomponents/SocialShareButton.tsx b/src/Components/Profile/Subcomponents/SocialShareButton.tsx index 04809fcf..64f0858a 100644 --- a/src/Components/Profile/Subcomponents/SocialShareButton.tsx +++ b/src/Components/Profile/Subcomponents/SocialShareButton.tsx @@ -84,6 +84,7 @@ const SocialShareButton = ({ url: string title: string }) => { + // eslint-disable-next-line security/detect-object-injection const config = platformConfigs[platform] if (!config) { diff --git a/src/Components/Templates/CircleLayout.tsx b/src/Components/Templates/CircleLayout.tsx index f36b8681..67e64ff1 100644 --- a/src/Components/Templates/CircleLayout.tsx +++ b/src/Components/Templates/CircleLayout.tsx @@ -25,6 +25,7 @@ export const CircleLayout = ({ const angle = startAngle + (i / itemCount) * (2 * Math.PI) const x = radius * Math.cos(angle) const y = radius * Math.sin(angle) + // eslint-disable-next-line security/detect-object-injection const child = container.children[i] as HTMLElement child.style.transform = `translate(${x}px, ${y}px)` } diff --git a/src/Utils/GetValue.ts b/src/Utils/GetValue.ts index c2d73ed3..ff159599 100644 --- a/src/Utils/GetValue.ts +++ b/src/Utils/GetValue.ts @@ -7,6 +7,7 @@ export function getValue(obj, path) { const pathArray = path.split('.') // Use a different variable for the split path for (let i = 0, len = pathArray.length; i < len; i++) { if (!obj) return undefined // Check if obj is falsy at each step + // eslint-disable-next-line security/detect-object-injection obj = obj[pathArray[i]] // Dive one level deeper } return obj // Return the final value diff --git a/src/Utils/MarkerIconFactory.ts b/src/Utils/MarkerIconFactory.ts index eb3614eb..6de46870 100644 --- a/src/Utils/MarkerIconFactory.ts +++ b/src/Utils/MarkerIconFactory.ts @@ -25,6 +25,7 @@ const createSvg = (shape: string, markerColor: string, borderColor: string) => { markerColor + '" />', } + // eslint-disable-next-line security/detect-object-injection return svgMap[shape] } diff --git a/src/Utils/ReplaceURLs.ts b/src/Utils/ReplaceURLs.ts index 8c45acd1..25981922 100644 --- a/src/Utils/ReplaceURLs.ts +++ b/src/Utils/ReplaceURLs.ts @@ -1,5 +1,5 @@ export const urlRegex = - // eslint-disable-next-line no-useless-escape + // eslint-disable-next-line no-useless-escape, security/detect-unsafe-regex /(^| )(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,10}(:[0-9]{1,10})?(\/.*)?$/gm export const mailRegex = /(?