Open Gidgidonihah opened 3 years ago
This is because SVGs are loaded as images which as per CSP is an "unsafe" source:
<img src="data:image/svg+xml;base64,..." alt="Swagger UI" height="40">
It should be replaced with inline SVG which has no such issues:
<svg xmlns="http://www.w3.org/2000/svg">...</svg>
Hello everybody,
Given @silverwind answer, this seems like something that can be fixed quite easily. Is anybody interested in issuing a PR?
@char0n probably this is due to the webpack pipeline. I think I had a look at it and the Image was imported via js import logo from 'some'
and placed in the src={logo}
. Maybe it could be change via webpack or it needs to be defined as svg inline.
Probably need to remove .svg
from url-loader
here and move it to raw-loader
and then load it via dangerouslySetInnerHTML
.
When can this change is available in swashbuckle .net core package means no inline styles and javascript and image displayed from data source in swagger index.html page? So that we can set Content-Security-Policy:default-src 'self'
Hello,
even with the change available, it seems img-src 'self' data:
is still needed. Will it be fixed as well ?
Hey,
Same here.
With the latest version of swagger-ui
i still need to use the unsafe approach img-src 'self' data:
.
It would be great to get off images declaration as data:image/svg+xml;base64,...
to make CSP happy.
Any update on this? Still running into this issue on the latest version.
Same here. I am using the most-strict CSP default-src 'self'; frame-ancestors 'none';
that works for my whole application except for the API documentation page based on Swagger UI.
Do you plan to fix this in the near future?
We need to use https://www.npmjs.com/package/@svgr/webpack avoid the CSP issue.
Addressed the SVG assets in https://github.com/swagger-api/swagger-ui/pull/9209
There are additional tree SVG embedded in SASS files. These needs to be handled as well.
Well with SVG assets embedded in CSS we have following options
This is possible to do but the build will have to have additional assets
directory. The issue will also be with build fragments distributed via different package systems. There were just two assets before - CSS and JavaScript file. This will introduce additional build fragments and will break established bundler configurations.
Instead of
<label htmlFor="servers">
<select onChange={ this.onServerChange } value={currentServer}>
{ servers.valueSeq().map(
( server ) =>
<option
value={ server.get("url") }
key={ server.get("url") }>
{ server.get("url") }
{ server.get("description") && ` - ${server.get("description")}` }
</option>
).toArray()}
</select>
</label>
We have to do:
<label htmlFor="servers">
<ArrowDownIcon />
<select onChange={ this.onServerChange } value={currentServer}>
{ servers.valueSeq().map(
( server ) =>
<option
value={ server.get("url") }
key={ server.get("url") }>
{ server.get("url") }
{ server.get("description") && ` - ${server.get("description")}` }
</option>
).toArray()}
</select>
</label>
This requires a lot of changes to existing React JSX.
I don't really like any of those options and I'm inclined to keep the status quo. Anybody has any other idea?
All right, I've merged https://github.com/swagger-api/swagger-ui/pull/9209. It helps the situation a bit, but doesn't resolve the issue completely. We still need to resolve https://github.com/swagger-api/swagger-ui/issues/7540#issuecomment-1718984278
I'd say data:
protocol is fine and should be part of any reasonable CSP because a lot of frontend js/css uses data:
uris for many purposes and they are kind of a self
source but were excluded from self
for whatever reason. If it works with below CSP, I'd say the issue is solved.
Content-Security-Policy "default-src 'self' data:"
Actually I think the original issue is invalid and unsafe-eval
was never needed, only data:
which is generally considered a "safe" source. I think the behaviour of unsafe-eval
for img-src
is not even defined in the spec and it's likely not matching on anything. Only these things classify for unsafe-eval
for style-src
and script-src
:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src#unsafe_style_expressions
If you decide to improve CSP compatibility, I would suggest doing it right, which would include avoiding data:
.
Imho, SVGs as static hardcoded data:
in CSS is perfectly fine and safe on it's own but of course, inline SVG in HTML would be ideal, which I guess means you have to touch all the JSX to extract to <svg>
components.
We'll most likely not be addressing the inline svg images in CSS. It's a big time investment not worth the effort.
I'll do another analysis and the goal is to fit SwaggerUI into Content-Security-Policy "default-src 'self' data:"
. (which I think we already fit after last PR).
If you decide to improve CSP compatibility, I would suggest doing it right, which would include avoiding data:.
We did enhance the situation, but complete remediation just for the sake of purity is currently out of question. We invite you to issue a PR though.
Imho, SVGs as static hardcoded data: in CSS is perfectly fine and safe on it's own but of course, inline SVG in HTML would be ideal
Agreed, It's not ideal but it's more than acceptable.
I'll document the recommended CSP depending on the the plugin composition (with or without Standalone plugin).
Using the data:
keyword in CSP seems to be a security issue.
For instance, it's an old thread but still valid: https://security.stackexchange.com/questions/94993/is-including-the-data-scheme-in-your-content-security-policy-safe
Moreover, some security scans are currently detecting the usage of data:
as a security vulnerability as well.
Do you have more informations about this ? I'm curious, and currently trying to get rid of this CSP directive.
I'm open to suggestions how to resolve this. I've already elaborated in https://github.com/swagger-api/swagger-ui/issues/7540#issuecomment-1718984278 what can be done. Both options have pros and cons.
IMHO ideal is to go for option 2 - refactor actual React components
.
Are there any other options you can think of?
I probed 2. refactor actual React components
and determined that it is quite significant effort. If there are any volunteers, that would be great.
Imho, refactor to react components, but make it generic, e.g. <Icon name="arrow-down"/>
.
Can we also include the script integrity for oauth2-redirect.html here https://github.com/swagger-api/swagger-ui/blob/e6837593bdeb6d489b6c8ffe288538c801aaf5a7/dist/oauth2-redirect.html#L7 ?
Quick google search gave me openssl dgst -sha384 -binary FILENAME.js | openssl base64 -A
on how to compute the checksum.
The most strict CSP I have found that still enables the site to function fully is:
Content-Security-Policy: default-src 'self'; img-src 'self' data: https://validator.swagger.io/; script-src 'self' 'sha256-5Fyhk/sAyk1LqSOCABSorU3lSp7aso7Uf5/J5HBwgDg='
worth noting these comments (but you should verify this is tolerable for your use case yourself):
# "data:" is generally considered insecure, but limited to "img-src" it seems tolerable:
# see: https://security.stackexchange.com/a/167244/271464
In flask I implement this with Talisman:
import os
from flask import Flask
from flask_talisman import Talisman
from flask_swagger_ui import get_swaggerui_blueprint
ROOT_PATH: str = os.path.dirname(os.path.abspath(__file__))
SWAGGER_URL = "/openapi/swagger" # URL for exposing Swagger UI (without trailing '/')
API_URL = "/openapi.yaml" # Our API url (can be a local resource or url)
app = Flask(__name__, static_folder="", root_path=ROOT_PATH)
swaggerui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL, # Swagger UI static files will be served at {SWAGGER_URL}/dist/
API_URL,
# config={}, # Swagger UI config overrides
# oauth_config={},
)
app.register_blueprint(swaggerui_blueprint)
# we need this CSP for talisman for swagger_ui to load:
# see: https://github.com/swagger-api/swagger-ui/issues/7540#issuecomment-1719302413
# and: https://github.com/swagger-api/swagger-ui/issues/7540#issue-1016654521
# and: https://github.com/GoogleCloudPlatform/flask-talisman?tab=readme-ov-file#content-security-policy
CSP = {
"default-src": ["'self'"],
# "data:" is generally considered insecure, but limited to "img-src" it seems tolerable:
# see: https://security.stackexchange.com/a/167244/271464
"img-src": ["'self'", "data:", "https://validator.swagger.io/"],
"script-src": ["'self'", "'sha256-5Fyhk/sAyk1LqSOCABSorU3lSp7aso7Uf5/J5HBwgDg='"],
}
talisman = Talisman(
app, strict_transport_security_preload=True, content_security_policy=CSP
)
Content-Security-Policy: default-src 'self'; img-src 'self' data: https://validator.swagger.io/; script-src 'self' 'sha256-5Fyhk/sAyk1LqSOCABSorU3lSp7aso7Uf5/J5HBwgDg='
Does not work, presumably the hash already changed.
The checkboxes in the Authorize-overlay cannot be checked anymore or at least the check marks don't appear since the resource is blocked. Finally the redirect from an OAuth-provider is blocked because of the inline handler. With A proper CSP swagger-ui is not usable with (OAuth) authorization. (And it is tedious to obtain and copy bearer tokens every couple minutes to a simple bearer input field)
Regarding the redirect there are also #5720 and #8330
Sorry if the question is dumb, but is it easy to compute the sha in the build pipeline and include in the nuget, or can we add something in our CI pipeline to compute it?
I don't see the reason for JavaScript-quirks to simply have an input of type checkbox checked (that are to be transferred as part of a form submit). But I also tolerate people using pliers to pull on trousers.
To answer the checksum-pipeline-question: as long as a checksum like in the comment above can be put into the appropriate resource. But with a CSP for a HTTP-server out of your control the answer cannot be other than »fix on customer side«. I can compute a checksum according to my needs which is tedious and breaks from time to time (with auto update tools for dependencies like Renovate). And others will return with the same error causing noise.
All the means of security can either be made right (avoid the unnecessary extensions/ reduce), undermined (by relaxing if possible) or left aside (making it unusable for contexts with strict security policies).
Q&A (please complete the following information)
Content & configuration
The default petstore example can be used.
Serve swagger-ui with a CSP that limits images, such as:
Describe the bug you're encountering
The swagger logo and icons are blocked when using a secure CSP. Swagger-ui should not use inline data images in the css for SVGs.
To reproduce...
Serve swagger-ui with a CSP that limits images, such as:
This will cause the browser to block images with a url starting with
data:image/svg+xml;
. The swagger-ui logo and expand/collapse icons are blocked.Expected behavior
The swagger logo and icons should not be blocked when using a secure CSP.
Screenshots
Additional context or thoughts
This can be worked around by using the CSP:
But, as is explicit in the header name, this is unsafe.
CSP in swagger-ui is a larger problem than this bug report
In this bug report, I kept it specific to the SVG images as I hadn't seen them mentioned in a bug report thus far. But CSP seems to be generally overlooked. I see no reason that swagger-ui should not work with a basic CSP:
As-is, I've had to build a very custom (see below) CSP that includes the hashes of various things to do with swagger-ui (across various versions) and also accept that the logo will look broken, and the expand/collaps icons are missing. This is not a great experience for the user.
See also: https://github.com/swagger-api/swagger-ui/issues/5817 https://github.com/swagger-api/swagger-ui/issues/3370 https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+content-security-policy