Skip to content

Publish our extensions to our own store, from CI - #125

Merged
ralyodio merged 1 commit into
mainfrom
feat/store-publish-automation
Sep 24, 2026
Merged

ralyodio merged 1 commit into
mainfrom
feat/store-publish-automation

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Publish our extensions to our own store, from CI

We built a store with one-click install and Chromium auto-update -- crx.ts
stamps our update_url into the manifest before signing, precisely so Chromium
polls /api/store/updates.xml rather than Google. Then every listing was created
by hand, which in practice meant almost none were: the store holds exactly one
extension, and our own MarkSyncr is not in it.

That is the gap worth closing. An extension in the store auto-updates for anyone
who installed it. An extension outside the store reaches TronBrowser only by
being rebuilt into the bundle, and reaches everyone else only when Google
approves it. MarkSyncr has three releases sitting in Chrome review right now.

So publishing runs from CI. scripts/store-publish.mjs resolves the listing by
slug, creates it on first run, and posts the version with the manifest and the
artifact URL. The reusable workflow wraps it so an extension repo adds six lines
rather than its own half of the job.

Two behaviours worth stating. A version that is already published exits clean
instead of failing, so re-running a tag is safe. And the artifact is polled
before submitting, because the store fetches it itself and a release asset can
lag its tag by a few seconds -- submitting into that window fails for a reason
that has nothing to do with the extension.

Verified against the live store: an existing listing resolves by slug
(coinpay-wallet), an unknown name takes the create path, and a manifest that is
not MV3 is refused before anything is sent.

Nothing publishes until TRONBROWSER_STORE_TOKEN exists. The API deliberately
refuses to mint a publisher token from a token -- it has to come from a signed-in
browser session -- so that one step is Anthony's and cannot be automated away.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

We built a store with one-click install and Chromium auto-update -- crx.ts
stamps our update_url into the manifest before signing, precisely so Chromium
polls /api/store/updates.xml rather than Google. Then every listing was created
by hand, which in practice meant almost none were: the store holds exactly one
extension, and our own MarkSyncr is not in it.

That is the gap worth closing. An extension in the store auto-updates for anyone
who installed it. An extension outside the store reaches TronBrowser only by
being rebuilt into the bundle, and reaches everyone else only when Google
approves it. MarkSyncr has three releases sitting in Chrome review right now.

So publishing runs from CI. scripts/store-publish.mjs resolves the listing by
slug, creates it on first run, and posts the version with the manifest and the
artifact URL. The reusable workflow wraps it so an extension repo adds six lines
rather than its own half of the job.

Two behaviours worth stating. A version that is already published exits clean
instead of failing, so re-running a tag is safe. And the artifact is polled
before submitting, because the store fetches it itself and a release asset can
lag its tag by a few seconds -- submitting into that window fails for a reason
that has nothing to do with the extension.

Verified against the live store: an existing listing resolves by slug
(coinpay-wallet), an unknown name takes the create path, and a manifest that is
not MV3 is refused before anything is sent.

Nothing publishes until TRONBROWSER_STORE_TOKEN exists. The API deliberately
refuses to mint a publisher token from a token -- it has to come from a signed-in
browser session -- so that one step is Anthony's and cannot be automated away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@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.

@ralyodio
ralyodio merged commit 2eb0eea into main Sep 24, 2026
7 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