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 https://github.com/swagger-api/swagger-ui/security/advisories/GHSA-qrmm-w75w-3wpx
This commit is contained in:
Vladimir Gorej
2021-12-09 17:28:17 +01:00
committed by GitHub
parent df7749b2fe
commit 01a3e55960
8 changed files with 30 additions and 9 deletions

View File

@@ -43,6 +43,13 @@ const defaultBaseConfig = {
type: "string", type: "string",
base: true base: true
} }
},
queryConfigEnabled: {
value: "false",
schema: {
type: "boolean",
base: true,
}
} }
} }

View File

@@ -23,6 +23,10 @@ const standardVariables = {
type: "string", type: "string",
name: "urls.primaryName" name: "urls.primaryName"
}, },
QUERY_CONFIG_ENABLED: {
type: "boolean",
name: "queryConfigEnabled"
},
LAYOUT: { LAYOUT: {
type: "string", type: "string",
name: "layout" name: "layout"

View File

@@ -31,6 +31,7 @@ Parameter name | Docker variable | Description
<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. <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.
<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. <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.
<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`. <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`.
<a name="queryConfigEnabled"></a>`queryConfigEnabled` | `QUERY_CONFIG_ENABLED` | `Boolean=false`. Enables overriding configuration parameters via URL search params.
##### Plugin system ##### Plugin system

View File

@@ -21,6 +21,7 @@ export default class SwaggerUI extends React.Component {
onComplete: this.onComplete, onComplete: this.onComplete,
docExpansion: this.props.docExpansion, docExpansion: this.props.docExpansion,
supportedSubmitMethods: this.props.supportedSubmitMethods, supportedSubmitMethods: this.props.supportedSubmitMethods,
queryConfigEnabled: this.props.queryConfigEnabled,
defaultModelExpandDepth: this.props.defaultModelExpandDepth, defaultModelExpandDepth: this.props.defaultModelExpandDepth,
displayOperationId: this.props.displayOperationId, displayOperationId: this.props.displayOperationId,
tryItOutEnabled: this.props.tryItOutEnabled, tryItOutEnabled: this.props.tryItOutEnabled,
@@ -99,6 +100,7 @@ SwaggerUI.propTypes = {
supportedSubmitMethods: PropTypes.arrayOf( supportedSubmitMethods: PropTypes.arrayOf(
PropTypes.oneOf(["get", "put", "post", "delete", "options", "head", "patch", "trace"]) PropTypes.oneOf(["get", "put", "post", "delete", "options", "head", "patch", "trace"])
), ),
queryConfigEnabled: PropTypes.bool,
plugins: PropTypes.arrayOf(PropTypes.object), plugins: PropTypes.arrayOf(PropTypes.object),
displayOperationId: PropTypes.bool, displayOperationId: PropTypes.bool,
showMutatedRequest: PropTypes.bool, showMutatedRequest: PropTypes.bool,
@@ -119,6 +121,7 @@ SwaggerUI.propTypes = {
SwaggerUI.defaultProps = { SwaggerUI.defaultProps = {
layout: "BaseLayout", layout: "BaseLayout",
supportedSubmitMethods: ["get", "put", "post", "delete", "options", "head", "patch", "trace"], supportedSubmitMethods: ["get", "put", "post", "delete", "options", "head", "patch", "trace"],
queryConfigEnabled: false,
docExpansion: "list", docExpansion: "list",
defaultModelsExpandDepth: 1, defaultModelsExpandDepth: 1,
presets: [], presets: [],

View File

@@ -77,6 +77,7 @@ export default function SwaggerUI(opts) {
"patch", "patch",
"trace" "trace"
], ],
queryConfigEnabled: false,
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance. // Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest. // 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) {
} }
} }
let queryConfig = parseSearch() let queryConfig = opts.queryConfigEnabled ? parseSearch() : {}
const domNode = opts.domNode const domNode = opts.domNode
delete opts.domNode delete opts.domNode

View File

@@ -56,7 +56,8 @@
} else { } else {
window.completeCount = 1 window.completeCount = 1
} }
} },
queryConfigEnabled: true,
}) })
window.ui = ui window.ui = ui

View File

@@ -65,7 +65,8 @@
} else { } else {
window.completeCount = 1 window.completeCount = 1
} }
} },
queryConfigEnabled: true,
}) })
window.ui = ui window.ui = ui

View File

@@ -109,6 +109,7 @@ describe("docker: env translator", function() {
SwaggerUIBundle.plugins.DownloadUrl SwaggerUIBundle.plugins.DownloadUrl
], ],
layout: "StandaloneLayout", layout: "StandaloneLayout",
queryConfigEnabled: false,
`)) `))
}) })
@@ -214,6 +215,7 @@ describe("docker: env translator", function() {
SwaggerUIBundle.plugins.DownloadUrl SwaggerUIBundle.plugins.DownloadUrl
], ],
layout: "StandaloneLayout", layout: "StandaloneLayout",
queryConfigEnabled: false,
url: "/swagger.json", url: "/swagger.json",
urls: ["/one", "/two"],` urls: ["/one", "/two"],`
@@ -313,6 +315,7 @@ describe("docker: env translator", function() {
plugins: [ plugins: [
SwaggerUIBundle.plugins.DownloadUrl SwaggerUIBundle.plugins.DownloadUrl
], ],
queryConfigEnabled: false,
configUrl: "/wow", configUrl: "/wow",
"dom_id": "#swagger_ui", "dom_id": "#swagger_ui",
spec: { swagger: "2.0" }, spec: { swagger: "2.0" },