fix(extension): make the packaged build valid for the Chrome Web Store - #21
Merged
Conversation
The manifests themselves were structurally fine, but the package the build produced was not, and several declared entries were dead or dev-only. Build: - vite.config.js read the bare `BROWSER` env var to pick its outDir. `BROWSER` is a standard Linux env var (xdg-open et al) and is set on developer machines, so Vite wrote to dist/true (or dist/firefox) while build.js copied the manifest into dist/chrome. The resulting zip shipped only the manifest, icons and rulesets - popup, options page, service worker, blocked.html and the favicon icons were all absent, which the Web Store rejects as a manifest referencing files not in the package. Renamed the switch to EXT_BROWSER, validated against the known targets, and passed it explicitly from build.js. - Dropped the stray root-level background.js: an unbundled copy of the source with bare import specifiers that nothing referenced. - Release builds now strip http://localhost host permissions (EXT_DEV=1 keeps them for local work) instead of shipping them to reviewers. Manifests (chrome, firefox, safari): - Removed the `oauth2` block. Its client_id was still the literal YOUR_GOOGLE_CLIENT_ID placeholder, and it was never read: Google auth goes through identity.launchWebAuthFlow, not identity.getAuthToken. - Removed `optional_permissions: ["tabs"]` - nothing in the codebase calls permissions.request, so it could never be granted. - Removed the `icons/*` web_accessible_resources entry matched to <all_urls>. Extension pages and notification iconUrls do not need WAR; exposing it only made the extension fingerprintable from any page. - Declared `notifications`, which background/index.js already calls when sync hits its retry limit. The call was throwing into its own catch, so the notification was never shown. `key` is kept: it derives to hjcjjcpialiakkalcgadnfnoomdaegjg, the live store item, and the OAuth redirect URIs depend on that ID staying stable. Verified: 786 tests pass, lint clean, and all three packaged manifests resolve every file they reference with BROWSER still polluted in the environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012BqLAA6Qqj6bPVkd5nYMVi
ThreatCrush Security Scan12 finding(s) MEDIUM: 8 | LOW: 4
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The manifests themselves were structurally fine, but the package the build produced was not, and several declared entries were dead or dev-only.
The blocker
vite.config.jsread the bareBROWSERenv var to pick itsoutDir.BROWSERis a standard Linux env var (xdg-open et al) and is set on developer machines — on this box it'strue. So Vite wrote todist/truewhilebuild.jscopied the manifest intodist/chrome, andmarksyncr-chrome.zipshipped with only the manifest, icons and rulesets:A manifest referencing files not present in the package is rejected at upload. Renamed the switch to
EXT_BROWSER, validated it against the known targets, and pass it explicitly frombuild.js.Other fixes
Build
background.js— an unbundled copy of the source with bare import specifiers that nothing referenced.http://localhosthost permissions (EXT_DEV=1keeps them for local work) rather than shipping a dev-only permission to reviewers.Manifests (chrome, firefox, safari)
oauth2block. Itsclient_idwas still the literalYOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.complaceholder, and it was never read — Google auth goes throughidentity.launchWebAuthFlow, notidentity.getAuthToken.optional_permissions: ["tabs"]— nothing callspermissions.request, so it could never be granted.icons/*web_accessible_resourcesentry matched to<all_urls>. Extension pages and notificationiconUrls don't need WAR; exposing it only made the extension fingerprintable from any page.notifications, whichbackground/index.js:3685already calls when sync hits its retry limit. The call was throwing into its own catch, so the notification was never shown.Left alone deliberately
keyis kept — it derives tohjcjjcpialiakkalcgadnfnoomdaegjg, the live store item, and thechromiumapp.orgOAuth redirect URIs depend on that ID staying stable.Verification
BROWSER=truestill polluting the environment.Not addressed — needs a product call
Single-purpose policy. The item bundles bookmark sync + an ad/tracker blocker + a security shield. That is the likeliest remaining review rejection, and it's a listing/positioning decision rather than a manifest fix.
🤖 Generated with Claude Code
https://claude.ai/code/session_012BqLAA6Qqj6bPVkd5nYMVi