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.pdf
artifacts 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.setFileInputFiles with the artifact path.
- macOS WKWebView: implement if a host-owned path exists; otherwise
UNSUPPORTED_CAPABILITY and declare fileUpload false. 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. Not html, 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 is ELEMENT_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
upload on 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.
What an agent cannot do today
Agents cannot attach a file to
<input type=file>. Inspect deliberately does not advertiseupload. 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 addcopies a local regular file into the existing0700artifact store as a new0600O_EXCLname.uploadtakes the same target grammar asclickand 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.
DOM.setFileInputFileswith the artifact path.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:pdf,png,jpg,jpeg,gif,webp,txt,csv,json. Nothtml,svg,exe, archives, or the blocked download extensions.upload:<input type=file>(or equivalent file control). Anything else isELEMENT_NOT_FOUND/ invalid target, not a silent click.uploadon file inputs once the command exists. Update the protocol test that currently forbids that string.Tests
Protocol: parse, reject path traversal, reject
.exe/.html, reject overwrite, reject oversized add, rejectuploadwithout 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_CAPABILITYif WebKit cannot attach files.Docs
COMMANDS.md,agentHelp, skill, capabilitiesfileUpload, what-is-excellent note that upload is artifact-store only.