draft

Security

No tokens on disk

Session backends shell out to an already authenticated CLI. draft never reads, stores or logs an API key.

Prompts and process listings

A prompt passed as a command-line argument is visible in a process listing for the duration of the call, along with the source excerpts it quotes. claude, codex and cursor-agent are driven over stdin and are not affected; the others were confirmed not to read stdin — their prompt flags require a value — so they still use an argument. On a shared host, prefer one of those three, or Ollama.

Know your agent's trust surface

Session providers run in non-interactive modes, some of which auto-approve tool use. draft asks only for text, but you are still handing a PDF to an agent that can act. Treat sources as untrusted input, and prefer Ollama for material you do not trust.

Template and source text are quoted as untrusted evidence, and the writing prompt tells the model to ignore any instructions found inside them. Treat that as defence in depth rather than a guarantee.

Bounded external calls

Extraction shells out only to pdftotext and textutil, with context timeouts, absolute paths — so a file named -x.pdf cannot be read as a flag — capped output, and no shell interpolation. Every generation call is bounded by DRAFT_CALL_TIMEOUT.

OLLAMA_HOST is validated: a value that is not a valid http/https URL is refused rather than concatenated into a request URL, and a host that is not loopback is reported, because a remote Ollama means your source text leaves the machine.

Cancellation means cancellation

Quitting the dashboard, or Ctrl+C in headless mode, cancels the run's context and terminates any in-flight subprocess or Ollama request. A cancelled run stops there rather than failing over to the next backend.

Verifiable releases

Signed with keyless Sigstore cosign, published with a CycloneDX SBOM per archive and GitHub build provenance:

cosign verify-blob --bundle checksums.txt.sigstore.json \
  --certificate-identity-regexp 'https://github.com/sebastienrousseau/draft/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  checksums.txt

Every pull request runs build, three-OS tests, lint, an MSRV check, govulncheck, CodeQL and REUSE compliance, with statement coverage gated at 95% and fuzzers on every parser that reads untrusted input.

Reporting a vulnerability

See the disclosure policy.