Skip to content
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

JS playgrounds leak permissions. Guidelines and examples needed #547

Closed
jan-ivar opened this issue May 6, 2024 · 10 comments · Fixed by #548
Closed

JS playgrounds leak permissions. Guidelines and examples needed #547

jan-ivar opened this issue May 6, 2024 · 10 comments · Fixed by #548

Comments

@jan-ivar
Copy link
Member

jan-ivar commented May 6, 2024

To summarize w3c/mediacapture-main#991, "JS playground" websites marketed at web developers are growing from awesome learning tools to mainstream development platforms, but remain risky to use permission-wise. Typically they use e.g. (simplified):

<iframe allow="camera" src="//users.site.net/user123/4" sandbox="allow-same-origin ...">

This leaks camera permission after use in a single piece of user-generated content to all user-generated content on the site. End-users experience this as an "unexpectedly broad" grant and a breach of trust — some blame the site others blame the browser — they expected permission to be local to the content (e.g. "game" or "fiddle") in front of them.

Github.io seems a good example of how to isolate permissions (and cookies): It separates user-created content into separate domains. But I've found no such exemplar using iframes. Nonetheless, we can extrapolate an answer (Edit: this is still problematic, see below):

<iframe allow="camera" src="//user123.site.io/4" sandbox="allow-same-origin ...">

More generally, websites that introduce markets of third-party installable content "plugins" (not web extensions) or "games", would presumably need bespoke permission UX for each at install time, and again use separate (sub) domains to implement:

<iframe allow="camera //vimeo-plugin.figma.io //twitch-plugin.figma.io src"
        src="//doc123.figma.io/4" sandbox="allow-same-origin ...">

None of this seems unique to camera or microphone so I'm raising it here. Is this how sites that introduce user-generated or discrete-developer-generated web content units are expected to manage permissions to powerful features?

When coming up with these answers, I had a hard time finding documentation. E.g. I had to look at the ABNF to learn multiple urls are accepted in allow=. Neither MDN nor any of the spec examples showed this.

If this spec is the right owner of this problem, then an example or two to point at might be useful.

@annevk
Copy link
Member

annevk commented May 7, 2024

How is this different from storage, cookies, or the cache leaking all over the playground? This is how the web's security model works.

I don't think there's a good solution here apart from using subdomains and registering your domain as registrable domain.

@rockinghelvetica
Copy link

rockinghelvetica commented May 7, 2024

I originally reported this to the media capture spec, because the stored permission for a camera strictly scoping to the top-level document doesn't work like storage, cookies, et al. There's an opinionated spec decision to side-step the hairy UX of conflating 2+ parties' trust in the UI prompt.

In discussion, @jan-ivar is starting to bring me around to the idea that this might be a Policy concern. As a web user I'm eager to see this less as the browser's remit — it's a recipe for anticompetitive motivations (permissions as a moat), and it's very confusing about how to be responsible.

The weird edge for me is less to do with the defaults, but rather: as a developer working in an iframe context, I cannot request a narrower scope. Perhaps this is intractable from fingerprinting, but I currently can't use the webcam on my own Replit app without opening up my device to the entire domain.

I respect that a solution exists for the embedding sites (subdomains + allow) but it's proving to be ineffective, in that few (no?) major sites supporting plugins or user scripts seems to do this work. GitHub is somewhat exceptional for avoiding the risk.

  1. What would break if a child-navigable could request a narrower origin with respect to the stored permission, without changing the rest of the model?
  2. Could a new constraint be introduced? Conceptually like how I can harmlessly extend an email alias with +string when providing my personal data to a site. The request might be constrained e.g. device+token, and the algo accounts for that extra token of specificity when evaluating a stored permission.

@annevk
Copy link
Member

annevk commented May 8, 2024

