Skip to content

TronBrowser's own Web Push service (a setting, defaulting to tronbrowser.dev) - #120

Merged
ralyodio merged 2 commits into
mainfrom
feat/own-push-service
Sep 24, 2026
Merged

ralyodio merged 2 commits into
mainfrom
feat/own-push-service

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Why

ungoogled-chromium ships without a push service, and a page can't pick one, so in TronBrowser pushManager.subscribe() fails on every site with Registration failed - push service error (reported on agenticjobs.work, reproduced in the bundled 152 engine).

What

  • Service (services/api/src/push, mounted at /api/1/push): standard RFC 8030 receive endpoint. Site servers send the same aes128gcm + VAPID requests they send to FCM/Mozilla (the VAPID key must match the one the site subscribed with). Ciphertext is queued until the browser acks, and delivered live over a WebSocket (@hono/node-ws). It answers 404/410 for gone subscriptions, plus 400/413/415/429.
  • Extension: push-page.js (MAIN world, document_start) replaces PushManager.subscribe/getSubscription/permissionState, and push-bridge.js relays page ↔ background. push-client.js holds the subscription keys, registers, decrypts (RFC 8291, WebCrypto only) and shows it with chrome.notifications; a click opens url. Adds the alarms permission (1-minute catch-up poll) and contentSettings (a site you later block stays silent).
  • Setting (Settings → Push notifications): TronBrowser (default), any compatible https URL (checked against GET / before switching), or off, which gives the engine's own behaviour.
  • Migration 0007_push.sql, a /push docs page, and a privacy entry.

Limit: an extension can't fire a site's service-worker push event, so TronBrowser renders the payload (title/body/icon/url, notification.*). Silent data-only pushes show as plain notifications.

Verified

  • services/api push tests: 13/13 pass. They use a real @profullstack/notifications sender and the extension's own decryptor, covering key mismatch → 403, TTL/encoding/size, Topic replace, 404/410.
  • Desktop: 138/138 pass. API typecheck is clean.
  • End to end in the real engine (ungoogled-chromium 152.0.7977.82, headless, via puppeteer):
    • Without the extension: AbortError: Registration failed - push service error.
    • With it: subscribe returns a real-looking PushSubscription (instanceof holds, getSubscription returns the same one, state granted). sendPush gets 201, the notification is created with its click URL, and the message is acked over the socket within 3s.
  • src/mcp/tron.test.ts can't load locally in a fresh worktree because @tronbrowser/browser-core is unbuilt. That's unrelated to push.

🤖 Generated with Claude Code

ungoogled-chromium ships without a push service and a page cannot choose
one, so pushManager.subscribe() failed on every site with 'Registration
failed - push service error' (reproduced in the bundled 152 engine).

- services/api: an RFC 8030 push service at /api/1/push. Site servers send
  standard aes128gcm + VAPID pushes (the sender's key must match the one the
  site subscribed with); ciphertext is queued until the browser acks it and
  delivered live over a WebSocket. 404/410/413/415/429 as senders expect.
- extension: push-page.js (MAIN world) replaces PushManager.subscribe /
  getSubscription / permissionState; push-client.js holds the subscription
  keys, registers, decrypts (RFC 8291, WebCrypto) and shows the notification.
- setting: Settings -> Push notifications. Default tronbrowser.dev, any
  compatible https URL (checked against GET / first), or off (engine's own).
- /push docs page, privacy entry, migration 0007.

Verified end to end in the real engine: subscribe returns a PushSubscription,
a real sendPush gets 201, the notification is created with its click URL and
the message is acked over the socket within 3s.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@socket-security

socket-security Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​profullstack/​notifications@​0.1.3751009488100
Added@​hono/​node-ws@​1.3.11001009681100

View full report

@github-actions

Copy link
Copy Markdown
Contributor

ThreatCrush Security Scan

52 finding(s)

HIGH/CRITICAL: 3 | MEDIUM: 28 | LOW: 21

Severity Rule Location
HIGH py-ssrf-outbound-request apps/desktop/launcher/tron-tor-helper:303
HIGH py-ssrf-outbound-request apps/desktop/launcher/tron-tor-helper:437
HIGH sh-remote-script-execution apps/web/public/install.sh:757
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:306
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/sidepanel.js:78
MEDIUM js-unescaped-html-sink apps/desktop/extensions/ai-sidebar/sidepanel.js:166
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:164
MEDIUM sh-remote-script-execution apps/web/public/install.sh:169
MEDIUM sh-remote-script-execution apps/web/public/install.sh:282
MEDIUM sh-remote-script-execution apps/web/public/install.sh:300
MEDIUM sh-remote-script-execution apps/web/public/install.sh:813
MEDIUM sh-remote-script-execution apps/web/public/install.sh:864
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:125
MEDIUM js-dynamic-code-execution packages/sdk/src/page.ts:68
MEDIUM js-dynamic-code-execution packages/sdk/src/page.ts:73
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 apps/desktop/extensions/ai-sidebar/pit-proxy.test.js:8
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:16
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:45
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:57
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:80
LOW js-unescaped-html-sink packages/browser-core/src/automation/extract-script.test.ts:99
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:62
LOW js-unescaped-html-sink packages/browser-core/src/automation/snapshot-script.test.ts:101
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 js-dynamic-code-execution packages/sdk/src/mcp/automate.test.ts:261
LOW secret-generic-api-key packages/storage/src/config.ts:51
LOW secret-generic-credential packages/storage/src/config.ts:51

…and 2 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 7ef12b4 into main Sep 24, 2026
14 checks passed
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