Security

Security

XORCISE runs offensive agents against deliberately vulnerable targets on your own machine. That deserves a page that says how the isolation is built, what crosses the boundary, how to tell us when it is wrong, and what we have not done yet.

Reporting a vulnerability

Email security@xorcise.ai. Please include the XORCISE version (xorcise --version), the host platform, what you did, what you expected, and what happened instead. A proof of concept helps more than a description of one.

We ask for coordinated disclosure: give us a chance to ship a fix before you publish, and we will credit you in the release notes unless you would rather we did not. We do not run a bug bounty, and we will not threaten anyone who reports a finding in good faith.

If you would rather not send it in the clear, encrypt to our disclosure key. Verify the fingerprint against this page before you trust it. We serve both from the same host, so this checks that you have the right key, not that nobody replaced it.

Fingerprint
7669 9A0C 221D D2F8 4358 E871 FC6A E63E B8E3 EB95
Key
RSA 4096, created 31 July 2026, expires 30 July 2029. Download the public key , or curl -sSL https://xorcise.ai/security/xorcise-security.asc | gpg --import.

Still not published: a response-time commitment and a security advisory feed. Report anything you find in the meantime. The absence of a process is not a reason to sit on a finding.

The isolation boundary

The site says the fence “holds by construction, not by trust”. This is what that means.

Each run mints its own Headscale control plane entry with an ACL scoped to that run: the agent can reach its one mission and nothing else, enforced at the network layer rather than asked of the agent. Rendering a policy that would permit more fails closed: an assert_policy_safe check gates every policy render, and a failed check stops the run instead of widening the fence. The ACL renderer also refuses wildcards outright: a policy containing *:*, a wildcard source or a group grant is rejected before it is ever applied.

Traffic between the agent and the mission is WireGuard, direct peer-to-peer where the network allows it. Where it does not, it falls back to the DERP relay embedded in the control plane, so the control plane can carry run traffic, as encrypted WireGuard packets it cannot read. It is a relay, not a party to the session, but “nothing passes through the control plane” would be the wrong thing to tell you.

Scope analysis over the recorded trace is a complementary audit, not the boundary. If the two ever disagree, the ACL is what actually happened and the trace is what was observed.

The fence confines the agent. It does not harden the mission image you chose to pull, and it is not a substitute for running this on a host you are willing to lose.

What leaves the host

Nothing goes to us by default: no phone-home, no usage telemetry, and the OTel mirror is off. App state, the trace store and every result stay in ~/.xorcise/. Three things do cross the boundary, all of them because you asked for them:

The mission catalogue
xorcise mission pull and xorcise catalog status reach our registry on demand. Once a mission is on disk, running and grading it never touches us again.
Your judge model
Half of every grade is produced by a model you configure, so the submitted artifacts and a distilled transcript go to that endpoint. Any OpenAI-compatible URL works, including a self-hosted model or an internal gateway. With no judge configured, that half scores zero.
The collector carve-out
In distributed deployments a fail-closed ACL exception lets the agent reach the trace collector on :4318. It is the only egress permitted beyond the mission subnet, and it is deliberate.

Ports, as shipped locally

PortComponentBindsDetail
:443Headscale control plane / rendezvouspublished on the hostHTTPS, forwarded to the container's listen_addr on :8443; gRPC on :50443. The only endpoint every peer must reach, and the one that carries the embedded DERP relay.
:4318OTLP telemetry ingestloopback + Docker bridge gatewayHTTP, JSON and protobuf, received in-process. This is how the agent's trace arrives, so it binds the Docker bridge gateway alongside loopback by the same rule as the API.
:3001REST API and the console UIloopback + Docker bridge gatewayServes /ui and everything the console does. Unauthenticated, apart from the per-run agent routes. Read it twice: the bridge address is there so the agent container can reach it, which means every local process and every container on that bridge can too. It widens to the IPv4 wildcard on an explicit XORCISE_HOST=0.0.0.0, or on Linux when the bridge gateway cannot be determined at boot.
:8800Runner plane127.0.0.1Drives mission containers. The per-run agent-facing routes are authenticated by an HMAC-signed run key that expires at teardown.

Running it safely

Treat the host as untrusted
Missions are deliberately vulnerable: the library includes an Apache 2.4.49 host carrying CVE-2021-41773, and others like it. Run them somewhere without routes into a network you care about, not on the laptop that holds your production credentials.
The console has no login
The REST API and UI on :3001 are unauthenticated, and on a default local install they bind the IPv4 wildcard rather than loopback so the agent container can reach them. Anyone who can route to that port can create runs, read results and browse the host's directory tree through the file picker. Put it behind a firewall, or do not run it on a network you do not control.
The host holds a secret
Your judge model key is stored in plaintext at ~/.xorcise/.env and never returned by the API. It is as safe as the machine it sits on.
It needs real privileges
A reachable Docker daemon, and /dev/net/tun on Linux for the per-run router. Anything that can talk to your Docker socket can do what Docker can do.
Only targets you are allowed to touch
XORCISE stands up its own targets and fences them. It does not choose what you point your agent at outside a run, and pointing a cyber agent at infrastructure you do not own or have written authority to test is not something this tool authorises.

Both of those now have a document behind them rather than a sentence: what XORCISE may be pointed at, and where export-control and sanctions responsibility sits, are set out in the acceptable use policy. If your organisation needs a specific export-control classification before it can adopt XORCISE, section 5 says how to ask for one.

Supply chain

The package
pip install xorcise, from PyPI. 14 direct runtime dependencies, named one by one with their licences in the third-party notices, opentelemetry-proto version-pinned. One of the fourteen, tiktoken, records its licence in a non-standard metadata field and is published as unresolved rather than guessed.
Upstream images
docker:27-dind, tailscale/tailscale:stable, headscale/headscale:stable and python:3.12-slim, pulled from their public registries at run time.
Mission images
One fused image per mission, pulled from our catalogue registry on xorcise mission pull. Deliberately vulnerable by design; see below.
The playbooks skill
Scripts and templates, cloned into your agent's skills folder and then executed by that agent. We host no archive of it, so the repository is the only copy: clone it, and prefer a tagged release, which you can diff against the history it came from. Those releases are not yet signed.

Every direct runtime dependency is named with its licence in the third-party notices, including the one we have not been able to resolve.

The playbooks skill you are told to hand to an agent is published from one place, its source repository. We host no archive of it, so there is no second copy to verify against: what you clone is the thing itself, at a commit you can name.

Everything we publish (the engine, the mission library, the playbooks skill and the docs) is Apache-2.0.

What we do not do yet

Published here rather than left to be discovered, because a gap you know about is one you can plan around.

Mission images are not signed and ship no SBOM
Pulled images are not signed, not pinned by digest in the catalogue, and carry no bill of materials. Verify what you run, and treat the host accordingly.
No third-party penetration test is published
The isolation boundary described below has not been audited by anyone outside the company, and we have not published a report.
No SOC 2, and no certification covering the engine itself
Fifth Domain, which operates XORCISE.AI, is certified to ISO 9001 and ISO/IEC 27001, which covers how the company is run, not an audit of this engine or its isolation boundary. No SOC 2 is held or in progress. XORCISE is a local process you run; there is no hosted service holding your data to certify.
Network facts are coarse
The evidence stream records ACL configuration, entry CIDRs and agent-user lifecycle. Per-connection flow capture and boundary-violation capture are not implemented, so a run report shows the fence as configured, not every packet it dropped.

XORCISE is in public beta. Privacy, AI trust & safety, and trademark policies →