qs 6.6.0 → 6.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/backport-record.md +79 -0
- package/.claude/ghsa-2856-comment.md +7 -0
- package/.claude/ghsa-6rw7-update.md +53 -0
- package/.claude/ghsa-w7fw-comment.md +10 -0
- package/.claude/settings.local.json +36 -0
- package/.editorconfig +14 -1
- package/.eslintrc +19 -2
- package/.github/FUNDING.yml +12 -0
- package/.nycrc +13 -0
- package/CHANGELOG.md +34 -1
- package/LICENSE.md +29 -0
- package/README.md +62 -21
- package/dist/qs.js +144 -99
- package/lib/formats.js +18 -10
- package/lib/parse.js +33 -24
- package/lib/stringify.js +74 -48
- package/lib/utils.js +17 -15
- package/package.json +19 -15
- package/test/parse.js +69 -1
- package/test/stringify.js +25 -0
- package/test/utils.js +47 -0
- package/.eslintignore +0 -1
- package/LICENSE +0 -28
- package/test/.eslintrc +0 -17
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Backport Record
|
|
2
|
+
|
|
3
|
+
Commits to backport from main (v6.14.1..v6.14.2, excluding version bump):
|
|
4
|
+
|
|
5
|
+
| # | SHA | Description |
|
|
6
|
+
|---|-----|-------------|
|
|
7
|
+
| 1 | 6744d30 | [Robustness] avoid `.push`, use `void` |
|
|
8
|
+
| 2 | 6bdfaf5 | [readme] replace runkit/travis CI badge with shields.io check-runs badge |
|
|
9
|
+
| 3 | 2a35775 | [meta] fix changelog typo |
|
|
10
|
+
| 4 | 1b9a8b4 | [actions] fix rebase workflow permissions |
|
|
11
|
+
| 5 | fbc5206 | [Fix] `parse`: fix error message |
|
|
12
|
+
| 6 | f6a7abf | [Fix] `parse`: enforce arrayLimit on comma-parsed values |
|
|
13
|
+
| 7 | febb644 | [Fix] `parse`: throw on arrayLimit exceeded with indexed notation |
|
|
14
|
+
| 8 | cfc108f | [Fix] arrayLimit means max count, not max index |
|
|
15
|
+
| 9 | 6addf8c | [Fix] `parse`: mark overflow objects for indexed notation |
|
|
16
|
+
| 10 | 5c308e5 | [readme] clarify parseArrays and arrayLimit documentation |
|
|
17
|
+
| 11 | 294db90 | [readme] document addQueryPrefix does not add ? to empty output |
|
|
18
|
+
|
|
19
|
+
## Results
|
|
20
|
+
|
|
21
|
+
| Version | Base Tag | Base SHA | Result HEAD | Applied | Skipped |
|
|
22
|
+
|---------|----------|----------|-------------|---------|---------|
|
|
23
|
+
| 6.14 | v6.14.2 | bdcf0c7 | bdcf0c7 | all | — |
|
|
24
|
+
| 6.13 | v6.13.1 | f1ee037 | 625fa19 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
25
|
+
| 6.12 | v6.12.3 | f90cc35 | 8a1b294 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
26
|
+
| 6.11 | v6.11.2 | 410bdd3 | 3a5f714 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
27
|
+
| 6.10 | v6.10.5 | 95bc018 | 8189da8 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
28
|
+
| 6.9 | v6.9.7 | 4cd0032 | 6a7a3bf | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
29
|
+
| 6.8 | v6.8.3 | 0db5538 | 76d53e9 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
30
|
+
| 6.7 | v6.7.3 | 834389a | 2991d8b | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
31
|
+
| 6.6 | v6.6.1 | 4cc653c | 7093153 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
32
|
+
| 6.5 | v6.5.3 | 298bfa5 | 40b77c3 | 1,2,4,10,11 | 3,5,6,7,8,9 |
|
|
33
|
+
| 6.4 | v6.4.1 | 486aa46 | d9ffe2b | 1,2,4,10 | 3,5,6,7,8,9,11 |
|
|
34
|
+
| 6.3 | v6.3.3 | ff235b4 | b4824cb | 1,2,4,10 | 3,5,6,7,8,9,11 |
|
|
35
|
+
| 6.2 | v6.2.4 | 90d9f2b | db7b937 | 1,2,4,10 | 3,5,6,7,8,9,11 |
|
|
36
|
+
| 6.1 | v6.1.2 | 68ca039 | 3245e1f | 1,2,10 | 3,4,5,6,7,8,9,11 |
|
|
37
|
+
| 6.0 | v6.0.4 | 10233c9 | b779be4 | 1,2,10 | 3,4,5,6,7,8,9,11 |
|
|
38
|
+
|
|
39
|
+
## Legend for Applied/Skipped columns
|
|
40
|
+
|
|
41
|
+
1=Robustness, 2=readme badge, 3=changelog typo, 4=actions permissions,
|
|
42
|
+
5=error msg fix, 6=comma arrayLimit, 7=indexed throw, 8=count semantics,
|
|
43
|
+
9=mark overflow, 10=parseArrays/arrayLimit docs, 11=addQueryPrefix docs
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
- #2 (badge): v6.4+ had runkit badge replaced; v6.0-v6.3 had Travis badge replaced
|
|
48
|
+
- #4 (actions): v6.2-v6.10 had permissions block ADDED (not modified); v6.0-v6.1 have no rebase.yml
|
|
49
|
+
|
|
50
|
+
## Skip Reasons
|
|
51
|
+
|
|
52
|
+
| Commit | Reason for skip |
|
|
53
|
+
|--------|----------------|
|
|
54
|
+
| 3 (2a35775) | v6.14.1-specific changelog — not applicable to other versions |
|
|
55
|
+
| 5 (fbc5206) | Requires `throwOnLimitExceeded` option (v6.14.0+) |
|
|
56
|
+
| 6 (f6a7abf) | Requires overflow system (`combine(a,b,arrayLimit,plainObjects)`) from v6.14.1 |
|
|
57
|
+
| 7 (febb644) | Requires `throwOnLimitExceeded` option (v6.14.0+) |
|
|
58
|
+
| 8 (cfc108f) | Requires overflow system from v6.14.1 |
|
|
59
|
+
| 9 (6addf8c) | Requires overflow system from v6.14.1 |
|
|
60
|
+
| 11 (294db90) | v6.4 and below lack `addQueryPrefix` in README |
|
|
61
|
+
|
|
62
|
+
## Release Tags
|
|
63
|
+
|
|
64
|
+
| Tag | SHA | Changelog Entries |
|
|
65
|
+
|-----|-----|-------------------|
|
|
66
|
+
| v6.13.2 | d8a8ab3 | Robustness, readme #543, readme #418, readme badge, actions |
|
|
67
|
+
| v6.12.4 | a67173e | Robustness, readme #543, readme #418, readme badge, actions |
|
|
68
|
+
| v6.11.3 | 6302f35 | Robustness, readme #543, readme #418, readme badge, actions |
|
|
69
|
+
| v6.10.6 | 1aa4bd9 | Robustness, readme #543, readme #418, readme badge, actions |
|
|
70
|
+
| v6.9.8 | 479d4b1 | Robustness, readme #543, readme #418, readme badge, actions |
|
|
71
|
+
| v6.8.4 | 0f2b1e2 | Robustness, readme #543, readme #418, readme badge, actions |
|
|
72
|
+
| v6.7.4 | d38e43a | Robustness, readme #543, readme #418, readme badge, actions |
|
|
73
|
+
| v6.6.2 | 5e1c72c | Robustness, readme #543, readme #418, readme badge, actions |
|
|
74
|
+
| v6.5.4 | c190488 | Robustness, readme #543, readme #418, readme badge, actions |
|
|
75
|
+
| v6.4.2 | 9b50144 | Robustness, readme #543, readme badge (runkit+travis), actions |
|
|
76
|
+
| v6.3.4 | aa3f9f4 | Robustness, readme #543, readme badge (travis), actions |
|
|
77
|
+
| v6.2.5 | d68f354 | Robustness, readme #543, readme badge (travis), actions |
|
|
78
|
+
| v6.1.3 | cb45ba1 | Robustness, readme #543, readme badge (travis) |
|
|
79
|
+
| v6.0.5 | a73f299 | Robustness, readme #543, readme badge (travis) |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# GHSA-2856-wc6q-8xwc — Comment to post
|
|
2
|
+
|
|
3
|
+
This is not a vulnerability. The described behavior only modifies properties on the **result object** returned by `qs.parse()` — it does not modify `Object.prototype` or any shared state. Setting `toString` or `hasOwnProperty` on a specific result object is not prototype pollution; it's the expected outcome of parsing a key with that name.
|
|
4
|
+
|
|
5
|
+
The `allowPrototypes` option exists precisely to control whether keys that shadow `Object.prototype` properties are allowed on result objects. When `depth <= 0` and brackets are present, the prototype check is applied to the bracketed form of the key rather than the stripped form — this is a minor inconsistency in the check, but the result is equivalent to what would happen with `allowPrototypes: true`, which is an explicitly supported configuration.
|
|
6
|
+
|
|
7
|
+
Closing as not applicable.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# GHSA-6rw7-vpxm-498p — Edits to make
|
|
2
|
+
|
|
3
|
+
## Severity
|
|
4
|
+
Change: High → Low
|
|
5
|
+
|
|
6
|
+
## CVSS 3.1
|
|
7
|
+
Old: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H` (7.5 High)
|
|
8
|
+
New: `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L` (3.7 Low)
|
|
9
|
+
|
|
10
|
+
Changes:
|
|
11
|
+
- AC: L → H (requires non-default parameterLimit config for real impact)
|
|
12
|
+
- A: H → L (bounded memory increase, not a crash/full DoS under defaults)
|
|
13
|
+
|
|
14
|
+
## Description — replace with:
|
|
15
|
+
|
|
16
|
+
### Summary
|
|
17
|
+
|
|
18
|
+
The `arrayLimit` option in qs did not enforce limits for bracket notation (`a[]=1&a[]=2`), only for indexed notation (`a[0]=1`). This is a consistency bug; `arrayLimit` should apply uniformly across all array notations.
|
|
19
|
+
|
|
20
|
+
**Note:** The default `parameterLimit` of 1000 effectively mitigates the DoS scenario originally described. With default options, bracket notation cannot produce arrays larger than `parameterLimit` regardless of `arrayLimit`, because each `a[]=value` consumes one parameter slot. The severity has been reduced accordingly.
|
|
21
|
+
|
|
22
|
+
### Details
|
|
23
|
+
|
|
24
|
+
The `arrayLimit` option only checked limits for indexed notation (`a[0]=1&a[1]=2`) but did not enforce it for bracket notation (`a[]=1&a[]=2`).
|
|
25
|
+
|
|
26
|
+
**Vulnerable code** (`lib/parse.js:159-162`):
|
|
27
|
+
```javascript
|
|
28
|
+
if (root === '[]' && options.parseArrays) {
|
|
29
|
+
obj = utils.combine([], leaf); // No arrayLimit check
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Working code** (`lib/parse.js:175`):
|
|
34
|
+
```javascript
|
|
35
|
+
else if (index <= options.arrayLimit) { // Limit checked here
|
|
36
|
+
obj = [];
|
|
37
|
+
obj[index] = leaf;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### PoC
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
const qs = require('qs');
|
|
45
|
+
const result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5 });
|
|
46
|
+
console.log(result.a.length); // Output: 6 (should be max 5)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Note on parameterLimit interaction:** The original advisory's "DoS demonstration" claimed a length of 10,000, but `parameterLimit` (default: 1000) caps parsing to 1,000 parameters. With default options, the actual output is 1,000, not 10,000.
|
|
50
|
+
|
|
51
|
+
### Impact
|
|
52
|
+
|
|
53
|
+
Consistency bug in `arrayLimit` enforcement. With default `parameterLimit`, the practical DoS risk is negligible since `parameterLimit` already caps the total number of parsed parameters (and thus array elements from bracket notation). The risk increases only when `parameterLimit` is explicitly set to a very high value.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# GHSA-w7fw-mjwx-w883 — Comment to post
|
|
2
|
+
|
|
3
|
+
This is a valid report — thank you. The comma-split code path in `parseArrayValue` returned the split array immediately, bypassing the `arrayLimit` check. Unlike the bracket notation case (GHSA-6rw7-vpxm-498p), this genuinely bypasses `parameterLimit` as well, since a single parameter like `a=x,x,x,...` produces an arbitrarily large array from one `&`-delimited parameter.
|
|
4
|
+
|
|
5
|
+
A fix has been implemented: after the comma split and decode step, if the resulting array exceeds `arrayLimit`, it is converted to an object (consistent with other `arrayLimit` exceedances), and `throwOnLimitExceeded` is respected.
|
|
6
|
+
|
|
7
|
+
A few corrections to the advisory:
|
|
8
|
+
- **Severity should be Medium, not High**: This requires the non-default `comma: true` option to be explicitly enabled. HTTP server request size limits also bound the practical impact.
|
|
9
|
+
- **Vulnerable version range**: Should be `<= 6.14.1` (not `< 6.14.1`), since 6.14.1 is also affected.
|
|
10
|
+
- **Patched version**: Will be set once the fix is released.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npm run lint:*)",
|
|
5
|
+
"Bash(npm test:*)",
|
|
6
|
+
"Bash(npm run tests-only:*)",
|
|
7
|
+
"Bash(npm show:*)",
|
|
8
|
+
"Bash(git log:*)",
|
|
9
|
+
"Bash(git tag:*)",
|
|
10
|
+
"Bash(npm view:*)",
|
|
11
|
+
"Bash(git fetch:*)",
|
|
12
|
+
"Bash(git cat-file:*)",
|
|
13
|
+
"Bash(git show:*)",
|
|
14
|
+
"Bash(git rev-parse:*)",
|
|
15
|
+
"Bash(git rev-list:*)",
|
|
16
|
+
"Bash(gh api:*)",
|
|
17
|
+
"Bash(node /tmp/qs-vuln-test.js:*)",
|
|
18
|
+
"Bash(git -C /Users/ljharb/git/ljharb/qs.git show 3086902 --stat)",
|
|
19
|
+
"Bash(git -C /Users/ljharb/git/ljharb/qs.git diff HEAD -- lib/parse.js lib/utils.js)",
|
|
20
|
+
"Bash(open:*)",
|
|
21
|
+
"WebSearch",
|
|
22
|
+
"WebFetch(domain:www.first.org)",
|
|
23
|
+
"WebFetch(domain:nvd.nist.gov)",
|
|
24
|
+
"WebFetch(domain:raw.githubusercontent.com)",
|
|
25
|
+
"Bash(git -C /Users/ljharb/git/ljharb/qs.git diff origin/main...HEAD)",
|
|
26
|
+
"Bash(for ver in v6.13.1 v6.12.3 v6.11.2 v6.10.5 v6.9.7 v6.8.3 v6.7.3 v6.6.1 v6.5.3 v6.4.1 v6.3.3 v6.2.4 v6.1.2 v6.0.4)",
|
|
27
|
+
"Bash(do echo '=== $ver ===')",
|
|
28
|
+
"Bash(done)",
|
|
29
|
+
"Bash(git checkout:*)",
|
|
30
|
+
"Bash(cd /Users/ljharb/git/ljharb/qs.git git add README.md git commit --no-verify --no-gpg-sign -m \"[readme] replace travis CI badge with shields.io check-runs badge\")",
|
|
31
|
+
"Bash(npm run dist:*)",
|
|
32
|
+
"Bash(for tag in v6.13.2 v6.12.4 v6.11.3 v6.10.6 v6.9.8 v6.8.4 v6.7.4 v6.6.2 v6.5.4 v6.4.2 v6.3.4 v6.2.5 v6.1.3 v6.0.5)",
|
|
33
|
+
"Bash(gh run view:*)"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|
package/.editorconfig
CHANGED
|
@@ -7,11 +7,15 @@ end_of_line = lf
|
|
|
7
7
|
charset = utf-8
|
|
8
8
|
trim_trailing_whitespace = true
|
|
9
9
|
insert_final_newline = true
|
|
10
|
-
max_line_length =
|
|
10
|
+
max_line_length = 160
|
|
11
|
+
quote_type = single
|
|
11
12
|
|
|
12
13
|
[test/*]
|
|
13
14
|
max_line_length = off
|
|
14
15
|
|
|
16
|
+
[LICENSE.md]
|
|
17
|
+
indent_size = off
|
|
18
|
+
|
|
15
19
|
[*.md]
|
|
16
20
|
max_line_length = off
|
|
17
21
|
|
|
@@ -28,3 +32,12 @@ indent_size = 2
|
|
|
28
32
|
[LICENSE]
|
|
29
33
|
indent_size = 2
|
|
30
34
|
max_line_length = off
|
|
35
|
+
|
|
36
|
+
[coverage/**/*]
|
|
37
|
+
indent_size = off
|
|
38
|
+
indent_style = off
|
|
39
|
+
indent = off
|
|
40
|
+
max_line_length = off
|
|
41
|
+
|
|
42
|
+
[.nycrc]
|
|
43
|
+
indent_style = tab
|
package/.eslintrc
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
"extends": "@ljharb",
|
|
5
5
|
|
|
6
|
+
"ignorePatterns": [
|
|
7
|
+
"dist/",
|
|
8
|
+
],
|
|
9
|
+
|
|
6
10
|
"rules": {
|
|
7
11
|
"complexity": 0,
|
|
8
12
|
"consistent-return": 1,
|
|
9
|
-
|
|
13
|
+
"func-name-matching": 0,
|
|
10
14
|
"id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
|
|
11
15
|
"indent": [2, 4],
|
|
12
16
|
"max-lines-per-function": [2, { "max": 150 }],
|
|
@@ -15,7 +19,20 @@
|
|
|
15
19
|
"multiline-comment-style": 0,
|
|
16
20
|
"no-continue": 1,
|
|
17
21
|
"no-magic-numbers": 0,
|
|
22
|
+
"no-param-reassign": 1,
|
|
18
23
|
"no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
|
|
19
24
|
"operator-linebreak": [2, "before"],
|
|
20
|
-
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
"overrides": [
|
|
28
|
+
{
|
|
29
|
+
"files": "test/**",
|
|
30
|
+
"rules": {
|
|
31
|
+
"max-lines-per-function": 0,
|
|
32
|
+
"max-statements": 0,
|
|
33
|
+
"no-extend-native": 0,
|
|
34
|
+
"function-paren-newline": 0,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
21
38
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# These are supported funding model platforms
|
|
2
|
+
|
|
3
|
+
github: [ljharb]
|
|
4
|
+
patreon: # Replace with a single Patreon username
|
|
5
|
+
open_collective: # Replace with a single Open Collective username
|
|
6
|
+
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
+
tidelift: npm/qs
|
|
8
|
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
+
liberapay: # Replace with a single Liberapay username
|
|
10
|
+
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
+
otechie: # Replace with a single Otechie username
|
|
12
|
+
custom: # Replace with a single custom sponsorship URL
|
package/.nycrc
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
## **6.6.2**
|
|
2
|
+
- [Robustness] avoid `.push`, use `void`
|
|
3
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
4
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
5
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
6
|
+
- [actions] fix rebase workflow permissions
|
|
7
|
+
|
|
8
|
+
## **6.6.1**
|
|
9
|
+
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
10
|
+
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
11
|
+
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
|
|
12
|
+
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
|
|
13
|
+
- [Fix] correctly parse nested arrays
|
|
14
|
+
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
|
|
15
|
+
- [Robustness] `stringify`: cache `Object.prototype.hasOwnProperty`
|
|
16
|
+
- [Refactor] `formats`: tiny bit of cleanup.
|
|
17
|
+
- [Refactor] `utils`: `isBuffer`: small tweak; add tests
|
|
18
|
+
- [Refactor]: `stringify`/`utils`: cache `Array.isArray`
|
|
19
|
+
- [Refactor] `utils`: reduce observable [[Get]]s
|
|
20
|
+
- [Refactor] use cached `Array.isArray`
|
|
21
|
+
- [Refactor] `parse`/`stringify`: make a function to normalize the options
|
|
22
|
+
- [readme] remove travis badge; add github actions/codecov badges; update URLs
|
|
23
|
+
- [Docs] Clarify the need for "arrayLimit" option
|
|
24
|
+
- [meta] fix README.md (#399)
|
|
25
|
+
- [meta] do not publish workflow files
|
|
26
|
+
- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
|
|
27
|
+
- [meta] add FUNDING.yml
|
|
28
|
+
- [meta] Fixes typo in CHANGELOG.md
|
|
29
|
+
- [actions] backport actions from main
|
|
30
|
+
- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10
|
|
31
|
+
- [Tests] always use `String(x)` over `x.toString()`
|
|
32
|
+
- [Dev Deps] backport from main
|
|
33
|
+
|
|
1
34
|
## **6.6.0**
|
|
2
35
|
- [New] Add support for iso-8859-1, utf8 "sentinel" and numeric entities (#268)
|
|
3
36
|
- [New] move two-value combine to a `utils` function (#189)
|
|
@@ -11,7 +44,7 @@
|
|
|
11
44
|
- [Refactor] add missing defaults
|
|
12
45
|
- [Refactor] `parse`: one less `concat` call
|
|
13
46
|
- [Refactor] `utils`: `compactQueue`: make it explicitly side-effecting
|
|
14
|
-
- [Dev Deps] update `browserify
|
|
47
|
+
- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`, `iconv-lite`, `safe-publish-latest`, `tape`
|
|
15
48
|
- [Tests] up to `node` `v10.10`, `v9.11`, `v8.12`, `v6.14`, `v4.9`; pin included builds to LTS
|
|
16
49
|
|
|
17
50
|
## **6.5.2**
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors)
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# qs <sup>[![Version Badge][2]][1]</sup>
|
|
2
2
|
|
|
3
|
-
[![
|
|
4
|
-
[![
|
|
5
|
-
[![
|
|
3
|
+
[![github actions][actions-image]][actions-url]
|
|
4
|
+
[![coverage][codecov-image]][codecov-url]
|
|
5
|
+
[![dependency status][deps-svg]][deps-url]
|
|
6
|
+
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
|
6
7
|
[![License][license-image]][license-url]
|
|
7
8
|
[![Downloads][downloads-image]][downloads-url]
|
|
8
9
|
|
|
9
|
-
[![npm badge][
|
|
10
|
+
[![npm badge][npm-badge-png]][package-url]
|
|
10
11
|
|
|
11
12
|
A querystring parsing and stringifying library with some added security.
|
|
12
13
|
|
|
@@ -237,8 +238,8 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
|
|
|
237
238
|
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
|
|
238
239
|
```
|
|
239
240
|
|
|
240
|
-
**qs** will also limit
|
|
241
|
-
instead be converted to an object with the index as the key
|
|
241
|
+
**qs** will also limit arrays to a maximum of `20` elements. Any array members with an index of `20` or greater will
|
|
242
|
+
instead be converted to an object with the index as the key. This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
|
|
242
243
|
|
|
243
244
|
```javascript
|
|
244
245
|
var withMaxIndex = qs.parse('a[100]=b');
|
|
@@ -252,7 +253,7 @@ var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
|
|
|
252
253
|
assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
|
|
253
254
|
```
|
|
254
255
|
|
|
255
|
-
To
|
|
256
|
+
To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
|
|
256
257
|
|
|
257
258
|
```javascript
|
|
258
259
|
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
|
|
@@ -323,6 +324,30 @@ var decoded = qs.parse('x=z', { decoder: function (str) {
|
|
|
323
324
|
}})
|
|
324
325
|
```
|
|
325
326
|
|
|
327
|
+
You can encode keys and values using different logic by using the type argument provided to the encoder:
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
|
|
331
|
+
if (type === 'key') {
|
|
332
|
+
return // Encoded key
|
|
333
|
+
} else if (type === 'value') {
|
|
334
|
+
return // Encoded value
|
|
335
|
+
}
|
|
336
|
+
}})
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
The type argument is also provided to the decoder:
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) {
|
|
343
|
+
if (type === 'key') {
|
|
344
|
+
return // Decoded key
|
|
345
|
+
} else if (type === 'value') {
|
|
346
|
+
return // Decoded value
|
|
347
|
+
}
|
|
348
|
+
}})
|
|
349
|
+
```
|
|
350
|
+
|
|
326
351
|
Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage.
|
|
327
352
|
|
|
328
353
|
When arrays are stringified, by default they are given explicit indices:
|
|
@@ -392,6 +417,12 @@ The query string may optionally be prepended with a question mark:
|
|
|
392
417
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
|
|
393
418
|
```
|
|
394
419
|
|
|
420
|
+
Note that when the output is an empty string, the prefix will not be added:
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
|
|
424
|
+
```
|
|
425
|
+
|
|
395
426
|
The delimiter may be overridden with stringify as well:
|
|
396
427
|
|
|
397
428
|
```javascript
|
|
@@ -544,18 +575,28 @@ assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
|
|
|
544
575
|
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
|
|
545
576
|
```
|
|
546
577
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
[
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
[
|
|
556
|
-
|
|
557
|
-
[
|
|
558
|
-
[
|
|
578
|
+
## Security
|
|
579
|
+
|
|
580
|
+
Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
|
|
581
|
+
|
|
582
|
+
## qs for enterprise
|
|
583
|
+
|
|
584
|
+
Available as part of the Tidelift Subscription
|
|
585
|
+
|
|
586
|
+
The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
|
587
|
+
|
|
588
|
+
[package-url]: https://npmjs.org/package/qs
|
|
589
|
+
[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
|
|
590
|
+
[deps-svg]: https://david-dm.org/ljharb/qs.svg
|
|
591
|
+
[deps-url]: https://david-dm.org/ljharb/qs
|
|
592
|
+
[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg
|
|
593
|
+
[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies
|
|
594
|
+
[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
|
|
595
|
+
[license-image]: https://img.shields.io/npm/l/qs.svg
|
|
559
596
|
[license-url]: LICENSE
|
|
560
|
-
[downloads-image]:
|
|
561
|
-
[downloads-url]:
|
|
597
|
+
[downloads-image]: https://img.shields.io/npm/dm/qs.svg
|
|
598
|
+
[downloads-url]: https://npm-stat.com/charts.html?package=qs
|
|
599
|
+
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
600
|
+
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
601
|
+
[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
|
|
602
|
+
[actions-url]: https://github.com/ljharb/qs/actions
|