Web: serve the app from its own origin, not mostro.network/app/
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
Start with CLAUDE.md § Web and the deployment workflow in .github/workflows/web-build.yml; then review test/web/pages_bundle_test.dart and the smoke test's BASE_PATH. The issue also identifies the service-worker, Firebase, manifest, and documentation paths that need review. Done means serving from a confirmed dedicated origin, updating the listed path-dependent settings and references, and providing the old-origin recovery notice before redirecting users.
Written by the indexing model from the issue text.
Description
Problem
The web app is published to https://mostro.network/app/ (deploy-pages.yml). Browser storage is scoped to the origin, not to the path, so everything the app keeps in localStorage and IndexedDB can be read by any script running on any page of https://mostro.network.
Today that origin also serves other GitHub Pages sites of the org. Checked on 2026-10-05:
| Path | Repo |
|---|---|
/ |
MostroP2P.github.io |
/protocol/ |
protocol (mdBook, with its own scripts) |
/docs-english/, /docs-spanish/ |
docs-english, docs-spanish |
/blog/ |
blog |
/app/ |
app (this repo) |
The org's other sites (mostro.foundation, mostro.watch, mostro.community, mostro.world) have custom domains and are not affected. Any repo in the org that turns on Pages without a custom domain joins this origin automatically. So a compromised dependency or build of any of those sites, or a malicious PR merged into one of them, can read the app's secrets from every user who opened the app in that browser.
What the app keeps on that origin
- The mnemonic, through
flutter_secure_storage(IdentityService). On web,flutter_secure_storage_web1.2.1 stores the AES-GCM key exported raw inlocalStorage['FlutterSecureStorage'], next to the ciphertext. Any script on the origin can decrypt it with one WebCrypto call. - IndexedDB, written by the Rust core (
rust/src/db/indexeddb.rs):identity,trade_keys,trades,messages(chat history),attachment_blobs,bond_claimsand others. - After #650 and #651: the NWC URI, whose secret can spend from the user's wallet. In #651 it goes into the same storage as the mnemonic, with the same exposure.
Encrypting at rest inside the page cannot fix this. Whatever key the app uses has to be usable by same-origin script, so a non-extractable WebCrypto key in IndexedDB still decrypts for an attacker running on that origin. The boundary that holds is the origin itself.
Proposal
Serve the app from an origin of its own, for example https://app.mostro.network. With GitHub Pages that is a custom domain on this repo's Pages site (plus the DNS record); the other sites stay where they are.
Before choosing the domain, confirm that nothing else is or will be served on it.
What has to change with the path (/app/ → /)
Every one of these yields a blank or broken page when wrong (see CLAUDE.md § Web):
-
--base-hrefin.github/workflows/web-build.yml -
test/web/pages_bundle_test.dart(it pins the sub-path) - The smoke test's
BASE_PATHin CI -
web/coi-serviceworker.min.jsscope (cross-origin isolation) - The FCM worker (
web/firebase-messaging-sw.js), registered relative to the base path, and its Firebase config (authorized domains for the new origin) -
web/manifest.json: relativestart_urlandscopeshould follow by themselves; check installability (SMOKE_INSTALLABLE=1) - Links to
mostro.network/app/in docs, release notes (tool/release/downloads.dart), README and CLAUDE.md
Existing web users
The storage does not move with the app: on the new origin a returning user starts empty. Before redirecting, the old /app/ should:
- Show a notice explaining the move.
- Offer to show the recovery words, which are needed to restore on the new origin. Trade history can come back through restore; the NWC connection has to be pasted again.
- Only then redirect to the new origin.
Once the notice has been up long enough, /app/ can become a plain redirect.
Related
- #650: NWC on web (this exposure is the reason it asks for #651 first).
- #651: NWC URI in secure storage. It protects native, not web; see its review.
- Dominant language
- Dart
- Stars
- 11
- Forks
- 9
- Avg merge
- 12h 41m
- Merged PRs (30d)
- 265
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MostroP2P/app
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Add-invoice screen stays on "Sent, waiting for the node" after a late acceptance on a sell orderOpenbug priority: medium
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
area: ui
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
MostroP2P/app#341 · 1 comment ·
Maintainers usually reply within 1 day
Similar issues
-
bug product: very_good_flutter_plugin
Difficulty 1/5 1-3 hours Newbie friendliness 78/100
VeryGoodOpenSource/very_good_templates#654 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
Maintainers usually reply within 1 day
-
Server never consumes the request body on early-error paths: _sinkIncoming does not resume the paused subscriptionMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
[BUG][All] VLESS URIs with flow=xtls-rprx-vision-udp443 are silently dropped on subscription importOpen
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
simonoppowa/OpenNutriTracker#1336 ·
Maintainers usually reply within 1 day