Commit e277daa
authored
fix(security): update dependency qs to v6.15.2 [security] (#1390)
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [qs](https://redirect.github.com/ljharb/qs) | [`6.15.1` →
`6.15.2`](https://renovatebot.com/diffs/npm/qs/6.15.1/6.15.2) |

|

|
---
### qs has a remotely triggerable DoS: qs.stringify crashes with
TypeError on null/undefined entries in comma-format arrays when
encodeValuesOnly is set
[CVE-2026-8723](https://nvd.nist.gov/vuln/detail/CVE-2026-8723) /
[GHSA-q8mj-m7cp-5q26](https://redirect.github.com/advisories/GHSA-q8mj-m7cp-5q26)
<details>
<summary>More information</summary>
#### Details
##### Summary
`qs.stringify` throws `TypeError` when called with `arrayFormat:
'comma'` and `encodeValuesOnly: true` on an array containing `null` or
`undefined`. The throw is synchronous and not handled by any of qs's
null-related options (`skipNulls`, `strictNullHandling`).
##### Details
In the comma + `encodeValuesOnly` branch, `lib/stringify.js:145` mapped
the array through the raw encoder before joining:
```js
obj = utils.maybeMap(obj, encoder);
```
`utils.encode` (`lib/utils.js:195`) reads `str.length` with no null
guard, so a `null` or `undefined` element throws `TypeError`.
`skipNulls` and `strictNullHandling` are both checked in the per-element
loop below this line and never get a chance to run.
Same class of bug as the filter-array path fixed in 0c180a4. The
vulnerable shape of the comma + `encodeValuesOnly` branch was introduced
in 4c4b23d ("encode comma values more consistently", PR #​463,
2023-01-19), first released in v6.11.1.
##### PoC
```js
const qs = require('qs');
qs.stringify({ a: [null, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true });
qs.stringify({ a: [undefined, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true });
qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true });
// TypeError: Cannot read properties of null (reading 'length')
// at encode (lib/utils.js:195:13)
// at Object.maybeMap (lib/utils.js:322:37)
// at stringify (lib/stringify.js:145:25)
```
##### Fix
`lib/stringify.js:145`, applied in 21f80b3 on `main`:
```diff
- obj = utils.maybeMap(obj, encoder);
+ obj = utils.maybeMap(obj, function (v) {
+ return v == null ? v : encoder(v);
+ });
```
`null` and `undefined` now pass through `maybeMap` unchanged and reach
the `join(',')` step as-is. For `{ a: [null, 'b'] }` this produces
`a=,b`, matching the non-`encodeValuesOnly` comma path (which already
joins before encoding and produces `a=%2Cb` for the same input).
Single-element `[null]` arrays still collapse via the existing
`obj.join(',') || null` and remain subject to `skipNulls` /
`strictNullHandling` in the main loop.
##### Affected versions
`>=6.11.1 <=6.15.1`
The vulnerable code shape was introduced in 4c4b23d and first shipped in
v6.11.1. Earlier versions — including all of 6.7.x, 6.8.x, 6.9.x,
6.10.x, and 6.11.0 — implemented the comma + `encodeValuesOnly` path
differently (joining before encoding) and are not affected. Empirically
verified across released versions.
##### Impact
Application code that calls `qs.stringify` with both `arrayFormat:
'comma'` and `encodeValuesOnly: true` (both non-default) on input that
may contain a `null` or `undefined` array element will throw
synchronously instead of producing a query string. In a typical Node.js
HTTP framework (Express, Fastify, Koa, hapi) the sync throw is caught by
the framework's error boundary and the affected request returns a 500;
the worker process does not exit and subsequent requests are unaffected.
The "kills the worker process" framing applies only to call sites
outside a request-handler error boundary (background jobs, startup
paths, stream pipelines) or to deployments with framework error handling
explicitly disabled.
The vulnerable input is a `null` or `undefined` entry inside an array;
this is reachable from JSON request bodies or from application code
constructing arrays from user input, but not from standard HTML form
submissions (which produce strings or omitted fields, not literal
`null`).
#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N`
#### References
-
[https://github.com/ljharb/qs/security/advisories/GHSA-q8mj-m7cp-5q26](https://redirect.github.com/ljharb/qs/security/advisories/GHSA-q8mj-m7cp-5q26)
-
[https://nvd.nist.gov/vuln/detail/CVE-2026-8723](https://nvd.nist.gov/vuln/detail/CVE-2026-8723)
-
[https://github.com/ljharb/qs/commit/21f80b33e5c8b3f7eba1034fff0da4a4a37a1d41](https://redirect.github.com/ljharb/qs/commit/21f80b33e5c8b3f7eba1034fff0da4a4a37a1d41)
-
[https://github.com/advisories/GHSA-q8mj-m7cp-5q26](https://redirect.github.com/advisories/GHSA-q8mj-m7cp-5q26)
This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-q8mj-m7cp-5q26)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>
---
### Release Notes
<details>
<summary>ljharb/qs (qs)</summary>
###
[`v6.15.2`](https://redirect.github.com/ljharb/qs/blob/HEAD/CHANGELOG.md#6152)
[Compare
Source](https://redirect.github.com/ljharb/qs/compare/v6.15.1...v6.15.2)
- \[Fix] `stringify`: skip null/undefined entries in `arrayFormat:
'comma'` + `encodeValuesOnly` instead of crashing in `encoder`
- \[Fix] `stringify`: use configured `delimiter` after `charsetSentinel`
([#​555](https://redirect.github.com/ljharb/qs/issues/555))
- \[Fix] `stringify`: apply `formatter` to encoded key under
`strictNullHandling`
([#​554](https://redirect.github.com/ljharb/qs/issues/554))
- \[Fix] `stringify`: skip null/undefined filter-array entries instead
of crashing in `encoder`
([#​551](https://redirect.github.com/ljharb/qs/issues/551))
- \[Fix] `parse`: handle nested bracket groups and add regression tests
([#​530](https://redirect.github.com/ljharb/qs/issues/530))
- \[readme] fix grammar
([#​550](https://redirect.github.com/ljharb/qs/issues/550))
- \[Dev Deps] update `@ljharb/eslint-config`
- \[Tests] add regression tests for keys containing percent-encoded
bracket text
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- ""
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/openfeature.dev).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTQuMCIsInVwZGF0ZWRJblZlciI6IjQzLjE5NC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZSJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>1 parent 0c1756d commit e277daa
1 file changed
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15537 | 15537 | | |
15538 | 15538 | | |
15539 | 15539 | | |
15540 | | - | |
15541 | | - | |
| 15540 | + | |
| 15541 | + | |
15542 | 15542 | | |
15543 | 15543 | | |
15544 | | - | |
| 15544 | + | |
15545 | 15545 | | |
15546 | 15546 | | |
15547 | 15547 | | |
| |||
0 commit comments