Skip to content

fix(launcher): find Flatpak web-app shortcuts, and give them the right profile - #88

Merged
ralyodio merged 1 commit into
mainfrom
fix-pwa-flextop-shortcuts
Aug 30, 2026
Merged

fix(launcher): find Flatpak web-app shortcuts, and give them the right profile#88
ralyodio merged 1 commit into
mainfrom
fix-pwa-flextop-shortcuts

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Follow-up to #87, which missed every shortcut it was meant to fix on a Flatpak
engine — the common Linux install. Found by looking at a machine where it had
changed nothing.

What was actually wrong

1. Shortcuts were matched by the filename prefix chrome-. That is what
Chromium names its own, but a Flatpak exports web apps to the host through
flextop:

io.github.ungoogled_software.ungoogled_chromium.flextop.chrome-<app-id>-Default.desktop

Eleven shortcuts on the reporting machine were invisible to the scan. What makes
a file a web-app shortcut is --app-id on its Exec line, so ask that.

2. Ownership was decided by --user-data-dir. A flextop export carries none,
so every Flatpak web app read as another browser's and was skipped. The profile
records what it has installed, under Web Applications/Manifest Resources/<app-id>,
and that does not depend on what the engine wrote. Either rule now establishes
ownership; matching neither still means hands off.

3. That missing --user-data-dir is the bug the user sees. Without it the
shortcut opens the Flatpak's own default profile, where the app is not
installed — so the browser starts, finds nothing, and exits a few seconds later.
It reads as a crash, but it is the right browser opening the wrong profile. Sync
now fills in the profile the app is actually installed in.

Two things that fell out of fixing it

Switches are now carried over by allowlist rather than "everything after the
program", because the program is not always the engine. A flextop Exec is
flatpak run --branch=… --command=… <app-id>, and forwarding those tokens would
hand the tron CLI a bare run — one of its own subcommands.

Since that deliberately drops tokens, revert could no longer rebuild the line:
it restored /usr/bin/flatpak with no run --command=…, leaving a shortcut that
launched nothing. Each original Exec is now recorded verbatim and restored as-is.
Shortcuts patched by 3.9.9 still revert through the old reconstruction path.

Tests

6 new cases reproducing the real machine — flextop filename, flatpak run Exec,
no --user-data-dir, app present in the profile, plus a stray snap Chromium
shortcut that must stay byte-identical. 20 in the file, 109 in the desktop suite.
Typecheck and lint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SZXtxiVkXd7rFmvrMYV7Ut

…t profile

The first pass at this missed every shortcut it was meant to fix on a Flatpak
engine, which is the common Linux install. Three bugs, found by looking at a
machine where it had changed nothing:

Shortcuts were matched by filename prefix `chrome-`. That is what Chromium names
its own, but a Flatpak exports web apps to the host through flextop, as
`<flatpak-app-id>.flextop.chrome-<app-id>-<profile>.desktop`. Eleven shortcuts on
the reporting machine were invisible to the scan. What makes a file a web-app
shortcut is `--app-id` on its Exec line, so ask that instead of the name.

Ownership was decided by `--user-data-dir` matching a TronBrowser profile. A
flextop export carries no `--user-data-dir` at all, so every Flatpak web app read
as "somebody else's" and was skipped. The profile itself records what it has
installed, under `Web Applications/Manifest Resources/<app-id>`, and that answer
does not depend on what the engine chose to write. Either rule now establishes
ownership; matching neither still means hands off.

That missing `--user-data-dir` is also the failure the user sees. Without it the
shortcut opens the Flatpak's OWN default profile, where the app is not installed
-- so the browser starts, finds nothing and exits a few seconds later. It reads
as a crash but it is the right browser opening the wrong profile. Sync now fills
in the profile the app is actually installed in.

Switches are carried over by allowlist rather than "everything after the
program", because the program is not always the engine: a flextop Exec is
`flatpak run --branch=… --command=… <app-id>`, and forwarding those tokens would
hand the `tron` CLI a bare `run`, which is one of its own subcommands.

