Browser Permission Model — Powerful, Policy-Controlled, and Widely Misconfigured
Browser permissions have two properties. “Powerful” means the browser prompts the user to grant access — camera and microphone are the main examples. “Policy-controlled” means the permission flows from the top-level document into iframes, governed by the Permissions-Policy HTTP response header (renamed from Feature Policy in 2021). That header is the only lever developers have.
Most don’t use it. A crawl of the top 1 million sites found that
“only around 10% really declare the permissions policy header” — Alberto Fernandez-de-Retana
Of those, many break parsing with a stray trailing comma, which silently disables the header entirely.
Three Misconceptions That Make Permission Hijacking Possible
Three assumptions make permission hijacking work. First, once food.bar delegates camera access to iframe.org, iframe.org can re-delegate it to any third party, regardless of food.bar’s original Permissions-Policy header. Delegation dissolves same-origin constraints downstream. Second, when a delegated widget requests camera access, the browser prompt names only the top-level document (food.bar), not the embedded widget doing the asking. Users approve a trusted domain and never see who actually gets the permission. Third, there is no notification after the grant. Any widget added later, inside a delegated iframe, inherits that permission silently.
Threat Model 1 — Hijacking Camera Access Through Embedded Chat Widgets
Chat widgets embedded in banking sites, news sites, and weather portals often receive delegated camera, microphone, and screen-share permissions from the host. Compromise that widget and you can insert a second-level iframe, re-delegating those same permissions to any origin you control. The browser prompt names only the top-level domain, so the user who granted camera access to their bank never sees the widget or the attacker’s iframe at all.
Case Studies — Vulnerabilities in Glassix and LiveChat
Glassix (100–2,000 sites) accepted a type parameter on chat attachment messages. Setting it to 8 injects an iframe at both ends, as shown in the Glassix type=8 iframe injection demo (14:39). Its CSP blocked the direct path; the local-scheme CSP bypass via reCAPTCHA endpoint (16:34) loaded a script from an allowed reCAPTCHA path and ran JavaScript on the worker side. LiveChat (38,000–500,000 sites) used markdown-to-JSX in its marketplace comment section. A form-action JavaScript URI there produced the LiveChat form-action one-click XSS in marketplace (24:20): an invisible full-screen button executes on any admin click, using a token with full admin rights.
“as attacker we only care about one working” — Alberto Fernandez-de-Retana
Threat Model 2 — Local-Scheme Bypass of Permissions-Policy on Sites Without Proper Headers
Setting Permissions-Policy: camera=self looks like a fix. It restricts camera access to the top-level document. But a local-scheme iframe has no HTTP response, so it inherits no policy from its parent. An attacker with HTML injection can insert a local-scheme middle iframe and re-delegate the permission to attacker.com. Fernandez-de-Retana reported this to Chromium last year. It remains unpatched. He demonstrated Local-scheme Permissions-Policy bypass (unpatched Chromium) (29:56).
“this vulnerability still works in all chromium based browser” — Alberto Fernandez-de-Retana
Q&A
Did you test any other chat widgets beyond Glassix and LiveChat? He tested only Glassix and LiveChat, acknowledging there are too many widgets to test all of them, and suggested the audience could find similar vulnerabilities in the rest. ▶ 33:05
How should developers approach CSP correctly — is there anything better than CSP? He had no definitive answer, saying correct CSP is hard even for small companies and what fits depends on the specific company or site. ▶ 34:18
How widespread are these CSP bypasses using allowed third-party endpoints like reCAPTCHA? He called these bypasses very common, attributing them to developers prioritizing working code over security, and noted XSS has been an unsolved problem since 2008-2010 without citing specific statistics. ▶ 36:08
How large is the potential damage from the LiveChat vulnerability? No specific figure, but he argued damage scales with user trust: people who rely on banking sites grant camera permissions without question, making the attack surface as large as the user base. ▶ 38:59
Notable Quotes
only around 10% really declare the permissions policy header Alberto Fernandez-de-Retana · ▶ 11:10
as attacker we only care about one working Alberto Fernandez-de-Retana · ▶ 26:33
if the bank ask for for your camera, you will be you you will allow the camera Alberto Fernandez-de-Retana · ▶ 39:38
this vulnerability still works in all chromium based browser Alberto Fernandez-de-Retana · ▶ 30:35
Key Takeaways
- Audit every chat widget your site embeds — delegated camera/microphone permissions travel through iframes you do not control.
- Set Permissions-Policy headers explicitly on every page that uses powerful permissions, then verify parsing is not broken by stray commas.
- Local-scheme iframes bypass Permissions-Policy in all Chromium browsers — treat any HTML injection on a site with granted permissions as a permission-hijacking primitive.
About the Speaker
Alberto Fernandez-de-Retana
Alberto Fernandez de Retana, known as bubu in CTFs, focuses his research on web security and privacy, as well as browser internals.