Security posture
How to run gimorra safely — the default posture, what it does not confine, what to put around it — and how to report a vulnerability in gimorra itself.
Most agentic security tooling is gated to the point of uselessness — a human confirms every action, so nothing runs unattended. Gimorra takes the opposite bet: maximum autonomy, bought with deterministic guardrails rather than with a per-action prompt. The permissiveness is the product.
| Default | Value | What it means |
|---|---|---|
agent.autonomy |
unrestricted |
No approval gates. Every in-scope action class runs auto — passive
recon, active non-mutating work, agent-authored scripts, exploit validation and
state-changing actions. Nothing parks for a human.
|
| tool execution | on this host |
Gimorra ships no sandbox. The agent's Bash and every CLI it
invokes run on your machine, as your user, with your filesystem, environment, network
and credentials.
|
agent.spend_cap_usd |
unset | Unbounded token spend on the engagement. |
unrestricted is not a mode we tolerate; it is the one the tool is designed
around. A run that stops at every judgement call is a run you may as well have done by hand.
The security boundary for that autonomy is the environment you run gimorra in, not gimorra. A VM, a disposable cloud box, a container you launched, a network namespace with its own egress rules. You pick it, and gimorra cannot verify it — so it says so on stderr before it spends a token, once per state dir, and then it runs. A marker records that you were told, which is not an acknowledgement.
gimorra config set isolation.sandbox_ack true # or GIMORRA_SANDBOX_ACK=1 gimorra config set isolation.require_sandbox true # or GIMORRA_REQUIRE_SANDBOX=1, refuse instead
Neither is a sandbox. The notice is the one moment this page gets read; the demand is for when a notice is not enough — a shared box, a CI runner, a team where "I read it" should be recorded before anything starts.
Earlier versions shipped a container execution mode: each job in a per-job image behind a default-deny egress firewall compiled from the engagement scope. Removed, deliberately. It bought its boundary by taking the agent's freedom back — default-deny egress blocks the mid-run install, the payload from a gist, the resolver the model wants — and it was worse than it read: the ops image satisfied one of the twenty CLIs the arsenal declares while the availability check reported all twenty present. Your exposure did not change when it went, because the shipped default was already the host.
Unrestricted is not unguarded. These are non-AI controls that hold regardless of
autonomy, and hold even if the model is prompt-injected, because
packages/safety and packages/validators have no dependency on the
agent, model, or network stack.
gimorra eng kill <id> writes durable state that a
running job re-reads before every target-touching call, so it reaches a job already in
flight in another process, bounding new traffic and rejecting late proof commits. It does
not recall a request already on the wire, and there is no automatic kill. Ctrl-C
also reaps the child processes of the run in your terminal.
Read this part before deciding your current setup is fine.
nuclei -u http://app.example is neither a URL nor a hostname to the extractor.
The agent invokes every arsenal CLI through Bash.
Those calls are allowed on purpose. Denying every command whose destination cannot be established would deny the whole arsenal. What they are not is silent — every one is recorded in the job transcript:
gimorra eng log <id> | grep scope-unbounded # what ran with no scope decision behind it
Beyond that:
~/.ssh, read ~/.aws,
reach your LAN or an internal service that was never in scope.
nuclei,
nmap, katana, semgrep and friends. A malicious or
compromised one runs on your host, not in a jail.
autonomy: unrestricted.
codex child is not gated in-loop at all. That runner cannot veto a
tool call, so gimorra's gate never sees them and its scope rests entirely on codex's own
OS sandbox. Every such child says so in its transcript.
The controls above keep a run from harming the target beyond a non-destructive proof. Only the environment keeps it from harming you. Pick one — they compose.
The shipped Dockerfile bakes the CLI plus the whole toolchain, so the agent's shell-outs land in the container's filesystem rather than yours — and it is the cheapest way to get that toolchain.
docker build -t gimorra -f infra/Dockerfile . docker run --rm -it \ -e ANTHROPIC_API_KEY=sk-... \ -e GIMORRA_SANDBOX_ACK=1 \ -v gimorra-data:/data \ gimorra gimorra scan -t 'http://TARGET/item?id=1'
A non-privileged user, a network segment that cannot reach your production estate, no ambient credentials — no cloud keys, no prod kubeconfig, no SSH agent forwarding, no password manager session. Assume everything reachable from the shell gimorra runs in is reachable by gimorra.
Gimorra no longer compiles a firewall from the engagement scope. If a program requires that no packet ever leaves toward an out-of-scope host, put that rule in the network itself — a namespace, a filtering proxy, a security group. The scope checker tells you what belongs on the allow-list.
gimorra eng scope-check <id> -i candidates.txt --in-scope-only
gimorra config set agent.autonomy standard # state-changing actions park for approval gimorra scan acme.test --autonomy strict # recon only, per run gimorra config set agent.spend_cap_usd 50 # hard ceiling on engagement spend gimorra config view -l # what posture am I actually running in
Both tiers keep the scope guard on. gimorra doctor reports what isolation it
can detect and whether you have acknowledged the posture, but detection is
advisory only — a VM and a network namespace are invisible from inside the process,
so it never gates anything.
$GIMORRA_HOME (default ~/.gimorra)
holds the store, the engagement folders and the proof documents. It is created
0700 and repaired on every store open.
<sha>.json. The unredacted <sha>.raw.json is written
0600, never hashed, and only read back on the machine that proved it.
Scrubbing happens once, at one seam.
0700 home.
--redact-credentials masks them for a screen share; that flag is not a
boundary, $GIMORRA_HOME is.
gimorra serve can start scans, so treat it as remote code execution by
design. It defaults to 127.0.0.1:8787 with authentication on
(username/password → a short-lived HS256 JWT; both the password and the signing secret are
auto-generated on first config write).
Two flags remove that protection, and you should never combine them on a reachable
interface: --host 0.0.0.0 binds every interface, -A disables
authentication entirely. If the gateway needs to be reachable, put it behind a reverse proxy
with TLS and your own authentication, keep gateway auth enabled, and rotate the JWT secret.
Authorization is role-based, running
viewer < operator < approver < administrator, and any mutating route
nobody listed fails closed to administrator.
Gimorra refuses active operations without an authorization artifact, but that artifact is something you assert: it records intent, it does not grant permission. Running gimorra against infrastructure you do not own or have written authorization to test is likely a crime in your jurisdiction, and the licence it ships under disclaims all warranty and liability.
Report privately through
GitHub Security Advisories. Include the version (gimorra version) and how it was installed; the
configuration that matters (agent.autonomy, the isolation block,
gateway auth); a minimal reproduction; and the impact you believe it has.
Expect an acknowledgement within a few days, and a fix or a stated rationale for anything confirmed. Credit is offered by default; say so if you would rather not be named.