Files
safetynet/docs/windows-file-uploads.md

71 lines
4.0 KiB
Markdown

# Windows file upload enforcement
Ordinary file-backed uploads now use the original Chromium request with protected
Windows handles. The browser scans the complete actual files and the ordered
multipart byte segments before releasing the request. File magic, central DLP,
enabled local semantic/YARA checks and configured upload ICAP inspection apply.
This preserves Chromium's credential, cookie and CORS handling; requests are not
forwarded through a second fetch operation.
Eligible paths are canonical absolute local NTFS paths, at most 240 characters,
without alternate streams, device paths or reparse points. The gate supports full
file descriptors with offset zero and length minus one. It bounds the complete
request by the signed DLP byte limit, supports at most 16 file descriptors per
lease and eight outstanding leased requests. Partial file ranges, UNC paths,
data pipes, blobs without file descriptors, streams and changed-destination
upload redirects remain blocked pending their own safe integrations.
The private helper opens each normal ancestor and the file with read-only sharing,
verifies handle-derived path, volume and file identity, and reads through that
same handle. Writable mappings and incompatible handles cause refusal. Each lock
is also duplicated into the browser main process before acknowledging acquisition.
Killing the helper therefore does not remove the browser-owned locks.
Handles stay held until the matching native completion/error event. Policy
changes, scanner denial, timeouts, redirect or helper failure alone never release
them. A confirmed terminal event permits explicit cleanup, including a trusted
replacement helper after helper death. Remote handle closure is one-shot: an
uncertain close is never retried because Windows may recycle a handle value.
Unexpected helper/protocol failure disables acquisition and keeps the browser in
quarantine across policy refresh until restart. Unknown handle receipts remain
locked until the owning browser process exits.
Snapshot buffers are cleared after inspection. File content is not persisted by
this gate. Ordinary transfer audit retains hash-free total request bytes and type,
decisions, policy version and trace correlation; it does not fingerprint an entire
multipart credential envelope. JavaScript/base64 string copies cannot be reliably
overwritten and are garbage-collected.
## Actual verification
- Real Windows tests reject writes, hardlink writes, renames, junctions, excessive
sizes, pre-existing write handles and writable mappings.
- Actual managed Electron uploads deliver exact allowed file bytes once and keep
a confidential file from reaching the receiver.
- Actual redirect/helper-death tests confirm denied redirect targets, terminal
cleanup, and persistent fatal quarantine.
- Package verification exercises the shipped helper and Python runtime, including
blocked overwrite/rename followed by explicit cleanup.
Evidence: `artifacts/native-file-upload-proof.json`,
`artifacts/upload-lifecycle-native-proof.json`, `tests/upload-lease.test.mjs` and
`tests/file-upload-gate.test.mjs`.
These checks concern the tested ordinary NTFS file path. They do not establish
every filesystem/filter-driver behavior, browser-main crash behavior while a
network service survives, protection against privileged OS manipulation, or all
remaining streaming/native Chromium enforcement requirements.
## Debug observability
`browser.upload.lease`, `browser.upload.part`, `browser.upload.release` and
`browser.upload.fault` provide phase timings. Local worker stages are children of
the relevant inspection span. Fixed `safetynet.reason` values identify context
changes, deadlines, invalid ownership and lost/failed handle leases. Arbitrary
rule strings and exception contents cannot become reason attributes.
A real helper termination exported `upload-lease-lost` in a fault span and two
correlated logs, linked to its original lease parent and the durable audit event:
trace `e6d26d4edf738a7b4f6f562ab2112f5b` (fault stage 36.27 ms). Proof:
`artifacts/native-upload-fault-trace-proof.json`.