Files
editor/package.json
T
dependabot[bot] 97f426c0d4 chore(deps): Bump i18next from 26.4.3 to 26.4.4 (#2239)
Bumps [i18next](https://github.com/i18next/i18next) from 26.4.3 to
26.4.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/i18next/i18next/releases">i18next's
releases</a>.</em></p>
<blockquote>
<h2>v26.4.4</h2>
<ul>
<li>fix(security): the nesting regexp no longer backtracks exponentially
(ReDoS) on an unclosed <code>$t(</code>. Its repeated group had
overlapping alternatives (<code>[^()&quot;']+</code> inside
<code>(?:...)*?</code>, and inside parentheses <code>[^()]</code> also
matched quotes), so a string containing <code>$t(</code> without a
closing <code>)</code> made the engine try every way to split the text:
about 2x the runtime per extra character, and a ~25 character value hung
<code>t()</code> for minutes. With the default config this was reachable
through any interpolated value (<code>t('greet', { name:
'$t(aaaaaaaaaaaaaaaaaaaaaaaa' })</code>): escaping does not touch
<code>$</code>, <code>t</code> or <code>(</code>, and the
<code>skipOnVariables</code> check runs the regexp on the interpolated
result, so <code>nest: false</code> did not help either. Every
alternative now starts with a different character (plain char,
<code>&quot;</code>, <code>'</code> or <code>(</code>), so there is only
one way to match and the cost is linear. Quoted strings and one level of
parentheses in nesting options keep working (<a
href="https://redirect.github.com/i18next/i18next/issues/2336">#2336</a>).
The only difference: a lone <code>&quot;</code> or <code>'</code> inside
unquoted parentheses within <code>$t(...)</code> is no longer matched.
Affects 25.3.3 to 26.4.3. Thanks to Anisetti Chaitanya Eshwar Prasad for
the responsible disclosure.</li>
<li>fix(security): <code>nest()</code> now resolves <code>$t(...)</code>
in a single pass and no longer nests text that came out of a resolved
value. Every nested lookup reset the shared nesting regexp, so the loop
started over from the beginning of the string after each match. That had
two effects. First, a <code>$t(...)</code> inside a variable that the
nested lookup deliberately kept literal (default <code>skipOnVariables:
true</code>) was resolved anyway by the outer loop: with <code>outer: 'A
$t(inner) B'</code> and <code>inner: 'Hi {{name}}'</code>,
<code>t('outer', { name: '$t(secret)' })</code> rendered the
<code>secret</code> translation. It now stays <code>A Hi $t(secret)
B</code>, the same as without the outer nesting; with
<code>skipOnVariables: false</code> it is still resolved. Second, the
cost was quadratic when an unclosed <code>$t(</code> preceded many
nestings, which matters when an app passes untrusted input as the key
itself (<code>t(userInput)</code>): 20,000 nestings took ~1.4 s, now ~25
ms. The resolved value is now sliced into the result instead of going
through <code>String.replace</code>, so <code>$&amp;</code>,
<code>$`</code>, <code>$'</code> and <code>$$</code> stay literal as
before (26.4.2).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/i18next/i18next/blob/master/CHANGELOG.md">i18next's
changelog</a>.</em></p>
<blockquote>
<h2>26.4.4</h2>
<ul>
<li>fix(security): the nesting regexp no longer backtracks exponentially
(ReDoS) on an unclosed <code>$t(</code>. Its repeated group had
overlapping alternatives (<code>[^()&quot;']+</code> inside
<code>(?:...)*?</code>, and inside parentheses <code>[^()]</code> also
matched quotes), so a string containing <code>$t(</code> without a
closing <code>)</code> made the engine try every way to split the text:
about 2x the runtime per extra character, and a ~25 character value hung
<code>t()</code> for minutes. With the default config this was reachable
through any interpolated value (<code>t('greet', { name:
'$t(aaaaaaaaaaaaaaaaaaaaaaaa' })</code>): escaping does not touch
<code>$</code>, <code>t</code> or <code>(</code>, and the
<code>skipOnVariables</code> check runs the regexp on the interpolated
result, so <code>nest: false</code> did not help either. Every
alternative now starts with a different character (plain char,
<code>&quot;</code>, <code>'</code> or <code>(</code>), so there is only
one way to match and the cost is linear. Quoted strings and one level of
parentheses in nesting options keep working (<a
href="https://redirect.github.com/i18next/i18next/issues/2336">#2336</a>).
The only difference: a lone <code>&quot;</code> or <code>'</code> inside
unquoted parentheses within <code>$t(...)</code> is no longer matched.
Affects 25.3.3 to 26.4.3. See advisory <a
href="https://github.com/i18next/i18next/security/advisories/GHSA-5jr9-983r-c8x4">GHSA-5jr9-983r-c8x4</a>,
CVSS 7.5 (<code>CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H</code>).
Thanks to Anisetti Chaitanya Eshwar Prasad for the responsible
disclosure.</li>
<li>fix(security): <code>nest()</code> now resolves <code>$t(...)</code>
in a single pass and no longer nests text that came out of a resolved
value. Every nested lookup reset the shared nesting regexp, so the loop
started over from the beginning of the string after each match. That had
two effects. First, a <code>$t(...)</code> inside a variable that the
nested lookup deliberately kept literal (default <code>skipOnVariables:
true</code>) was resolved anyway by the outer loop: with <code>outer: 'A
$t(inner) B'</code> and <code>inner: 'Hi {{name}}'</code>,
<code>t('outer', { name: '$t(secret)' })</code> rendered the
<code>secret</code> translation. It now stays <code>A Hi $t(secret)
B</code>, the same as without the outer nesting; with
<code>skipOnVariables: false</code> it is still resolved. Second, the
cost was quadratic when an unclosed <code>$t(</code> preceded many
nestings, which matters when an app passes untrusted input as the key
itself (<code>t(userInput)</code>): 20,000 nestings took ~1.4 s, now ~25
ms. The resolved value is now sliced into the result instead of going
through <code>String.replace</code>, so <code>$&amp;</code>,
<code>$`</code>, <code>$'</code> and <code>$$</code> stay literal as
before (26.4.2).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/i18next/i18next/commit/f6a7746d119790f07bc03ba86b130b090af8e443"><code>f6a7746</code></a>
26.4.4</li>
<li><a
href="https://github.com/i18next/i18next/commit/25988d5405e8e57415b2550af179f512c33ca2be"><code>25988d5</code></a>
build</li>
<li><a
href="https://github.com/i18next/i18next/commit/c9f8ebab17b456b5837e61a2e542ee27d190e151"><code>c9f8eba</code></a>
fix(security): nesting regexp ReDoS on unclosed $t( and single-pass
nest(), c...</li>
<li>See full diff in <a
href="https://github.com/i18next/i18next/compare/v26.4.3...v26.4.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=i18next&package-manager=npm_and_yarn&previous-version=26.4.3&new-version=26.4.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-15 13:58:11 +00:00

153 lines
5.0 KiB
JSON

{
"name": "maputnik",
"version": "3.1.0",
"description": "A MapLibre GL visual style editor",
"type": "module",
"main": "''",
"scripts": {
"copy-rtl-text-plugin": "mkdir -p public && cp -p node_modules/@mapbox/mapbox-gl-rtl-text/dist/mapbox-gl-rtl-text.js public/",
"start": "npm run copy-rtl-text-plugin && vite",
"build": "npm run copy-rtl-text-plugin && tsc && vite build --mode=production",
"build-desktop": "npm run copy-rtl-text-plugin && tsc && vite build --mode=desktop && cd desktop && make",
"build-linux": "npm run copy-rtl-text-plugin && tsc && vite build --mode=desktop && cd desktop && make bin/linux/maputnik",
"i18n:extract": "npx i18next-cli extract",
"lint": "eslint",
"test": "playwright test",
"test-e2e": "playwright test",
"test-unit": "vitest",
"test-unit-ci": "vitest run --coverage --reporter=json",
"lint-css": "stylelint \"src/styles/*.scss\"",
"sort-styles": "jq 'sort_by(.id)' src/config/styles.json > tmp.json && mv tmp.json src/config/styles.json"
},
"repository": {
"type": "git",
"url": "https://github.com/maplibre/maputnik"
},
"author": "Lukas Martinelli",
"license": "MIT",
"homepage": "https://github.com/maplibre/maputnik#readme",
"dependencies": {
"@codemirror/lang-json": "^6.0.2",
"@codemirror/lint": "^6.9.7",
"@codemirror/state": "^6.7.6",
"@codemirror/theme-one-dark": "^6.1.3",
"@codemirror/view": "^6.43.14",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@mapbox/mapbox-gl-rtl-text": "^0.4.0",
"@maplibre/maplibre-gl-geocoder": "^1.9.4",
"@maplibre/maplibre-gl-inspect": "^1.9.0",
"@maplibre/maplibre-gl-style-spec": "^26.4.4",
"array-move": "^4.0.0",
"buffer": "^6.0.3",
"classnames": "^2.5.1",
"codemirror": "^6.0.2",
"color": "^5.0.3",
"detect-browser": "^5.3.0",
"downshift": "^9.4.0",
"events": "^3.3.0",
"file-saver": "^2.0.5",
"i18next": "^26.4.4",
"i18next-browser-languagedetector": "^8.2.1",
"i18next-resources-to-backend": "^1.2.3",
"json-stringify-pretty-compact": "^4.0.0",
"json-to-ast": "^2.1.0",
"lodash": "^4.18.1",
"lodash.capitalize": "^4.2.1",
"lodash.clamp": "^4.0.3",
"lodash.clonedeep": "^4.5.0",
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
"lodash.throttle": "^4.1.1",
"maplibre-gl": "^6.14.0",
"maputnik-design": "github:maputnik/design#172b06c",
"ol": "^10.11.0",
"ol-mapbox-style": "^13.5.1",
"pmtiles": "^4.5.0",
"prop-types": "^15.8.1",
"react": "^19.3.0",
"react-accessible-accordion": "^5.0.1",
"react-aria-menubutton": "^8.0.0",
"react-aria-modal": "^5.0.2",
"react-collapse": "^5.1.1",
"react-color": "^2.19.3",
"react-dom": "^19.3.0",
"react-i18next": "^17.0.16",
"react-icons": "^5.7.0",
"react-markdown": "^10.1.0",
"react-resizable-panels": "^4.14.4",
"reconnecting-websocket": "^4.4.0",
"slugify": "^1.6.9",
"string-hash": "^1.1.3",
"url": "^0.11.4"
},
"jshintConfig": {
"esversion": 6
},
"stylelint": {
"extends": "stylelint-config-recommended-scss",
"rules": {
"no-descending-specificity": null,
"media-feature-name-no-unknown": [
true,
{
"ignoreMediaFeatureNames": [
"prefers-reduced-motion"
]
}
]
}
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@playwright/test": "^1.64.0",
"@stylistic/eslint-plugin": "^5.10.0",
"@types/codemirror": "^5.60.18",
"@types/color": "^4.2.1",
"@types/cors": "^2.8.19",
"@types/file-saver": "^2.0.7",
"@types/geojson": "^7946.0.16",
"@types/json-to-ast": "^2.1.4",
"@types/lodash.capitalize": "^4.2.9",
"@types/lodash.clamp": "^4.0.9",
"@types/lodash.clonedeep": "^4.5.9",
"@types/lodash.get": "^4.4.9",
"@types/lodash.isequal": "^4.5.8",
"@types/lodash.throttle": "^4.1.9",
"@types/randomcolor": "^0.5.9",
"@types/react": "^19.3.0",
"@types/react-aria-menubutton": "^6.2.14",
"@types/react-aria-modal": "^5.0.0",
"@types/react-collapse": "^5.0.4",
"@types/react-color": "^3.0.13",
"@types/react-dom": "^19.3.0",
"@types/string-hash": "^1.1.3",
"@types/wicg-file-system-access": "^2023.10.7",
"@vitejs/plugin-react": "^6.1.2",
"@vitest/coverage-v8": "^5.0.4",
"cors": "^2.8.6",
"eslint": "^10.12.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.7",
"i18next-cli": "^1.75.2",
"istanbul": "^0.4.5",
"istanbul-lib-coverage": "^3.2.2",
"nyc": "^18.0.0",
"postcss": "^8.5.29",
"react-hot-loader": "^4.13.1",
"sass": "^1.105.1",
"stylelint": "^17.16.0",
"stylelint-config-recommended-scss": "^17.0.1",
"stylelint-scss": "^7.3.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.71.1",
"uuid": "^14.0.3",
"vite": "^8.3.4",
"vite-plugin-istanbul": "^9.0.1",
"vitest": "^5.0.4"
}
}