-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Defined location/href of Constructed Stylesheets #95
Comments
Thanks for filing this. I think the addition makes sense, however I think we should be fine with just defining a base URL (so we don't need the (also, cc-ing @tabatkins @bzbarsky @domenic) |
My questions here revolve around spoofing and security risks. Presumably we'd want to only allow an href value that could be an href of a sheet loaded by this document (e.g. no file:// URL stylesheets attached to http:// documents)? What other restrictions might we need? What referrer is sent with the stylesheet subresource loads? Would this allow spoofing a not-same-site referrer? If we just set the base URL, but keep the sheet URL as the document URL and ensure it's the thing that's used in all sorts of security checks, referrer headers, etc, etc, I think most of those issues don't arise. |
To expand on this, right now if you attach a file:// stylesheet, e.g. as a user sheet, to an http:// document, that file:// sheet can link to other file:// resources, for obvious reasons. So we would want to prevent being able to spoof a sheet being file://. |
yep, we don't need the "filename" as part of the full url resolution, i guess it could be named
yes, we should prevent file:// and follow CSP if specified, with respect the const stylesheet = new CSSStyleSheet({
location: 'https://unpkg.com/my-collection/dist/assets'
});
stylesheet.replace(`
body {
background: url('./image.png')
}
`); would be equivalent to: const stylesheet = new CSSStyleSheet();
stylesheet.replace(`
body {
background: url('https://unpkg.com/my-collection/dist/assets')
}
`); But the |
In order to workaround this issue, I am building a PostCSS transform that injects certain comments at specific locations within the CSS text: - background: url('./image.png')
+ background: url(/*!baseURL*/'./image.png')
- background: url('/image.png')
+ background: url(/*!origin*/'/image.png') This way, at runtime, we can perfom a quick find-replace over the stylesheet text before parsing them with cssText = cssText
.replace(/\/\*baseURL\*\//g, resourcesURL)
.replace(/\/\*origin\*\//g, resourcesOrigin);
const stylesheet = new CSSStylesheet();
stylesheet.replace(cssText); I believe this transform of relative paths to absolute URLs could be done internally by |
That's exactly what the stylesheet base URL is used for, yes. At least in Gecko. |
@bzbarsky thanks cool! so exactly that for Constructable Stylesheets I guess :) |
Yes, after reading stylesheet referrer and relative URL specs, it seems like it would be better to just leave the stylesheet's |
@rakina would that option be passed down in the constructor? new CSSStyleSheet({
baseURL,
}); that would work perfect for us! |
The CSS Working Group just discussed
The full IRC log of that discussion<stantonm> topic: Defined location/href of Constructed Stylesheets<astearns> github: https://github.com//issues/95 <stantonm> heycam: regular non-constructable style sheets have url to resolve other stylesheets <stantonm> with constructable, no facility to provide url <stantonm> ... regular urls are resolved against document <stantonm> ... you might want to be able to specify <stantonm> TabAtkins: web component wants css to also be relative to some 3rd party url? <stantonm> ... can't hardcode deployment url, how do you use to it to get relative url <stantonm> ... when user says background.png, want it to use 3rd party load path - currently uses first party <stantonm> heycam: read issue as today there's not a good way to do this <stantonm> TabAtkins: splitting parts of URL, base part still might be hard to obtain <stantonm> ... url is hardcoded somewhere...just elsewhere than your stylesheet pipeline <stantonm> hober: probably fine to set base and location as specified <stantonm> heycam: not speficying url of sheet itself <stantonm> hober: yes, sheet url is same as document url <stantonm> RESOLVED: add base URL constructor argument for sole purpose of resolving relative URLs in stylesheet, and location of the stylesheet remains that of the document <TabAtkins> TabAtkins: And do we need to note the security concerns that bz raised, like with file:// etc? <TabAtkins> hober: Those are addressed by instead doing this as just a relative-url resolver, and keeping the stylesheet location the same. <TabAtkins> TabAtkins: Cool. |
How should the For example, if someone provides:
could we resolve this to |
I think the right answer it to pass it through Unless others do think it's useful to resolve it as |
Or more likely as |
Right, thanks. |
The majority of URL-accepting APIs resolve relative to the current settings object's API base URL. (I.e., document.baseURI.) The only exception I'm aware of that requires absolute URLs is the WebSocket constructor, and that because it's not possible to have a relative URL end up with the ws:/wss: scheme. So, I'd encourage us to be consistent. |
Cool, I wasn't sure of the consistency. More than happy to be consistent there. |
Constructed Stylesheets use the same location (base path) as the document, this makes it impossible to use relative links inside,
url()
, or@import()
when deploying reusable components.This is an important problem to solve when using CSS that could be imported from a CDN or any non-determined path.
Let's say a web component that uses
CSSStylesheet
is imported from the following url:https://unpkg.com/my-super-css-component/dist/index.js
And it contains some styles that will loaded using Constructable Stylesheets and adopted by some shadow-root:
We would like the user-agent to load:
https://unpkg.com/my-super-css-component/dist/background.png
but instead it will load:
https://mydomain.com/path/to/page/background.png
Today, there is not a good solution for this problem, since:
Making the path absolute
url('/my-super-css-component/dist/background.png')
would still load the resource from the wrong origin.It's not always possible to hard code the full deployment URL, since it's likely to change or being deployment in mutable places (different paths and origins).
Proposal
When a
CSSStylesheet
is instantiated, it takes an optionalhref
, that can be defined by JS to simulate the stylesheet has an path and origin different than thedocument
, just like it was loaded using<link rel="stylesheet" href>
:This way the any relative paths, including
@import
andurl()
would resolve based in the CSSStylesheet's specifiedhref
.The text was updated successfully, but these errors were encountered: