Преглед на файлове

Add URL sanitizer to avoid `javascript:` XSS attack vector

bubble
Kyle Shockey преди 6 години
родител
ревизия
afa615e01d
променени са 6 файла, в които са добавени 22 реда и са изтрити 12 реда
  1. +1
    -0
      package.json
  2. +7
    -6
      src/core/components/info.jsx
  3. +5
    -2
      src/core/components/online-validator-badge.jsx
  4. +2
    -1
      src/core/components/operation.jsx
  5. +2
    -2
      src/core/components/operations.jsx
  6. +5
    -1
      src/core/utils.js

+ 1
- 0
package.json Целия файл

@@ -39,6 +39,7 @@
"e2e": "npm-run-all --parallel -r hot-server mock-api test-e2e"
},
"dependencies": {
"@braintree/sanitize-url": "^2.0.2",
"base64-js": "^1.2.0",
"brace": "0.7.0",
"classnames": "^2.2.5",


+ 7
- 6
src/core/components/info.jsx Целия файл

@@ -2,6 +2,7 @@ import React from "react"
import PropTypes from "prop-types"
import { fromJS } from "immutable"
import ImPropTypes from "react-immutable-proptypes"
import { sanitizeUrl } from "core/utils"


class Path extends React.Component {
@@ -35,9 +36,9 @@ class Contact extends React.Component {

return (
<div>
{ url && <div><a href={ url } target="_blank">{ name } - Website</a></div> }
{ url && <div><a href={ sanitizeUrl(url) } target="_blank">{ name } - Website</a></div> }
{ email &&
<a href={`mailto:${email}`}>
<a href={sanitizeUrl(`mailto:${email}`)}>
{ url ? `Send email to ${name}` : `Contact ${name}`}
</a>
}
@@ -59,7 +60,7 @@ class License extends React.Component {
return (
<div>
{
url ? <a target="_blank" href={ url }>{ name }</a>
url ? <a target="_blank" href={ sanitizeUrl(url) }>{ name }</a>
: <span>{ name }</span>
}
</div>
@@ -97,7 +98,7 @@ export default class Info extends React.Component {
{ version && <VersionStamp version={version}></VersionStamp> }
</h2>
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
{ url && <a target="_blank" href={ url }><span className="url"> { url } </span></a> }
{ url && <a target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></a> }
</hgroup>

<div className="description">
@@ -106,14 +107,14 @@ export default class Info extends React.Component {

{
termsOfService && <div>
<a target="_blank" href={ termsOfService }>Terms of service</a>
<a target="_blank" href={ sanitizeUrl(termsOfService) }>Terms of service</a>
</div>
}

{ contact && contact.size ? <Contact data={ contact } /> : null }
{ license && license.size ? <License license={ license } /> : null }
{ externalDocsUrl ?
<a target="_blank" href={externalDocsUrl}>{externalDocsDescription || externalDocsUrl}</a>
<a target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</a>
: null }

</div>


+ 5
- 2
src/core/components/online-validator-badge.jsx Целия файл

@@ -1,5 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import { sanitizeUrl } from "core/utils"

export default class OnlineValidatorBadge extends React.Component {
static propTypes = {
@@ -32,6 +33,8 @@ export default class OnlineValidatorBadge extends React.Component {
let { getConfigs } = this.props
let { spec } = getConfigs()

let sanitizedValidatorUrl = sanitizeUrl(this.state.validatorUrl)

if ( typeof spec === "object" && Object.keys(spec).length) return null

if (!this.state.url || !this.state.validatorUrl || this.state.url.indexOf("localhost") >= 0
@@ -40,8 +43,8 @@ export default class OnlineValidatorBadge extends React.Component {
}

return (<span style={{ float: "right"}}>
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}>
<ValidatorImage src={`${ this.state.validatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
<a target="_blank" href={`${ sanitizedValidatorUrl }/debug?url=${ this.state.url }`}>
<ValidatorImage src={`${ sanitizedValidatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
</a>
</span>)
}


+ 2
- 1
src/core/components/operation.jsx Целия файл

@@ -2,6 +2,7 @@ import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import { getList } from "core/utils"
import * as CustomPropTypes from "core/proptypes"
import { sanitizeUrl } from "core/utils"

//import "less/opblock"

@@ -206,7 +207,7 @@ export default class Operation extends PureComponent {
<span className="opblock-external-docs__description">
<Markdown source={ externalDocs.get("description") } />
</span>
<a className="opblock-external-docs__link" href={ externalDocs.get("url") }>{ externalDocs.get("url") }</a>
<a className="opblock-external-docs__link" href={ sanitizeUrl(externalDocs.get("url")) }>{ externalDocs.get("url") }</a>
</div>
</div> : null
}


+ 2
- 2
src/core/components/operations.jsx Целия файл

@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import { helpers } from "swagger-client"
import { createDeepLinkPath } from "core/utils"
import { createDeepLinkPath, sanitizeUrl } from "core/utils"
const { opId } = helpers

export default class Operations extends React.Component {
@@ -101,7 +101,7 @@ export default class Operations extends React.Component {
{ tagExternalDocsUrl ? ": " : null }
{ tagExternalDocsUrl ?
<a
href={tagExternalDocsUrl}
href={sanitizeUrl(tagExternalDocsUrl)}
onClick={(e) => e.stopPropagation()}
target={"_blank"}
>{tagExternalDocsUrl}</a> : null


+ 5
- 1
src/core/utils.js Целия файл

@@ -1,5 +1,5 @@
import Im from "immutable"
import { sanitizeUrl as braintreeSanitizeUrl } from "@braintree/sanitize-url"
import camelCase from "lodash/camelCase"
import upperFirst from "lodash/upperFirst"
import _memoize from "lodash/memoize"
@@ -722,6 +722,10 @@ export const shallowEqualKeys = (a,b, keys) => {
})
}

export function sanitizeUrl(url) {
return braintreeSanitizeUrl(url)
}

export function getAcceptControllingResponse(responses) {
if(!Im.OrderedMap.isOrderedMap(responses)) {
// wrong type!


Зареждане…
Отказ
Запис