Security model
What it refuses to do is the product.
Every control below is enforced in the server, before a handler runs. None of it depends on the model behaving well, and none of it can be talked out of by a prompt.
Defence in depth
Six layers, checked in order
Transport
The server binds 127.0.0.1 unless OMAS_HOST says otherwise. It refuses to start on a non-loopback address without a public path token, and refuses outright on a non-loopback address when any repository has command execution enabled.
Public access is expected to go through a tunnel or the Premium relay. Team control must stay on a loopback bind.
Root resolution
The client never supplies an absolute repository path. It supplies a repo_id, and the server resolves that id to an approved root from config. Unknown repositories are rejected.
All model-supplied paths must be repo-relative POSIX paths. The path sandbox rejects absolute paths, traversal, symlink escapes, device files, sockets, and named pipes.
Secret candidates
Secret-looking paths are blocked by default even when explicitly requested: .env files, private keys, certificate bundles, identity keys, and directories named exactly secrets or credentials.
Ordinary code, docs, and tests are not blocked merely for containing the word secret. Public templates such as .env.example can be read only if their contents also pass secret scanning.
Write policy
Writes are disabled for every repository until it opts in. Denied globs and hard secret checks win over allowed globs, always.
Every write enforces repo-relative paths, no traversal, no symlink escape, a max-bytes cap, and a secret scan of the resulting content. dry_run performs all checks and computes the result without writing.
Command execution
Not part of the capability ladder at all. Commands stay disabled until you configure named recipes, and are gated per repository.
Execution uses argument vectors directly with no shell, so there is no interpolation to exploit. Only configured environment names are inherited; server credentials never are.
Audit
Every operation emits a JSON audit event with value-free metadata: the log records that an operation happened and against what, never the contents.
Tool outputs, errors, and logs are barred from including blocked secret contents, tokens, credentials, environment variables, or raw errors.
Honest limits
What the path token is not
A tunnel URL ending in /t/<token>/mcp is guess-resistance, not authentication.
Anyone holding the full URL can reach the MCP endpoint while the public tunnel is running. Treat an omas connect URL as a temporary development endpoint and stop it when you are done.
Network exposure does not widen repository policy. The client still supplies only a repo_id; approved roots, default excludes, path sandboxing, secret checks, write policy, and tool schemas all still apply. Mutating tools stay disabled unless that repository enabled them.
For a longer-lived connection, the Premium relay replaces the shared-URL model with an enrolled node and its own credential.
The escape hatch
unsafe_full_access, documented plainly
One switch removes most of the above. It exists for fully trusted local setups, and the documentation does not soften what it does.
{
"unsafe_full_access": true,
"dynamic_roots": {
"discovery_roots": ["/home/admin/Projects"]
}
}
- Removes repository containment and symlink-escape checks
- Removes secret and content protections
- Removes configured byte and path limits
- Permits absolute and traversing paths
- Returns unredacted, untruncated command output
This is equivalent to granting the agent the MCP process user's host permissions. Do not enable it on an endpoint you do not fully trust. Network routing and tokenized endpoint protections are unchanged by it.
Read the threat model before enabling writes
The full document covers tool annotations, artifact roots, default excludes, the operations policy, nested repositories, the error envelope, and audit logging.