diff --git a/package.json b/package.json
index 14456728..18229513 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"test": "npm run lint-errors && npm run just-test-in-node",
"test-in-node": "npm run lint-errors && npm run just-test-in-node",
"just-test": "karma start --config karma.conf.js",
- "just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package",
+ "just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
"test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json",
"e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render",
"mock-api": "json-server --watch test/e2e/db.json --port 3204",
diff --git a/src/core/components/providers/markdown.jsx b/src/core/components/providers/markdown.jsx
index 2b21c10b..2ef8b6a6 100644
--- a/src/core/components/providers/markdown.jsx
+++ b/src/core/components/providers/markdown.jsx
@@ -29,7 +29,10 @@ Markdown.propTypes = {
export default Markdown
const sanitizeOptions = {
- allowedTags: sanitize.defaults.allowedTags.concat([ "img" ]),
+ allowedTags: sanitize.defaults.allowedTags.concat([ "h1", "h2", "img" ]),
+ allowedAttributes: {
+ "img": sanitize.defaults.allowedAttributes.img.concat(["title"])
+ },
textFilter: function(text) {
return text.replace(/"/g, "\"")
}
diff --git a/src/core/components/response-body.jsx b/src/core/components/response-body.jsx
index 265ff679..c55c1d6d 100644
--- a/src/core/components/response-body.jsx
+++ b/src/core/components/response-body.jsx
@@ -83,8 +83,12 @@ export default class ResponseBody extends React.Component {
// Anything else (CORS)
} else if (typeof content === "string") {
bodyEl =
- } else {
+ } else if ( content.size > 0 ) {
+ // We don't know the contentType, but there was some content returned
bodyEl =
diff --git a/src/core/plugins/download-url.js b/src/core/plugins/download-url.js
index c8dff0b8..d80e982b 100644
--- a/src/core/plugins/download-url.js
+++ b/src/core/plugins/download-url.js
@@ -7,13 +7,16 @@ export default function downloadUrlPlugin (toolbox) {
let { fn } = toolbox
const actions = {
- download: (url)=> ({ errActions, specSelectors, specActions }) => {
+ download: (url)=> ({ errActions, specSelectors, specActions, getConfigs }) => {
let { fetch } = fn
+ const config = getConfigs()
url = url || specSelectors.url()
specActions.updateLoadingStatus("loading")
fetch({
url,
loadSpec: true,
+ requestInterceptor: config.requestInterceptor || (a => a),
+ responseInterceptor: config.responseInterceptor || (a => a),
credentials: "same-origin",
headers: {
"Accept": "application/json,*/*"
diff --git a/src/core/plugins/oas3/wrap-components/markdown.js b/src/core/plugins/oas3/wrap-components/markdown.js
index 103a2801..2d7f27e7 100644
--- a/src/core/plugins/oas3/wrap-components/markdown.js
+++ b/src/core/plugins/oas3/wrap-components/markdown.js
@@ -1,10 +1,11 @@
import React from "react"
+import PropTypes from "prop-types"
import ReactMarkdown from "react-markdown"
import { Parser, HtmlRenderer } from "commonmark"
import { OAS3ComponentWrapFactory } from "../helpers"
import { sanitizer } from "core/components/providers/markdown"
-export default OAS3ComponentWrapFactory(({ source }) => {
+export const Markdown = ({ source }) => {
if ( source ) {
const parser = new Parser()
const writer = new HtmlRenderer()
@@ -23,4 +24,9 @@ export default OAS3ComponentWrapFactory(({ source }) => {
)
}
return null
-})
\ No newline at end of file
+}
+Markdown.propTypes = {
+ source: PropTypes.string
+}
+
+export default OAS3ComponentWrapFactory(Markdown)
\ No newline at end of file
diff --git a/src/style/_layout.scss b/src/style/_layout.scss
index 9b38a700..95584a7c 100644
--- a/src/style/_layout.scss
+++ b/src/style/_layout.scss
@@ -543,14 +543,14 @@
.response-col_description__inner
{
- span
+ div.markdown, div.renderedMarkdown
{
font-size: 12px;
font-style: italic;
display: block;
- margin: 10px 0;
+ margin: 0;
padding: 10px;
border-radius: 4px;
diff --git a/test/components/markdown.js b/test/components/markdown.js
new file mode 100644
index 00000000..01a55e1c
--- /dev/null
+++ b/test/components/markdown.js
@@ -0,0 +1,48 @@
+/* eslint-env mocha */
+import React from "react"
+import expect from "expect"
+import { render } from "enzyme"
+import Markdown from "components/providers/markdown"
+import { Markdown as OAS3Markdown } from "corePlugins/oas3/wrap-components/markdown.js"
+
+describe("Markdown component", function() {
+ describe("Swagger 2.0", function() {
+ it("allows image elements", function() {
+ const str = ``
+ const el = render(
)
+ expect(el.html()).toEqual(`

\n
`)
+ })
+
+ it("allows heading elements", function() {
+ const str = `
+# h1
+## h2
+### h3
+#### h4
+##### h5
+###### h6`
+ const el = render(
)
+ expect(el.html()).toEqual(`
h1
\nh2
\nh3
\nh4
\nh5
\nh6
\n`)
+ })
+ })
+
+ describe("OAS 3", function() {
+ it("allows image elements", function() {
+ const str = ``
+ const el = render(
)
+ expect(el.html()).toEqual(`
`)
+ })
+
+ it("allows heading elements", function() {
+ const str = `
+# h1
+## h2
+### h3
+#### h4
+##### h5
+###### h6`
+ const el = render(
)
+ expect(el.html()).toEqual(`
`)
+ })
+ })
+})
diff --git a/test/xss/info-sanitization.js b/test/xss/info-sanitization.js
new file mode 100644
index 00000000..e868fe9f
--- /dev/null
+++ b/test/xss/info-sanitization.js
@@ -0,0 +1,33 @@
+/* eslint-env mocha */
+import React from "react"
+import expect from "expect"
+import { render } from "enzyme"
+import { fromJS } from "immutable"
+import Info from "components/info"
+import Markdown from "components/providers/markdown"
+
+describe("
Sanitization", function(){
+ const dummyComponent = () => null
+ const components = {
+ Markdown
+ }
+ const props = {
+ getComponent: c => components[c] || dummyComponent,
+ info: fromJS({
+ title: "Test Title **strong** ",
+ description: "Description *with* "
+ }),
+ host: "example.test",
+ basePath: "/api"
+ }
+
+ it("renders sanitized .title content", function(){
+ let wrapper = render(
)
+ expect(wrapper.find(".title").html()).toEqual("Test Title **strong** <script>alert(1)</script>")
+ })
+
+ it("renders sanitized .description content", function() {
+ let wrapper = render(
)
+ expect(wrapper.find(".description").html()).toEqual("
")
+ })
+})
diff --git a/test/xss/markdown-script-sanitization.js b/test/xss/markdown-script-sanitization.js
new file mode 100644
index 00000000..9d6624c7
--- /dev/null
+++ b/test/xss/markdown-script-sanitization.js
@@ -0,0 +1,36 @@
+/* eslint-env mocha */
+import React from "react"
+import expect from "expect"
+import { render } from "enzyme"
+import Markdown from "components/providers/markdown"
+import { Markdown as OAS3Markdown } from "corePlugins/oas3/wrap-components/markdown.js"
+
+describe("Markdown Script Sanitization", function() {
+ describe("Swagger 2.0", function() {
+ it("sanitizes `
+ const el = render(
)
+ expect(el.html()).toEqual(`
`)
+ })
+
+ it("sanitizes
![]()
elements", function() {
+ const str = `

`
+ const el = render(
)
+ expect(el.html()).toEqual(`

\n
`)
+ })
+ })
+
+ describe("OAS 3", function() {
+ it("sanitizes `
+ const el = render(
)
+ expect(el.html()).toEqual(`
`)
+ })
+
+ it("sanitizes
![]()
elements", function() {
+ const str = `

`
+ const el = render(
)
+ expect(el.html()).toEqual(`
`)
+ })
+ })
+})