Skip to content

Commit 01a3e55

Browse files
authored
fix(security): disable reading config params from URL search params (#7697)
Reading configuration parameters from URL search params is by default no longer enabled. To re-enable it, set queryConfigEnabled configuration parameter to true. Functionally, this is a breaking change, but given we're just providing a security vulnerability patch we're considering this a PATCH version bump only. Refs #4872 Refs GHSA-qrmm-w75w-3wpx
1 parent df7749b commit 01a3e55

File tree

8 files changed

+30
-9
lines changed

8 files changed

+30
-9
lines changed

docker/configurator/translator.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ const defaultBaseConfig = {
4343
type: "string",
4444
base: true
4545
}
46+
},
47+
queryConfigEnabled: {
48+
value: "false",
49+
schema: {
50+
type: "boolean",
51+
base: true,
52+
}
4653
}
4754
}
4855

@@ -51,14 +58,14 @@ function objectToKeyValueString(env, { injectBaseConfig = false, schema = config
5158
const keys = Object.keys(env)
5259

5360
// Compute an intermediate representation that holds candidate values and schemas.
54-
//
61+
//
5562
// This is useful for deduping between multiple env keys that set the same
5663
// config variable.
5764

5865
keys.forEach(key => {
5966
const varSchema = schema[key]
6067
const value = env[key]
61-
68+
6269
if(!varSchema) return
6370

6471
if(varSchema.onFound) {
@@ -88,8 +95,8 @@ function objectToKeyValueString(env, { injectBaseConfig = false, schema = config
8895

8996
Object.keys(valueStorage).forEach(key => {
9097
const value = valueStorage[key]
91-
92-
const escapedName = /[^a-zA-Z0-9]/.test(key) ? `"${key}"` : key
98+
99+
const escapedName = /[^a-zA-Z0-9]/.test(key) ? `"${key}"` : key
93100

94101
if (value.schema.type === "string") {
95102
result += `${escapedName}: "${value.value}",\n`
@@ -101,4 +108,4 @@ function objectToKeyValueString(env, { injectBaseConfig = false, schema = config
101108
return result.trim()
102109
}
103110

104-
module.exports = objectToKeyValueString
111+
module.exports = objectToKeyValueString

docker/configurator/variables.js

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ const standardVariables = {
2323
type: "string",
2424
name: "urls.primaryName"
2525
},
26+
QUERY_CONFIG_ENABLED: {
27+
type: "boolean",
28+
name: "queryConfigEnabled"
29+
},
2630
LAYOUT: {
2731
type: "string",
2832
name: "layout"

docs/usage/configuration.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Parameter name | Docker variable | Description
3131
<a name="url"></a>`url` | `URL` | `String`. The URL pointing to API definition (normally `swagger.json` or `swagger.yaml`). Will be ignored if `urls` or `spec` is used.
3232
<a name="urls"></a>`urls` | `URLS` | `Array`. An array of API definition objects (`[{url: "<url1>", name: "<name1>"},{url: "<url2>", name: "<name2>"}]`) used by Topbar plugin. When used and Topbar plugin is enabled, the `url` parameter will not be parsed. Names and URLs must be unique among all items in this array, since they're used as identifiers.
3333
<a name="urls.primaryName"></a>`urls.primaryName` | `URLS_PRIMARY_NAME` | `String`. When using `urls`, you can use this subparameter. If the value matches the name of a spec provided in `urls`, that spec will be displayed when Swagger UI loads, instead of defaulting to the first spec in `urls`.
34+
<a name="queryConfigEnabled"></a>`queryConfigEnabled` | `QUERY_CONFIG_ENABLED` | `Boolean=false`. Enables overriding configuration parameters via URL search params.
3435

3536
##### Plugin system
3637

flavors/swagger-ui-react/index.jsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default class SwaggerUI extends React.Component {
2121
onComplete: this.onComplete,
2222
docExpansion: this.props.docExpansion,
2323
supportedSubmitMethods: this.props.supportedSubmitMethods,
24+
queryConfigEnabled: this.props.queryConfigEnabled,
2425
defaultModelExpandDepth: this.props.defaultModelExpandDepth,
2526
displayOperationId: this.props.displayOperationId,
2627
tryItOutEnabled: this.props.tryItOutEnabled,
@@ -29,7 +30,7 @@ export default class SwaggerUI extends React.Component {
2930
showMutatedRequest: typeof this.props.showMutatedRequest === "boolean" ? this.props.showMutatedRequest : true,
3031
deepLinking: typeof this.props.deepLinking === "boolean" ? this.props.deepLinking : false,
3132
showExtensions: this.props.showExtensions,
32-
filter: ["boolean", "string"].includes(typeof this.props.filter) ? this.props.filter : false,
33+
filter: ["boolean", "string"].includes(typeof this.props.filter) ? this.props.filter : false,
3334
})
3435

3536
this.system = ui
@@ -99,6 +100,7 @@ SwaggerUI.propTypes = {
99100
supportedSubmitMethods: PropTypes.arrayOf(
100101
PropTypes.oneOf(["get", "put", "post", "delete", "options", "head", "patch", "trace"])
101102
),
103+
queryConfigEnabled: PropTypes.bool,
102104
plugins: PropTypes.arrayOf(PropTypes.object),
103105
displayOperationId: PropTypes.bool,
104106
showMutatedRequest: PropTypes.bool,
@@ -119,6 +121,7 @@ SwaggerUI.propTypes = {
119121
SwaggerUI.defaultProps = {
120122
layout: "BaseLayout",
121123
supportedSubmitMethods: ["get", "put", "post", "delete", "options", "head", "patch", "trace"],
124+
queryConfigEnabled: false,
122125
docExpansion: "list",
123126
defaultModelsExpandDepth: 1,
124127
presets: [],

src/core/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export default function SwaggerUI(opts) {
7777
"patch",
7878
"trace"
7979
],
80+
queryConfigEnabled: false,
8081

8182
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
8283
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
@@ -108,7 +109,7 @@ export default function SwaggerUI(opts) {
108109
}
109110
}
110111

111-
let queryConfig = parseSearch()
112+
let queryConfig = opts.queryConfigEnabled ? parseSearch() : {}
112113

113114
const domNode = opts.domNode
114115
delete opts.domNode

test/e2e-cypress/static/index.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
} else {
5757
window.completeCount = 1
5858
}
59-
}
59+
},
60+
queryConfigEnabled: true,
6061
})
6162

6263
window.ui = ui

test/e2e-cypress/static/pages/5138/index.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
} else {
6666
window.completeCount = 1
6767
}
68-
}
68+
},
69+
queryConfigEnabled: true,
6970
})
7071

7172
window.ui = ui

test/unit/docker/translator.js

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ describe("docker: env translator", function() {
109109
SwaggerUIBundle.plugins.DownloadUrl
110110
],
111111
layout: "StandaloneLayout",
112+
queryConfigEnabled: false,
112113
`))
113114
})
114115

@@ -214,6 +215,7 @@ describe("docker: env translator", function() {
214215
SwaggerUIBundle.plugins.DownloadUrl
215216
],
216217
layout: "StandaloneLayout",
218+
queryConfigEnabled: false,
217219
url: "/swagger.json",
218220
urls: ["/one", "/two"],`
219221

@@ -313,6 +315,7 @@ describe("docker: env translator", function() {
313315
plugins: [
314316
SwaggerUIBundle.plugins.DownloadUrl
315317
],
318+
queryConfigEnabled: false,
316319
configUrl: "/wow",
317320
"dom_id": "#swagger_ui",
318321
spec: { swagger: "2.0" },

0 commit comments

Comments
 (0)