The fundamental problem is that end users are not aware of nested documents (and shouldn't really have to be, although there are some notable exceptions). So trust has to flow through what is in the address bar. And as such that domain has to be responsible for delegation.

Any kind of scoping would complicate the end user experience quite a bit for rather minimal gain.

@rockinghelvetica
Copy link

rockinghelvetica commented May 8, 2024

It feels pretty factual to say that domains are not taking responsibility for the delegation.

I wrote to Replit, but since this is demonstrated at Figma, Huggingface, and hundreds of other services, it feels like something is wrong with the status quo. Risky microphone permissions in Figma alone might be a million active uniques, used daily by enterprises like banks (the one I’m familiar with has thousands of licenses).

Backing up to the ask of this Issue: what can sites do?

GitHub elects to aggressively limit UX (no major permissions delegated to embeds on their primary origin), and that’s one tactic. I suspect that search rank hurt by isolating content across domains precludes this for startups.

What else can a site do? When private/local LLMs take off this is going to scale up (arguably people limit their microphone/camera use to a few apps, but agents could blow up the surface area of this trust model)

@annevk
Copy link
Member

annevk commented May 8, 2024

If those websites end up sharing your camera and microphone with whomever that does sound problematic, but there's nothing we can really do about that if that is what they want to do be doing (if we didn't offer delegation they'd just do it through postMessage() or some such instead). End users of those websites might well be justified to complain about this in a variety of ways though.

@rockinghelvetica
Copy link

rockinghelvetica commented May 8, 2024

The topic of this conversation is not that the cited specs and their surrounding documentation are above critique. Neither is there a goal to prevent top-level domains from delegating permissions under any circumstance.

The question is how might a site best are any sites with third-party code ecosystems using allow= to avoid creating the risk described, if not the extremely conservative case of GitHub.com?

@jan-ivar
Copy link
Member Author

jan-ivar commented May 8, 2024

I opened this issue to ask for examples that show this use case addressed by allow=, so I think that's the topic.

I agree it's concerning that web-developer-marketed sites are taking these shortcuts, but suggesting we need to toss the design over it seems like an appeal to ignorance. In any case it seems possible to argue that in parallel in a separate issue.

It was pointed out these sites are likely leaking storage, cookies, and cache as well. I suspect they've been getting a pass from their roots as tools for a technical audience that historically hasn't demanded mainstream-level protections.

As an analogy, it took COVID and remote learning for WebRTC developers to realize open-meeting-urls were a bad idea.

@rockinghelvetica
Copy link

Well put, @jan-ivar. I edited my most recent reply to avoid expanding the discussion further.

I love the WebRTC analogy. I would step back from saying this risk applies just to a technical audience, today:

  • Enterprise users of SaaS tools that have third-party integrations
  • Wordpress blogs with plugins, hacks, or both
  • Shopify & ilk that have app stores for functionality like barcode reading, virtual try-ons, live chat, etc.
  • Likely any site with Gradio, where end users might be technical but not necessarily in the web platform sense

Shopify is an interesting case: their developer API locks down iframes for admin plugins, BUT the end stores can have arbitrary code. When the store is previewed in the CMS, is that iframe secured? IDK

@jan-ivar
Copy link
Member Author

jan-ivar commented May 10, 2024

How is this different from storage, cookies, or the cache leaking all over the playground?

Sorry, my first example showed poor isolation, a red herring. I think the issue is delegation not isolation.

The second example isolates storage, cookies, and cache, but (if the allow="camera" is indiscriminate) retains the problem of delegating camera permission to all user-generated content on the site after a single use (pseudo code):

// site.com/index.html
<iframe allow="camera" src=`//${user.id}.site.io/${user.fiddleId}` sandbox="allow-same-origin ...">

The answer is don't do this, but developers seem to confuse delegation with permission isolation.

I suggest adding two examples to clarify this and what to do instead:

  1. allow nothing by default and build bespoke UX that allows end-users to delegate
  2. use separate top-level (sub) domains instead like github.io does to lean on browser UX

AFAIK both Shopify and Wordpress use separate top-level subdomains for user-content.

@rockinghelvetica
Copy link

This is a great summary.

Yes, they are by-domain but it’s common for a Wordpress/Shopify site to have multiple vendors’ code plugged in by less-technical admins. They represent a wide-based territory of risk (many sites, many web users) where the “right” way to do this work needs to be promoted loudly imo.

No slight to an indie tool developer, but if the expensive staff at Replit bungled this, I’m not feeling confident about the status quo of knowledge on this topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants