This guide is the enterprise threat model and data-handling contract for CodeProbe. It describes the current implementation, not a target state.
The machine-checked inventory for this guide lives in
docs/security/enterprise_inventory.json and is enforced by
tests/lint/test_enterprise_security_docs.py. Source anchors for the claims in
this document include src/codeprobe/adapters/_base.py,
src/codeprobe/cli/check_infra.py, src/codeprobe/cli/purge_cmd.py,
src/codeprobe/cli/run_cmd.py, src/codeprobe/core/containment.py,
src/codeprobe/core/scoring/sandbox.py, src/codeprobe/net/credential_ttl.py,
src/codeprobe/net/offline.py, src/codeprobe/sandbox/agent_container.py,
src/codeprobe/sandbox/image_bootstrap.py,
src/codeprobe/sandbox/image_config.py, src/codeprobe/sandbox/runner.py,
src/codeprobe/cli/bootstrap_cmd.py, src/codeprobe/sandbox/Dockerfile.agent,
src/codeprobe/sandbox/Dockerfile.scoring, src/codeprobe/snapshot/redact.py,
src/codeprobe/trace/content_policy.py, and src/codeprobe/trace/store.py.
Related public contracts are SECURITY.md, README.md,
docs/SNAPSHOT_REDACTION.md, docs/EVIDENCE_BUNDLE.md, and
docs/adapters.md.
CodeProbe turns repository history into evaluation tasks, runs one or more coding agents against isolated worktrees, scores the results, and records outcomes. It can also create local snapshots and zero-code-access evidence bundles for review.
CodeProbe executes:
- git commands against the target repository;
- agent subprocesses or backend SDK calls;
- mined
test.shand verifier scripts; - Docker or Podman containers when the required images are available; and
- local snapshot, export, validation, and purge commands.
CodeProbe reads:
- repository source and history;
.codeprobe/experiment metadata, tasks, and prior run artifacts;- security-relevant environment variables documented below;
- per-agent configuration such as
CLAUDE_CONFIG_DIR; and - generated MCP configuration temp files named
codeprobe-mcp-*.json.
CodeProbe writes:
.codeprobe/<experiment>/runs/results, transcripts, checkpoints, andtrace.db;- isolated task worktrees and scoring temp directories;
- per-slot agent session directories in temp storage for agents that need session isolation;
- snapshots and zero-code-access evidence bundles when requested; and
- local export artifacts for downstream systems.
Protected assets:
- proprietary repository source and diffs;
- prompts, instructions, task metadata, transcripts, traces, and verifier outputs;
- API keys, OAuth tokens, gateway tokens, proxy credentials, and short-lived cloud credentials;
- experiment configuration, results, aggregate reports, and evidence bundles; and
- the operator workstation or CI runner that invokes CodeProbe.
Trust boundaries:
| Boundary | Current contract |
|---|---|
| Operator host or CI runner | Trusted to hold source, credentials, container engine state, and local artifacts. Local OS compromise is out of scope for CodeProbe controls. |
| Agent worktree | Isolated per task, created from committed state. A dirty primary checkout is refused unless --allow-dirty is passed. |
| Agent process | Autonomous code execution. Container mode limits mounts but still gives model egress. Host-consented mode gives the agent host filesystem, credential, and network access. |
| Scoring process | Mined third-party verifier code. Container scoring uses --network=none; host fallback requires an already contained environment or explicit --uncontained consent. |
| Model, git, and tool providers | External trust boundary. Content sent to those endpoints is governed by the operator's provider contracts. |
| Snapshot and evidence export | Local file boundary. Export commands write files only; the operator decides whether and where to transmit them. |
Attacker capabilities considered:
- a malicious or compromised mined verifier script;
- a malicious or compromised agent process;
- prompt or tool output that includes secrets or proprietary source;
- stale or unexpected MCP configuration temp files;
- accidental publication of local run artifacts;
- network endpoints that log prompts, tool requests, or source snippets; and
- symlink or path manipulation near deletion and export boundaries.
Out of scope:
- a compromised host kernel or container runtime;
- malicious maintainers of the target repository;
- provider-side retention or training policy outside CodeProbe's control; and
- operator mistakes after local export files have been created.
| Subsystem | Required egress | Notes |
|---|---|---|
codeprobe bootstrap |
Configured OCI registry in online mode; none in paired archive mode | Online mode asks the container engine to pull each digest-pinned image. Archive mode requires no network egress and validates local OCI archives with Skopeo. Registry authentication, proxy, and private-CA trust belong to the engine. |
codeprobe mine |
Git remotes, optional PR or issue APIs, optional LLM backend, optional MCP or code-search endpoint | Narrative and enrichment quality depend on configured sources. --no-llm and offline fallbacks reduce egress but may lower task quality. |
codeprobe run agent execution |
Model API or configured agent gateway; configured MCP/tool endpoints when the agent arm enables them | Agent containers run with --network=bridge because the agent must reach the model API. |
| Scoring and verifier execution | None in container mode | The scoring container uses --network=none. Host-consented verifier execution inherits the host network. |
codeprobe check-infra offline |
None | Credential TTL checks read environment variables only. |
codeprobe snapshot create, snapshot verify, snapshot evidence, snapshot export |
None | These commands are local transforms. Uploading generated artifacts is outside CodeProbe. |
codeprobe purge |
None | Deletes only scoped local artifacts. |
CodeProbe does not restrict agent-container bridge egress by destination. Use host, container-engine, or network controls when an enterprise policy requires an endpoint allowlist.
The published image names are versioned CodeProbe labels. Their base images
are pinned by SHA-256 digest:
node:22-bookworm-slim@sha256:6c74791e557ce11fc957704f6d4fe134a7bc8d6f5ca4403205b2966bd488f6b3
for codeprobe-agent:0.14.0 and
debian:bookworm-slim@sha256:7b140f374b289a7c2befc338f42ebe6441b7ea838a042bbd5acbfca6ec875818
for codeprobe-scoring:0.14.0. Debian package installation uses a dated
snapshot. The Claude Code version and npm integrity are pinned, and both
images declare the non-root codeprobe user. The release workflow emits SBOM
and provenance attestations, scans both images, and signs their immutable
digests. Runtime consumers must use the verified digest identities rather
than treating a version tag as an integrity boundary.
Prepare the released agent and scoring images from an installed wheel. Replace the example digests with the verified release or private-registry digests:
codeprobe bootstrap \
--agent-image 'registry.example.test/platform/codeprobe-agent@sha256:<agent-digest>' \
--scoring-image 'registry.example.test/platform/codeprobe-scoring@sha256:<scoring-digest>'The released source image names for this package version are
codeprobe-agent:0.14.0 and codeprobe-scoring:0.14.0. Bootstrap works with
Docker or Podman and needs no repository checkout or Dockerfiles. It verifies
both expected digests before atomically recording immutable local IDs. Private
registry authentication, proxy configuration, and private CA trust remain
operator-controlled engine settings. For air-gapped loading, pass both
--agent-archive and --scoring-archive; Skopeo validates and imports the OCI
archives.
Mount matrix:
| Execution path | Network | Host mount | Container mount | Mode |
|---|---|---|---|---|
| Agent container | --network=bridge |
per-task slot worktree | identical path | rw |
| Agent container | --network=bridge |
per-slot CLAUDE_CONFIG_DIR, when present |
identical path | rw |
| Agent container | --network=bridge |
generated MCP config temp file | identical path | ro |
| Agent container | --network=bridge |
validated private CA files and directories | collision-safe path under /etc/codeprobe/ca |
ro |
| Scoring container | --network=none |
scoring temp directory | identical path | rw |
The primary checkout and the user's global agent config directory are not
mounted into the agent container. A host-global CLAUDE_CONFIG_DIR is not used
as a fallback mount. The container receives a per-slot config dir only when
session isolation produced one.
Claude session isolation ensures credential files are private regular files
inside that per-slot directory. A hardlink is used when possible so in-place
OAuth refreshes remain coherent; the copy fallback keeps mode 0600. Other
read-mostly host configuration entries remain symlinks to the live host
configuration, including settings, skills, agents, hooks, plugins, commands,
and rules. Mounting the per-slot directory therefore exposes only that selected
session layout to the agent container even though the host-global config
directory is not mounted directly. Mutable session state is recreated inside
the slot.
The container posture is containment, not a hardened multi-tenant sandbox.
Both images declare a non-root codeprobe user, and runtime commands also map
to the invoking host UID and GID where supported. Agent and scoring containers
use --cap-drop=ALL, --security-opt=no-new-privileges, --read-only, a
bounded writable /tmp, --cpus=2, --memory=4g, and --pids-limit=256.
They retain the container engine's default seccomp profile rather than
shipping a custom seccomp profile. Operators running untrusted tasks should
still use a dedicated workstation, VM, or CI runner and keep the host kernel
and container engine patched.
Agent subprocesses receive a filtered environment from
src/codeprobe/adapters/_base.py, not the full parent process environment.
The host subprocess adapter environment whitelist is:
| Variable | Host purpose | Agent container behavior |
|---|---|---|
ALL_PROXY |
Proxy URL | Passthrough |
ANTHROPIC_API_KEY |
Agent or LLM backend API key | Passthrough |
ANTHROPIC_AUTH_TOKEN |
Enterprise LLM gateway auth token | Passthrough |
ANTHROPIC_BASE_URL |
Enterprise LLM gateway URL | Passthrough |
CARGO_HOME |
Rust toolchain path | Excluded because host paths are not mounted |
CLAUDE_CODE_OAUTH_TOKEN |
Agent OAuth token | Passthrough |
CLAUDE_CONFIG_DIR |
Per-slot agent config directory | Passthrough only when that directory is mounted |
CODEPROBE_SANDBOX |
User-set containment signal | Passthrough |
COPILOT_GITHUB_TOKEN |
Copilot GitHub token | Passthrough |
COPILOT_MODEL |
Copilot model override | Passthrough |
COPILOT_OFFLINE |
Copilot offline-provider toggle | Passthrough |
COPILOT_PROVIDER_API_KEY |
Copilot offline-provider credential | Passthrough |
COPILOT_PROVIDER_BASE_URL |
Copilot offline-provider endpoint | Passthrough |
COPILOT_PROVIDER_TYPE |
Copilot offline-provider type | Passthrough |
CURL_CA_BUNDLE |
Private CA bundle path | Excluded from valueless passthrough; mounted ro and rewritten |
DBUS_SESSION_BUS_ADDRESS |
Desktop session bus path | Excluded because host paths are not mounted |
GH_TOKEN |
GitHub CLI token usable by Copilot | Passthrough |
GITHUB_TOKEN |
Git provider token for agent tooling | Passthrough |
GOPATH |
Go toolchain path | Excluded because host paths are not mounted |
GOROOT |
Go toolchain path | Excluded because host paths are not mounted |
HOME |
Host home path | Excluded because host paths are not mounted |
HTTPS_PROXY |
Proxy URL | Passthrough |
HTTP_PROXY |
Proxy URL | Passthrough |
LANG |
Locale | Passthrough |
LC_ALL |
Locale | Passthrough |
LOGNAME |
User identity metadata | Passthrough |
NODE_EXTRA_CA_CERTS |
Private CA bundle path | Excluded from valueless passthrough; mounted ro and rewritten |
NODE_PATH |
Node toolchain path | Excluded because host paths are not mounted |
NO_PROXY |
Proxy bypass list | Passthrough |
NPM_CONFIG_PREFIX |
npm toolchain path | Excluded because host paths are not mounted |
OPENAI_API_KEY |
Agent or LLM backend API key | Passthrough |
PATH |
Host executable search path | Excluded because the image owns its toolchain |
PYTHONPATH |
Python import path | Excluded because host paths are not mounted |
REQUESTS_CA_BUNDLE |
Private CA bundle path | Excluded from valueless passthrough; mounted ro and rewritten |
RUSTUP_HOME |
Rust toolchain path | Excluded because host paths are not mounted |
SSL_CERT_DIR |
Private CA directory path | Excluded from valueless passthrough; mounted ro and rewritten |
SSL_CERT_FILE |
Private CA file path | Excluded from valueless passthrough; mounted ro and rewritten |
TERM |
Terminal metadata | Passthrough |
TMPDIR |
Host temp path | Excluded because host paths are not mounted |
USER |
User identity metadata | Passthrough |
VIRTUAL_ENV |
Python virtualenv path | Excluded because host paths are not mounted |
XDG_CONFIG_HOME |
Desktop config path | Excluded because host paths are not mounted |
XDG_DATA_HOME |
Desktop data path | Excluded because host paths are not mounted |
XDG_RUNTIME_DIR |
Desktop runtime path | Excluded because host paths are not mounted |
all_proxy |
Proxy URL | Passthrough |
http_proxy |
Proxy URL | Passthrough |
https_proxy |
Proxy URL | Passthrough |
no_proxy |
Proxy bypass list | Passthrough |
Additional process-level variables are:
| Variable | Purpose | Container behavior |
|---|---|---|
ANTHROPIC_API_KEY |
Agent or LLM backend API key | Forwarded by key name |
CLAUDE_CODE_OAUTH_TOKEN |
Agent OAuth token | Forwarded by key name |
CLAUDE_CONFIG_DIR |
Per-slot agent config directory | Forwarded only when that directory is mounted |
OPENAI_API_KEY |
Agent or LLM backend API key | Forwarded by key name |
COPILOT_GITHUB_TOKEN |
Copilot GitHub token | Forwarded by key name |
GH_TOKEN |
GitHub CLI token usable by Copilot | Forwarded by key name |
GITHUB_TOKEN |
Git provider token for agent tooling | Forwarded by key name |
COPILOT_OFFLINE |
Copilot offline-provider toggle | Forwarded by key name |
COPILOT_PROVIDER_BASE_URL |
Copilot offline-provider endpoint | Forwarded by key name |
COPILOT_PROVIDER_API_KEY |
Copilot offline-provider credential | Forwarded by key name |
COPILOT_PROVIDER_TYPE |
Copilot offline-provider type | Forwarded by key name |
COPILOT_MODEL |
Copilot model override | Forwarded by key name |
ANTHROPIC_BASE_URL |
Enterprise LLM gateway URL | Forwarded by key name |
ANTHROPIC_AUTH_TOKEN |
Enterprise LLM gateway auth token | Forwarded by key name |
CODEPROBE_SANDBOX |
User-set containment signal | Read by sandbox detection |
CODEPROBE_CONTAINER_CONFIG |
Absolute prepared-image record path | Read by bootstrap and container runtime |
CODEPROBE_OFFLINE |
Offline guard signal | Set by codeprobe run --offline after preflight |
CODEPROBE_SIGNING_KEY |
Snapshot HMAC key | Read by snapshot signing |
AWS_SESSION_EXPIRATION |
Bedrock session expiration | Read by offline preflight |
AWS_CREDENTIAL_EXPIRATION |
Bedrock fallback credential expiration | Read by offline preflight |
GOOGLE_APPLICATION_CREDENTIALS_TOKEN_EXPIRY |
Vertex token expiration | Read by offline preflight |
AZURE_TOKEN_EXPIRES_ON |
Azure OpenAI token expiration | Read by offline preflight |
Secrets passed into an agent container are emitted as valueless -e arguments
using only the variable name, so secret values do not appear in the container
argv. MCP configuration values may expand exported environment variables into
a temporary JSON file. Redacted values and references to variables absent from
the codeprobe process environment are rejected before any agent starts. The
temporary file can contain secrets in cleartext until cleanup succeeds;
codeprobe purge also sweeps stale codeprobe-mcp-*.json files.
Run the offline preflight directly:
codeprobe check-infra offline --jsonOr run with the preflight wired into codeprobe run:
codeprobe run . --offline --offline-expected-run-duration 1hHost subprocess execution passes these proxy variables when present:
HTTP_PROXY, HTTPS_PROXY, NO_PROXY, ALL_PROXY, http_proxy,
https_proxy, no_proxy, and all_proxy.
The same proxy URL variables are forwarded into the agent container. Private CA
host-path variables are whitelisted for host subprocess execution but excluded
from valueless container passthrough: SSL_CERT_FILE, SSL_CERT_DIR,
REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, and NODE_EXTRA_CA_CERTS.
During agent-container preparation, CodeProbe validates private CA files and
directories, resolves and deduplicates their host paths, mounts them read-only
under /etc/codeprobe/ca, and rewrites the container environment values to the
collision-safe container paths. Invalid or unreadable paths are not mounted;
codeprobe doctor reports the selected agent's invalid CA configuration before
the run. These runtime mounts do not configure the container engine itself:
registry pulls and bootstrap still use the operator-controlled engine trust
store.
codeprobe run --offline performs a credential TTL preflight and then sets
CODEPROBE_OFFLINE=1. Network-touching Python subsystems that call
guard_offline fail loud with OFFLINE_NET_ATTEMPT.
There is no socket-level interception. The offline guard is opt-in at known
network call sites; it does not monkeypatch sockets or block egress from
external binaries. Agent processes own their network behavior. Scoring
containers still use --network=none when the scoring image is available.
trace.db stores agent lifecycle events under
.codeprobe/<experiment>/runs/trace.db. Tool inputs and outputs are redacted
before insertion by src/codeprobe/trace/content_policy.py:
- exact live environment values of length at least eight become
[REDACTED-ENV]; - authorization and token-shaped strings become
[REDACTED-AUTH]; and - user-supplied
--trace-denyglobs can replace matching tool outputs with[REDACTED-GLOB].
Agent transcripts under .codeprobe/<experiment>/runs/<config>/<task>/ receive
secret-token and auth-pattern redaction only. Source code printed by the agent
is not redacted.
Application logs are stdout and stderr from the CLI process. JSON output, terminal transcripts, shell history, CI logs, and container engine logs are operator-managed and can contain paths, diagnostics, command lines, and fragments of verifier output. CodeProbe does not provide a central log store or log-retention policy.
Run artifacts are local, retained until the operator deletes them, and may
contain proprietary source in cleartext. CodeProbe does not encrypt local run
artifacts at rest. The v1 control is operator-managed encrypted storage for
the workspace, CI runner, and artifact volume, plus codeprobe purge
retention enforcement.
Deletion responsibilities:
| Artifact | Delete with | Notes |
|---|---|---|
.codeprobe/ |
Operator filesystem deletion or codeprobe purge . --all --yes |
Whole experiment directory removal. |
.codeprobe/<experiment>/runs/ |
codeprobe purge . --yes |
Removes transcripts, checkpoints, and trace storage for each experiment. |
.codeprobe/<experiment>/runs/trace.db |
codeprobe purge . --yes |
Contains redacted trace rows, but source snippets are possible when a tool output is not covered by a redaction rule. |
.codeprobe/<experiment>/runs/<config>/<task>/ |
codeprobe purge . --yes |
Contains task transcripts such as agent_output.txt and agent_error.txt. |
codeprobe-mcp-*.json |
codeprobe purge . --yes |
Swept from the system temp directory when it is a regular file and not a symlink. |
| Task worktrees | Operator temp/worktree cleanup | Created outside .codeprobe/; purge does not delete them. |
| Per-slot agent session directories | Operator temp/session cleanup | Includes per-slot CLAUDE_CONFIG_DIR contents when session isolation created them, including private credential hardlinks or copies outside .codeprobe/ result artifacts. |
| Scoring temp directories | Operator temp cleanup | Purge does not delete scoring temp directories outside .codeprobe/. |
SNAPSHOT_DIR |
Operator filesystem deletion | Snapshot output is outside .codeprobe/ unless the operator places it there. |
evidence |
Operator filesystem deletion | Evidence bundle output is outside .codeprobe/ unless the operator places it there. |
| Export directories | Operator filesystem deletion | Includes observability and spreadsheet exports. |
| CI logs, terminal transcripts, shell history, and backups | Operator platform controls | Purge cannot delete records retained by CI, backup, shell, or terminal systems. |
codeprobe purge does not delete snapshots, evidence bundles, export
directories, task worktrees, per-slot agent session directories, scoring temp
directories, CI logs, terminal transcripts, shell history, or backups.
Use the purge command as the retention lever:
codeprobe purge .
codeprobe purge . --yes
codeprobe purge . --older-than 30 --yes
codeprobe purge . --all --yescodeprobe purge lists candidates by default. With --yes, it deletes
.codeprobe/ run artifacts, or whole experiment directories when --all is
passed, plus stale codeprobe-mcp-*.json temp files. It never touches your
source tree and never runs git.
Operators own backup policy. If .codeprobe/, worktree temp directories,
snapshot outputs, or evidence bundles are included in endpoint backup or CI
artifact backup, those systems become part of the retention boundary.
The default shareable snapshot is hashes-only:
codeprobe snapshot create EXPERIMENT_DIR --out SNAPSHOT_DIR --redact hashes-only
codeprobe snapshot verify SNAPSHOT_DIRhashes-only snapshots include paths, sizes, hashes, and attestation metadata,
but no file bodies. Content-bearing modes require
--allow-source-in-export; see docs/SNAPSHOT_REDACTION.md.
Zero-code-access evidence bundles are stricter than snapshots. They export a fixed five-file bundle that excludes file names, file sizes, prompts, patches, traces, task-level results, raw diagnostics, and free-form identifying text:
codeprobe snapshot evidence preview request.json --no-json
codeprobe snapshot evidence export request.json --out evidence --approve sha256:DIGEST --no-json
codeprobe snapshot evidence validate evidence --expect sha256:DIGEST --no-jsonObservability and spreadsheet exporters are local transforms. The operator is responsible for reviewing generated files before uploading them to any external system.
Operator responsibilities:
- run CodeProbe in a contained or dedicated environment;
- manage encrypted storage for local artifacts;
- set retention windows and run
codeprobe purge; - rotate any credential exposed through prompts, transcripts, traces, temp MCP config files, snapshots, logs, or exported artifacts;
- preserve relevant
.codeprobe/artifacts only when needed for forensics; and - review generated export files before transmission.
CodeProbe maintainer responsibilities:
- fix defects in containment, redaction, deletion, or export code;
- correct documentation that overstates implemented controls;
- add drift tests when a documented security claim becomes machine-checkable; and
- publish security fixes for supported versions under
SECURITY.md.
If a secret may have been written to local artifacts, treat the artifact volume, CI logs, terminal transcripts, snapshots, and backups as possible exposure locations. Rotate first, then purge or quarantine affected files according to the operator's incident process.