Files
safetynet/docs/immutable-upload-feasibility.md
T

6.4 KiB

Immutable native upload binding: Electron 44.7 feasibility

The protocol-forwarding proof below is not a production upload implementation and its credential widening remains a blocker. A separate native-handle path is now implemented for ordinary Windows NTFS files; see Windows file upload enforcement. Unsupported data-pipe, range and streaming paths remain blocked. The earlier candidate/prototype sections below describe the experiments that preceded that implementation.

Run node scripts/immutable-upload-probe.cjs. It launches a finite, hidden, CPU-rendered, sandboxed Electron fixture against a loopback HTTP receiver. No managed browser configuration, actual credentials, OS clipboard, or website code is changed. The fixture uses a real HTML file input populated through test-only native CDP, then submits Chromium-generated multipart FormData.

Evidence

artifacts/immutable-upload-probe.json records:

  • requestBodyAvailable: true: session.protocol.handle('http') exposes the real multipart file stream through Request.arrayBuffer().
  • mutatedAfterSnapshot: true: the disk fixture is replaced after body capture and before forwarding.
  • exactBytes: true: receiver SHA-256 equals inspected snapshot SHA-256; receiver contains the original bytes and excludes the replacement bytes.
  • credentialsPreserved: false: both renderer credentials: 'include' and credentials: 'omit' become protocol requests reporting credentials: 'same-origin', with no Cookie header. Forwarding through the same session attaches its synthetic session cookie to both. The original credential choice cannot be inferred from these fields.
  • redirectDenied: true: forwarding with redirect: 'error' denies a 307 and never reaches the redirect destination. Transparent redirect compatibility is therefore not established.

The cookie behavior is a security blocker for a transparent HTTP(S) protocol bridge. The proof deliberately asserts this limitation rather than presenting a passing byte comparison as sufficient approval to ship.

Compatibility and security boundaries

Electron documents that protocol requests include a trusted initiatorOrigin. This establishes the requesting origin; it does not recover the original Fetch credential mode, top-level site cookie context, authenticated request semantics, redirect chain, or full request policy context.

CORS preservation has not been demonstrated. Browser preflight handling, credential-dependent Access-Control-Allow-Origin rules, opaque responses, response URL/type, frame/site cookie partitioning, authentication challenges, and service-worker paths require separate receiver-based tests and implementation support. They must not be inferred from same-origin multipart success. Electron explicitly documents incorrect response .type and .url for session.fetch, and says bypassing custom protocols still invokes webRequest handlers. Consequently an integration also needs safe request identity and recursion handling; a broad trusted forwarding bypass would weaken existing enforcement.

The anonymous-only fallback was not implemented. A deployable solution must preserve original Chromium request semantics and bind the scanner decision to immutable bytes, destination, policy version, identity, and request context. Native Chromium interception or a verified native network integration remains required before file/data-pipe upload support can be enabled.

Primary references

This test concerns one in-memory multipart upload. It does not prove full DLP coverage for streaming, WebSockets, WebRTC, browser uploads, or downloads.

Windows file-handle alternative: actual native proof, 2026-10-13

A separate sandboxed Electron 44.7.0 fixture now demonstrates a viable path for ordinary file-backed multipart uploads without forwarding or rewriting requests. It holds restrictive Win32 handles for all eight normal ancestor directories and the leaf file, reads the candidate scan bytes through that same held file handle, then lets the original Chromium request continue. The real receiver saw original file bytes; attempted overwrite, hardlink overwrite, leaf rename and parent rename were refused. Chromium's reader could coexist with the handles. Fetch credentials: omit remained anonymous and include retained its cookie. Both handle sets were released only after their corresponding native onCompleted events. Proof: artifacts/upload-lock-native-proof.json; reproducible ignored fixture: artifacts/upload-lock-native.cjs and upload-lock-helper.py.

Separate Windows experiments verified that a pre-existing writable mapping causes restrictive lock acquisition to fail. A lock failure must block; the mapping can still mutate the underlying file. These observations use synthetic files on this Windows machine and are not a general filesystem or privileged-attacker guarantee.

This is not enabled in the product. The fixture knows its synthetic paths and does not implement production reparse rejection or identity verification. The next gate must restrict eligibility to supported local fixed-volume files, retain the complete normal ancestor chain, verify final path/volume/file identity, and bound whole-file reads through the held handle. Whole-file inspection avoids trusting the exposed offset/length conversion for large ranges. It must inspect both each actual file and the other multipart segments, preserve request order, and keep handles until the matching native terminal event. Helper death, policy changes, cancellation, redirects, retries and uncertain lifecycle state require explicit safe handling before release of either handles or requests. Data pipes, streaming and other operating systems remain separate requirements.

The existing public-API forwarding bridge remains unsuitable because of its credential widening. This proof advances ordinary Windows file binding through native operating-system handles while preserving the original network request. See Microsoft CreateFileW for the underlying access and sharing contract.