Since that deliberately drops tokens, revert can no longer rebuild the line --
it restored `/usr/bin/flatpak` with no `run --command=…` and left a shortcut
that launched nothing. Each original Exec is now recorded verbatim and restored
as-is; shortcuts patched by 3.9.9 still revert via the old reconstruction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SZXtxiVkXd7rFmvrMYV7Ut
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

49 finding(s)

MEDIUM: 31 | LOW: 18

Severity Rule Location
MEDIUM js-open-redirect apps/desktop/extensions/ai-sidebar/install-helper.js:156
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/media.js:34
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/media.js:57
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/newtab.js:237
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/newtab.js:266
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/newtab.js:336
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/options.js:305
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/sidepanel.js:77
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/sidepanel.js:165
MEDIUM sh-remote-script-execution apps/desktop/launcher/tronbrowser:84
MEDIUM sh-remote-script-execution apps/desktop/launcher/tronbrowser:394
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:77
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:227
MEDIUM js-unescaped-html-sink apps/extensions/public/store.js:569
MEDIUM js-unescaped-html-sink apps/web/public/app.js:29
MEDIUM js-unescaped-html-sink apps/web/public/dns.js:54
MEDIUM sh-remote-script-execution apps/web/public/install.sh:138
MEDIUM sh-remote-script-execution apps/web/public/install.sh:143
MEDIUM sh-remote-script-execution apps/web/public/install.sh:242
MEDIUM sh-remote-script-execution apps/web/public/install.sh:260
MEDIUM sh-remote-script-execution apps/web/public/install.sh:820
MEDIUM js-unescaped-html-sink apps/web/public/settings.js:96
MEDIUM js-unescaped-html-sink apps/web/public/settings.js:168
MEDIUM js-dynamic-code-execution packages/sdk/src/mcp/tools.ts:80
MEDIUM js-dynamic-code-execution packages/sdk/src/mcp/tools.ts:92
MEDIUM js-dynamic-code-execution packages/sdk/src/mcp/tools.ts:103
MEDIUM js-dynamic-code-execution packages/sdk/src/page.ts:65
MEDIUM js-dynamic-code-execution packages/sdk/src/page.ts:70
MEDIUM sql-template-interpolation services/api/src/store/db.ts:116
MEDIUM js-dynamic-code-execution services/api/src/store/scanner.ts:44
MEDIUM sh-predictable-temp-path start.sh:25
LOW js-dynamic-code-execution packages/agent-runtime/src/analyze/form-script.test.ts:6
LOW js-unescaped-html-sink packages/agent-runtime/src/analyze/form-script.test.ts:26
LOW js-unescaped-html-sink packages/agent-runtime/src/analyze/form-script.test.ts:49
LOW js-dynamic-code-execution packages/browser-core/src/automation/extract-script.test.ts:6
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:35
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:47
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:70
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:89
LOW js-dynamic-code-execution packages/browser-core/src/automation/snapshot-script.test.ts:11
LOW js-unescaped-html-sink packages/browser-core/src/automation/snapshot-script.test.ts:24
LOW js-unescaped-html-sink packages/browser-core/src/automation/snapshot-script.test.ts:63
LOW js-unescaped-html-sink packages/provenance/src/scan.test.ts:47
LOW js-unescaped-html-sink packages/provenance/src/scan.test.ts:170
LOW js-unescaped-html-sink packages/provenance/src/scan.test.ts:216
LOW secret-generic-api-key packages/storage/src/config.ts:51
LOW secret-generic-credential packages/storage/src/config.ts:51
LOW js-dynamic-code-execution services/api/src/store/scanner.test.ts:32
LOW js-hardcoded-crypto-key services/api/src/store/signing.test.ts:24

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit 01a8966 into main Aug 30, 2026
8 checks passed
@ralyodio
ralyodio deleted the fix-pwa-flextop-shortcuts branch August 30, 2026 15:36
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 this pull request may close these issues.

1 participant