security: relayUrl validation, remove dead pending code, fix about:blank#3
Open
DeetBot wants to merge 30 commits into
Open
security: relayUrl validation, remove dead pending code, fix about:blank#3DeetBot wants to merge 30 commits into
DeetBot wants to merge 30 commits into
Conversation
- New readme reflecting Artífice branding and architecture - Credits upstream (OpenClaw + Unayung resilient fork) - Documents hybrid architecture (extension + Tauri app) - Security model and install instructions
- manifest.json: name, description, tooltip rebranded - icons: resized from Artífice dark brand asset (16/32/48/128px)
- Manifest validation (MV3, required fields) - Required files check - Icon sizes check - JS syntax check (node --check) - Secret scanning
- Title, heading, subtitle rebranded - Accent color: OpenClaw orange → Artífice gold (#c8962e) - Getting started text updated (references Artífice app, not OpenClaw) - Gateway token → Client token - Hints reference Artífice Connect app pairing
rebrand: options page for Artífice Connect
…nd options.js - background.js: All console.log/warn prefixes [OpenClaw Relay] → [Artífice Relay] - background.js: All chrome.action.setTitle strings OpenClaw Browser Relay → Artífice Connect - options.js: HTTP header x-openclaw-relay-token → x-artifice-relay-token - options.js: User-facing error message rebranded - No functional logic, auth, or WebSocket behavior changed
rebrand: replace OpenClaw references with Artífice in background.js and options.js
- Replace localhost:port with configurable relay URL (default wss://relay.artificeia.mx) - Token passed as query param (browser WebSocket can't set headers) - Options page updated with URL field instead of port - host_permissions updated for any relay domain
feat: configurable public WSS relay URL
- Bump version to 1.0.0 - Narrow host_permissions to relay.artificeia.mx - Add privacy policy - Update README - Add homepage_url
chore: Chrome Web Store submission prep
fix: update options page copy
chore: final cleanup for CWS submission
Google rejected with 'Purple Potassium' — tabs permission unnecessary since activeTab covers all implemented functionality. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove tabs permission (Chrome Web Store rejection)
Token no longer passed as ?token= query param — no more exposure
in server logs, Caddy access logs, or browser history. On open,
extension sends { method: 'auth', token } as first message and
waits for { method: 'auth', ok: true } before resolving.
Timeout bumped to 10s to cover auth round-trip.
Co-authored-by: Fernando Baz <bazfer@gmail.com>
Relay now requires version: 1 in the auth handshake. Without it the relay rejects the connection with a protocol version mismatch error.
Send protocol version in auth message
…ed sendToRelay throws - Target.createTarget now rejects non-http/https URLs (blocks file://, data:, blob: etc.) - sendToRelay in error reply path (onRelayMessage) wrapped in try/catch - sendToRelay in attachTab tab-announce path wrapped in try/catch
Security: URL scheme allowlist for Target.createTarget; catch unhandled sendToRelay throws
Relay-side timeout is 30s — if relay never replies, extension pending entry leaked forever. 35s timer ensures cleanup slightly after relay gives up, preventing unbounded map growth on long sessions.
Clear pending map entries after 35s timeout
- getRelayUrl(): validate wss:// scheme — invalid storage value falls back to DEFAULT_RELAY_URL with console.warn; prevents token exfil to attacker relay if chrome.storage is compromised - options.js save(): reject non-wss:// URLs before writing to storage - Remove requestFromRelay, pending map, and all usage sites — never called; dead code introduced by PR #11 adding a timeout to an uncalled function - Target.createTarget: add about: to allowed URL schemes alongside http/https fixes regression from PR #10 where about:blank (DevTools default) was blocked
- H1 restoreState: verify targetId after re-attach — drop session if tab navigated away between worker death and restart (Chrome reuses tab IDs) - H2/M1 handleForwardCdpCommand: unknown sessionId throws instead of falling through; sessionId-less fallback only resolves when exactly one tab is attached - M2 attachTab: fix attachOrder off-by-one (was nextSession post-increment, now pre-capture) - M3 checkRelayReachable: remove misleading 401='token rejected' message — probe sends no token so status code tells us nothing about token validity - M4 ensureRelayConnection: null out stale socket handlers and close before opening new WebSocket; fix timeout handler to close socket before rejecting
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.
Summary
getRelayUrl()now validates that the stored URL haswss://scheme before connecting. An invalid value falls back toDEFAULT_RELAY_URLwith aconsole.warn. Without this, a compromisedchrome.storagecould redirect the extension to an attacker relay and exfil the auth token.save()validateswss://scheme before writing to storage. Shows an error in the UI instead of silently persisting a bad URL.requestFromRelay, thependingmap, and all usage sites. The function was introduced early as infrastructure but never called. PR #11 added a timeout to it — still uncalled. Two usage sites (onRelayClosedpending drain,onRelayMessagepending dispatch) were also unreachable.Target.createTargetnow allowsabout:alongsidehttp:andhttps:. PR #10 added the scheme allowlist but omittedabout:, breaking theabout:blankdefault that Chrome DevTools uses when opening new tabs. Also restoresabout:blankas the fallback URL whenparams.urlis absent (PR #10 had changed it to empty string, which threwInvalid URL).Test plan
http://URL in extension options → save rejected with error messagewss://127.0.0.1:18792→ saves and connects normallyTarget.createTargetwith no URL → createsabout:blanktab and attachesTarget.createTargetwithjavascript:alert(1)→ throws "URL scheme not allowed"requestFromRelayorpendingreferences remain