`app_uid` was removed from the request-permission URL because the uid names who receives the grant, so it has to come from the requesting origin rather than from whoever built the link. Two other parameters still carried exactly that identity, and the origin is the identity twice over: it is the name the dialog attributes the request to, and it is what the server resolves into the app the grant is written against. `opener_origin` is believed on every popup boot, ahead of the referrer. `origin` was the fallback in the request-permission block itself, reached whenever there is no opener at all. Either one lets a bare link raise a consent prompt in some other app's name — the token exchange bootstraps an app row for whatever origin was typed, so the grant then commits against it — while the user is looking at a domain the requester does not control. That is the whole dialog defeated: a site can name `docs.google.com` and have the Allow land on Google's app row. So a permission popup now takes only an origin the browser vouches for: `document.referrer`, or the opener's own reply to the `requestOrigin` handshake. Neither can be forged to another origin. Nothing legitimate relied on the parameters — the SDK sends neither, and the OIDC redirect `opener_origin` exists for drops `action` too, so no permission flow can arrive through one. The `origin` fallback only ever fired when there was no opener, which is to say when there was no requester either; that path now reports its denial as usual instead of prompting. The referrer is safe here precisely because `action` is only `request-permission` on the popup's first load, so it is always the opener's. Restoring the action across an OIDC hop would break that — the returning navigation's referrer is the identity provider — which is why the round trip is withheld rather than repaired: A popup that signs in through OIDC comes back to a redirect URI the server hard-codes to `/action/sign-in`, so it returns believing it is a plain sign-in popup. It posts `puter.token`, which the SDK's global listener feeds straight into `setAuthToken()`, and never runs the action it was opened for. For a permission prompt that is the exact outcome `deliversTokenToOpener` exists to prevent: the site is signed in without ever asking, the user is never shown the permission they were brought there to decide, and the request resolves as a denial. Nothing in the returned URL says what the popup was for, so it cannot recover on its own. Until the redirect can carry the action back — and the opener origin can be re-established from the handshake on return — a popup whose purpose cannot survive the hop does not offer the hop. Email sign-in stays in the window and is unaffected. Pinned by e2e tests that spoof each parameter and expect the prompt to name the real opener, or not to appear at all. The long-hostname test drove the dialog through `origin=`, which no longer produces one, so it now asserts the CSS elision contract directly while the popup test asserts the real flow applies the `perm-dialog-entity-host` class that contract keys on.
The Open-Source Internet Computer!
« LIVE DEMO »
Puter.com
·
App Store
·
Developers
·
Discord
·
Reddit
·
X
Puter
Puter is an advanced, open-source, self-hostable internet computer designed to be feature-rich, fast, and highly extensible.
For Users
Puter's goal is to provide you with every app and feature you need to work, create, and play under one roof. From a simple Notepad and Voice Recorder to Spreadsheet and Camera, Puter wants to be the all-in-one solution for your digital life.
For Developers
Puter provides everything you need to build and publish web apps and games. From AI to Cloud Storage and Database to Serverless Workers, Puter has you covered. Puter also helps you get users! Once you build your app, you can publish it on our App Store to reach and monetize users.
Getting Started
💻 Local Development
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
→ This should launch Puter at http://puter.localhost:4100
🚀 Self-Hosting
Linux/macOS
curl -fsSL https://puter.com/selfhost | sh
Windows
irm https://puter.com/selfhost?os=windows | iex
→ For more details, see Self-Hosting Puter.
☁️ Puter.com
Puter is available as a hosted service at puter.com.
Support
Connect with the maintainers and community through these channels:
- Bug report or feature request? Please open an issue.
- Discord: discord.com/invite/PQcx7Teh8u
- X (Twitter): x.com/HeyPuter
- Reddit: reddit.com/r/puter/
- Mastodon: mastodon.social/@puter
- Security issues or abuse reports? security@puter.com
- Email maintainers at hi@puter.com
We are always happy to help you with any questions you may have. Don't hesitate to ask!
License
This repository, including all its contents, sub-projects, modules, and components, is licensed under AGPL-3.0 unless explicitly stated otherwise. Third-party libraries included in this repository may be subject to their own licenses.
Translations
- Arabic / العربية
- Armenian / Հայերեն
- Bengali / বাংলা
- Chinese / 中文
- Danish / Dansk
- English
- Farsi / فارسی
- Finnish / Suomi
- French / Français
- German / Deutsch
- Hebrew/ עברית
- Hindi / हिंदी
- Hungarian / Magyar
- Indonesian / Bahasa Indonesia
- Italian / Italiano
- Japanese / 日本語
- Korean / 한국어
- Malay / Bahasa Malaysia
- Malayalam / മലയാളം
- Polish / Polski
- Portuguese / Português
- Punjabi / ਪੰਜਾਬੀ
- Romanian / Română
- Russian / Русский
- Spanish / Español
- Swedish / Svenska
- Tamil / தமிழ்
- Telugu / తెలుగు
- Thai / ไทย
- Turkish / Türkçe
- Ukrainian / Українська
- Urdu / اردو
- Vietnamese / Tiếng Việt

