Skip to content

File upload from the private artifact store #168

Description

@yashranaway

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:agent-runtimeInjected JS: inspection, pruning, refsarea:cliCLI parser, help, capabilitiesarea:core-protocolHeadlessProtocol: wire protocol, validation, transportarea:linux-hostChromium host (LinuxHost/, CDP)area:macos-hostWKWebView host (main.swift, Host/)priority:mediumScheduled, not blockingtype:featureNew capability or commandtype:securitySecurity boundary or hardening

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions