Repository navigation
File upload from the private artifact store #168
Description
What an agent cannot do today
Agents cannot attach a file to <input type=file>. Inspect deliberately does not advertise upload. QA of resume/import/image flows requires a human. Downloads stay denied; this is the inverse: a user-supplied fixture enters the private artifact store, then the host attaches it.
Proposed surface
headless artifacts add ./resume.pdf --name resume.pdf
headless artifacts list
headless upload --role textbox --name "Resume" --artifact resume.pdf
headless upload @e12 --artifact resume.pdfartifacts add copies a local regular file into the existing 0700 artifact store as a new 0600 O_EXCL name. upload takes the same target grammar as click and an artifact basename only. The password never leaves the store as a socket payload; the host uses the on-disk path.
Engines
Both if the engine can attach a file without an arbitrary-JS verb.
- Linux Chromium:
DOM.setFileInputFileswith the artifact path. - macOS WKWebView: implement if a host-owned path exists; otherwise
UNSUPPORTED_CAPABILITYand declarefileUploadfalse. Do not fake it with page JavaScript that the site could observe as a hole.
Contract
Architecture-decision entry in the same PR. Downloads remain denied. No home-directory paths on upload. No TCP fixture server.
artifacts add:
- Source must be an absolute or cwd-relative regular file. No directories, no FIFOs, read the bytes, do not preserve a symlink as the stored object.
- Destination is a validated bare name, no leading dot, portable charset, never overwrite, never path-traverse.
- Size cap 5 MiB.
- Extension allow-list:
pdf,png,jpg,jpeg,gif,webp,txt,csv,json. Nothtml,svg,exe, archives, or the blocked download extensions. - Fail closed if the store is missing or the name exists.
upload:
- Artifact name only, same validation. Missing artifact is a specific error.
- Target must be
<input type=file>(or equivalent file control). Anything else isELEMENT_NOT_FOUND/ invalid target, not a silent click. - File bytes never appear in protocol parameters, MCP, logs, flows, snapshots, diagnostics, or errors. Flows may record the artifact basename.
- Inspect may advertise
uploadon file inputs once the command exists. Update the protocol test that currently forbids that string. - Private artifact listing includes the new extensions.
Tests
Protocol: parse, reject path traversal, reject .exe / .html, reject overwrite, reject oversized add, reject upload without a stored artifact, reject upload to a non-file control.
Linux E2E: add a tiny pdf/png fixture, upload into a file input, assert the page sees a filename. macOS E2E: same, or assert UNSUPPORTED_CAPABILITY if WebKit cannot attach files.
Docs
COMMANDS.md, agentHelp, skill, capabilities fileUpload, what-is-excellent note that upload is artifact-store only.
Activity
feat(protocol): add artifact ingest and file upload
SarthakWade commentedon Sep 12, 2026
PR #169 delivered the safe half of this issue: an agent can attach a validated file that already exists in the private artifact store. It intentionally removed the proposed agent/MCP-facing
artifacts add <local-path>command because that surface would let an agent read and exfiltrate arbitrary host files with allowed extensions. Reopening this issue for the remaining trusted, user-mediated staging design. The completed upload command must remain restricted to private-store basenames.yashranaway commentedon Sep 13, 2026
Shipped in #169. Agents can
uploada basename that already exists in the private artifact store. Ingest is a local CLI operator path (headless artifacts add), not a protocol or MCP command, so the agent cannot read arbitrary files. WebKit still returnsUNSUPPORTED_CAPABILITY.