diff --git a/web/html/src/.eslintrc.js b/web/html/src/.eslintrc.js index a83436f5a002..5452897c58f4 100644 --- a/web/html/src/.eslintrc.js +++ b/web/html/src/.eslintrc.js @@ -72,6 +72,13 @@ module.exports = { "sort-imports": "off", // We use a `DEPRECATED_` prefix for old components that doesn't conform with this rule "react/jsx-pascal-case": "off", + "no-restricted-imports": [ + "error", + { + name: "node-gettext", + message: "Please import from `core/intl/node-gettext` instead.", + }, + ], ...(process.env.NODE_ENV === "production" ? productionRules : {}), }, diff --git a/web/html/src/core/intl/index.tsx b/web/html/src/core/intl/index.tsx index 4b0279abb9fe..476f74d3bae4 100644 --- a/web/html/src/core/intl/index.tsx +++ b/web/html/src/core/intl/index.tsx @@ -1,6 +1,6 @@ import { createIntl, createIntlCache } from "@formatjs/intl"; -import Gettext from "node-gettext"; +import Gettext from "core/intl/node-gettext"; import { jsFormatPreferredLocale } from "core/user-preferences"; import type { Values } from "./inferValues"; @@ -30,7 +30,7 @@ const alwaysExists = { configurable: true, enumerable: true }; const messages = new Proxy( {}, { - get(_, key) { + get(_, key: string) { return gt.gettext(key); }, getOwnPropertyDescriptor() { diff --git a/web/html/src/core/intl/node-gettext.ts b/web/html/src/core/intl/node-gettext.ts new file mode 100644 index 000000000000..919246f13469 --- /dev/null +++ b/web/html/src/core/intl/node-gettext.ts @@ -0,0 +1,19 @@ +/** + * This module is a basic placeholder stopfix for CVE-2024-21528 in `node-gettext`. + * There is currently no patched version available, once a fix is published, please update `node-gettext` and remove + * this module and other changes introduced by this commit. + */ +// eslint-disable-next-line no-restricted-imports +import RawGettext from "node-gettext"; + +export default class Gettext extends RawGettext { + addTranslations(locale: string, domain: string, translations: Record) { + if (String(locale) === "__proto__") { + throw new RangeError("Invalid locale"); + } + if (String(domain) === "__proto__") { + throw new RangeError("Invalid domain"); + } + return super.addTranslations.call(this, locale, domain, translations); + } +} diff --git a/web/html/src/package.json b/web/html/src/package.json index e6ea3545c931..cd62dde38a64 100644 --- a/web/html/src/package.json +++ b/web/html/src/package.json @@ -133,6 +133,7 @@ "@types/jquery": "3.2.0", "@types/lodash": "^4.14.168", "@types/node": "14.14.10", + "@types/node-gettext": "^3.0.6", "@types/react": "^16.8.6", "@types/react-datepicker": "^4.8.0", "@types/react-dom": "^16.8.6", diff --git a/web/html/src/yarn.lock b/web/html/src/yarn.lock index 8517cd30dd08..c7abaeb88caa 100644 --- a/web/html/src/yarn.lock +++ b/web/html/src/yarn.lock @@ -2835,6 +2835,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/node-gettext@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/node-gettext/-/node-gettext-3.0.6.tgz#2a814953c8e019f7a60cff80853053a19452dbf6" + integrity sha512-A0W1IyyW3Ya+Wj6fDDWWwnXWNgrDNvKkq6xKj5Korc7YIo9023LP8qVTzgwQ5SUIANg2Pm2ggA7bfTcwoPPDUQ== + "@types/node@*": version "13.1.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.1.tgz#6d11a8c2d58405b3db9388ab740106cbfa64c3c9" diff --git a/web/spacewalk-web.changes.eth.CVE-2024-21528 b/web/spacewalk-web.changes.eth.CVE-2024-21528 new file mode 100644 index 000000000000..dc6c1ca6db5f --- /dev/null +++ b/web/spacewalk-web.changes.eth.CVE-2024-21528 @@ -0,0 +1 @@ +- Add safeguard against CVE-2024-21528