Security posture

The boundary around a run is yours

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.

Only ever point gimorra at systems you are authorized to test. No authorization artifact, no active operation: that part is enforced in code. Everything else about how much rope the agent gets is a config value, and the shipped default gives it all of it.

The default posture is unrestricted and unsandboxed, on purpose

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.

There used to be a second layer here. There isn't.

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.

What still holds

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.

What those controls do not do

Read this part before deciding your current setup is fine.

The in-loop guard governs structured tool calls. It does not constrain the offensive tooling itself. A tool argument that is a URL, a hostname, an IP or a CIDR gets extracted and checked. A shell command line does not: it is one opaque string, and 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:

Required: run gimorra in a sandbox, a VM, or a container

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.

1 · Run gimorra itself inside the operator image

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'

2 · A disposable VM or a dedicated box

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.

3 · Your own egress rules, if scope compliance is contractual

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

4 · Turn the autonomy dial down when the target is not yours

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.

Secrets, artifacts, and logs

Exposing the gateway

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.

Authorization and legal use

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.

Reporting a vulnerability

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.