swagger-ui
swagger-ui copied to clipboard
Swagger-ui appears to require 'unsafe-eval' in CSP Headers
Q&A (please complete the following information)
- OS: [MacOS v10.14.5] but really N/A
- Browser: [Chrome] (or any modern browser)
- Version: [Version 79.0.3945.130 (Official Build) (64-bit)]
- Method of installation: [maven via org.webjars::swagger-ui]
- Swagger-UI version: [3.22.1]
- Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0]
Content & configuration
Here's a quick image of the console error:

Here's a detailed callstack if I break on the thrown error: `
| eval | @ | VM240:1 |
|---|---|---|
| (anonymous) | @ | |
| w | @ | |
| (anonymous) | @ | |
| e. |
@ | |
| r | @ | |
| (anonymous) | @ | |
| Promise.then (async) | ||
| r | @ | |
| (anonymous) | @ | |
| t | @ | |
| (anonymous) | @ | |
| b | @ | |
| E | @ | |
| w | @ | |
| setTimeout (async) | ||
| (anonymous) | @ | |
| x | @ | |
| (anonymous) | @ | |
| (anonymous) | @ | |
| (anonymous) | @ | |
| i.requestResolvedSubtree | @ | |
| i.toggleShown | @ | |
| o | @ | |
| u | @ | |
| executeDispatchesInOrder | @ | |
| f | @ | |
| d | @ | |
| e.exports | @ | |
| processEventQueue | @ | |
| (anonymous) | @ | |
| handleTopLevel | @ | |
| d | @ | |
| perform | @ | |
| batchedUpdates | @ | |
| batchedUpdates | @ | |
| dispatchEvent | @ | |
| ` |
Describe the bug you're encountering
Quite simply: if my nginx configuration is set to exclude 'unsafe-eval' for the 'script-src' directive of the Content-Security-Policy, the Swagger-UI is choking due to an error - in this case specifically due to the usage of new Function(...) which relies on eval to execute at runtime (not the best practice).
I've cloned the git repo and looked at the code in your "src" directory and do not see any offending usages of calls to new Function constructors. It does, however, turn up a number of matches inside the "dist" director including the "swagger-ui-bundle.js". Unfortunately this suggests the code is being included in from 3rd party npm dependencies bundled via webpack.
To reproduce...
Steps to reproduce the behavior:
-
swagger is being deployed behind nginx. The nginx server block in the config contains something like this:
server { ... location /swagger { ... add_header Content-Security-Policy "default-src 'self'; script-src 'self';" always; ... }which explicitly does not have the 'unsafe-eval' option enabled. -
Load swagger in your browser:
https://<ip-address>/swagger -
Scroll down to some API endpoint e.g. "Foo" and click to expand it
-
Scroll to any specific request option: e.g. GET /foo and click to expend it
Expected behavior
Expect the UI view to expand open to view documentation detail, model definitions, and the typical "try it out" button to execute an interactive request against the api
Actual - a small section expands down but is empty. The only way to see that something is wrong is inside the browser console. which throws the error regarding blocked eval for Function
Screenshots
Additional context or thoughts
@BrandKNY , I observe a similar issue. To debug and workaround it I was using the next piece of code:
Object.defineProperty(window, 'Function', {
get: function() {
return function () {
console.log(arguments);
debugger;
};
}
});
Could you look where exactly is it calling the Function for you?
It seems, for my case it is https://github.com/swagger-api/swagger-js/blob/2063f8e8cbdb35e0493e32014e40d561ccfdbe59/src/specmap/index.js#L353 .
In my case this appears to be triggered by regenerator-runtime:
https://github.com/facebook/regenerator/blob/master/packages/regenerator-runtime/runtime.js#L728
It's trying to define regeneratorRuntime in the global context, but is being prevented by "use strict", which doesn't allow assigning to undeclared variables. (This might be introduced by the Angular build somewhere, I'm not sure.) So it falls back to calling the Function to try to escape the "use strict", which runs afoul of the CSP protection.
My fix (such as it is) is to pre-emptively define regeneratorRuntime in the global context, by including this in the <head> of my main HTML file:
<script>
regeneratorRuntime = undefined;
</script>
I am getting similar behavior, but worse, I get a blank screen in the swagger UI, my target CSP is
context.Response.Headers.Add("Content-Security-Policy", "script-src 'self'");
For anyone coming across this in the future, this CSP Config works with swagger - at least for me:
defaultSrc 'self';
styleSrc: 'self' 'unsafe-inline';
imgSrc: 'self' validator.swagger.io
scriptSrc: 'self' 'unsafe-inline'
One reason to have a Content Security Policy in place is to make it impossible to manipulate a page in a way where inline scripts with malicious code are being executed. So it would be very nice if swagger would find a way to not rely on inline styles and scripts in order to make a stricter CSP possible.
Although one could argue that its not necessary on a swagger site because only trusted people can manipulate the sites content. But it would still be nice to see improvement here. (Inline styles and scripts are bad practice anyway 😉 )
Although one could argue that its not necessary on a swagger site because only trusted people can manipulate the sites content. But it would still be nice to see improvement here. (Inline styles and scripts are bad practice anyway wink )
Please refer to https://github.com/swagger-api/swagger-ui/security/advisories/GHSA-qrmm-w75w-3wpx -> https://www.vidocsecurity.com/blog/hacking-swagger-ui-from-xss-to-account-takeovers/ for an concrete example of how an URL-based reflected XSS can be used to inject malicious inline scripts into the swagger-ui DOM.
This is exactly the kind of vulnerability/attack that CSP is supposed to mitigate, but this is not possible if the normal operation of the page requires script-src -> 'unsafe-eval' or 'unsafe-inline' :frowning_face: