Please report security issues privately via GitHub Security Advisories rather than opening a public issue. Include reproduction steps and the version you tested.
Expect an initial response within a week. This is a volunteer-maintained project, so there is no formal SLA beyond that.
OmniWork is an autonomous coding agent. It executes shell commands and writes files on your machine, driven by a language model. That is the product, not a bug, but it means the safety boundary is narrower than most desktop apps. Be deliberate about what you point it at.
The file tools — read_file, write_file, edit_file, list_dir — resolve every path against
the workspace folder you pick and reject anything that escapes it, including via .., an
absolute path, or a symlink: paths are compared after resolving links, so a link committed in a
repository (docs/x -> ~/.ssh) cannot carry a read or write outside. Writes never go through a
symlink at all, even one that points back inside. Approval previews and ACP diffs read old file
contents through the same check.
run_command is not sandboxed. It runs in your shell with your full user privileges,
starting in the workspace directory. It does not inherit OmniWork's environment: commands get
PATH, home and temp directories, locale, proxy and CA settings, and toolchain locations, but
not tokens or keys from your shell (GITHUB_TOKEN, AWS_*, provider keys, database URLs), and
the shell is not a login shell, so your profile is not re-sourced. Add variables a project needs
with OMNIWORK_COMMAND_ENV_PASSTHROUGH=NAME,NAME. This narrows what a command is handed; it
does not stop a command from reading files in your home folder. Nothing stops a command from leaving that directory,
reading files elsewhere in your home folder, installing packages, making network requests, or
deleting data. Workspace confinement applies to the file tools only — it is not a sandbox, and
it is not a security boundary against shell commands.
Practically: the agent can do anything you could do from a terminal.
By default OmniWork runs tools without asking. Click the 🛡 toggle in the status bar (or run
/approve ask) to require confirmation before every command, file write, web request
(web_fetch, web_search, browse_page, open_url), subagent fan-out, and MCP call. Approval
prompts show a diff for file changes and the full command line for shell calls.
Turn this on when working in a repository you care about, or when running a task you have not run before.
Two rules hold in every mode:
- Writes that outlive the session ask first.
save_skill,install_skillsand globalsave_memoryload into every future session in every project, so a prompt-injected save would persist the injection. They ask even inauto(a project-scoped memory note is the exception), are blocked inplan, and are refused in headless runs that have nobody to ask.OMNIWORK_AUTO_PERSIST=1restores the oldautobehaviour for one release. - Unknown means no. An unrecognised approval mode blocks every tool, and a tool name the agent does not know is blocked rather than dispatched.
The agent reads files, fetches web pages, and calls MCP tools — and everything it reads enters
its context. A hostile README, a poisoned web page, or a malicious MCP server can contain text
that instructs the model to run commands you never asked for. Model output is not a trusted
channel.
The practical mitigations, in order of effectiveness:
- When the task is to read untrusted text — score a document, extract fields, summarise a
page — don't give it an agent at all: use tool-free completion (ACP
completionmode, the MCPcompletetool, ornpm run complete). The request carries no tools, so there is nothing for injected text to call. - Use approval mode when the agent will touch untrusted content
- Point the workspace at a specific project, not your home directory. A repository's own
instruction files (
AGENTS.md,CLAUDE.md,.cursorrules, …) and.omniwork/skillsreach the model as labelled, lower-trust project context, never with the authority of your instructions (a repository skill can't replace one you installed). For a repository you don't trust, leave them out entirely:OMNIWORK_PROJECT_FILES=off, or_meta.omniwork.projectFiles: falseon ACP. - Only connect MCP servers you trust — they run as local subprocesses with your privileges
- Prefer a VM or container for genuinely untrusted repositories
- The gateway binds loopback only (
127.0.0.1:20128). It is not reachable from your network. - It only serves OmniWork. Every request needs the per-install key in
~/.omniwork/gateway-key.txt(owner-only), so web pages and other accounts on the machine can't use your providers through/v1. A guard inside the gateway refuses anyHostheader other than its loopback address (which defeats DNS rebinding) and any cross-siteOrigin.OMNIWORK_GATEWAY_OPEN=1drops the key requirement for one release. - OmniRoute's management API (
/api/*, used by its dashboard) is not behind the key while the dashboard has no password: the guard keeps browsers out, but another account on the same machine could still reach it. On a shared machine, set a dashboard password in OmniRoute's settings. - Provider API keys are stored by OmniRoute in its local data directory (
storage.sqlite), readable only by your account. OmniWork does not enable OmniRoute's field encryption, so treat that directory — and any copy or backup of it — as holding your keys. - The gateway does not write prompts or replies to disk: OmniWork's requests go through a no-log
key. OmniRoute still records per-request metadata (model, token counts, status), kept for a day.
OMNIWORK_GATEWAY_LOGS=onkeeps full bodies incall_logs/(owner-only, one day). Everything the gateway writes, and ACP transcripts, are owner-only. - Prompts and file contents are sent to whichever model provider
autorouting selects. Free providers vary in their data-retention policies — do not send secrets or proprietary code through free-tier models without checking the provider's terms. - OmniWork itself has no telemetry and phones home to nothing.
- OmniRoute (the gateway) and OpenCode are pinned to exact versions. Both run with your
privileges, and both install with npm
postinstallscripts —npm ciin a clone runs them. - Everything OmniWork downloads at runtime is checked against a hash pinned with the version before it is unpacked: the OmniRoute engine in Lite builds, and the OpenCode binary.
npx -y omniwork-acpruns the newest release. To review an upgrade before it runs in your editor, pin the version you checked:npx -y omniwork-acp@<version>.
Release binaries are not code-signed or notarized. macOS and Windows will warn you, and you have no cryptographic assurance the download is unmodified beyond the SHA-256 published in the release notes. Verify it if that matters to you:
shasum -a 256 ~/Downloads/OmniWork-0.9.1-arm64.dmgBuilding from source avoids this entirely.
Only the latest release receives fixes. There are no long-term support branches.
| Version | Supported |
|---|---|
| 0.9.x | ✅ |
| < 0.9 | ❌ |