Skip to content

Security

Protected credential files, permission rules, the audit log, the Linux shell sandbox, the advisor and OpenTelemetry export.

hordecode has several controls over what the agent can read, run and record. This page lists each one and what it covers.


Protected credential files

hordecode protects auth.json and mcp-auth.json in the hordecode data directory. A deny rule for these files is added last to every agent ruleset, so no user or session allow rule overrides it.

The protection matches the literal path, the symlink target and hard links to the file. The shell tool and the external-directory check both call the protected-path check.

The data directory is also a protected root, and a sandbox grant does not overlap it.


Permissions

Each permission rule resolves to "allow", "ask" or "deny". Rule patterns use glob matching: * matches zero or more characters and ? matches exactly one. The last matching rule wins. When no rule matches, the action asks.

hordecode.json
{
"$schema": "https://hordecode.com/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"rm *": "deny"
}
}
}

By default, reading a file that matches *.env or *.env.* asks for approval. Files matching *.env.example are allowed. See Permissions for every permission key and its defaults.


Permission audit log

The audit log is opt-in. Set HORDECODE_PERMISSION_AUDIT=1, or enable the permission_audit switch.

Terminal window
export HORDECODE_PERMISSION_AUDIT=1

Permission decisions and replies are written as one JSON line each to <data>/log/permission.jsonl. Each line records the permission, its patterns, the outcome, and prev, the SHA-256 hash of the previous line. The chain continues across rotated files.

  • The log records permission patterns only. Key-value secrets such as passwords, tokens and API keys are redacted from those patterns, along with Bearer and Basic tokens and URL user info.
  • The file rotates at 5 MiB and keeps three older files. Set HORDECODE_PERMISSION_AUDIT_MAX_BYTES to change the size limit.

To check the chain, run:

Terminal window
horde debug audit-verify

When the chain holds, the command prints ok with file, line and legacy-line counts. When it finds a break, it prints the file and line and exits with code 1. It also exits with code 1 when no log is found.

The chain is a local integrity check without a secret key. Someone who can write the log can rewrite the whole chain consistently, so keep the log where only you can write it.


Shell sandbox on Linux

On Linux, the shell sandbox runs commands under bubblewrap with no network. The network is shared with the host only when HORDECODE_SANDBOX_NETWORK is set to host.

Only the paths the sandbox lists are mounted. The project worktree and an approved external directory are mounted read-write, and system directories such as /usr and /etc are mounted read-only. The sandbox applies to the shell tool.

The sandbox is off by default. Enable it with the HORDECODE_SANDBOX environment variable:

Terminal window
export HORDECODE_SANDBOX=auto

The modes are off, auto and required. In required mode, commands run only inside the sandbox.

You can also enable it with the experimental switch. Setting experimental.switches.sandbox to true sets the mode to auto. Set this in your global config.

hordecode.json
{
"$schema": "https://hordecode.com/config.json",
"experimental": {
"switches": {
"sandbox": true
}
}
}

Advisor

The advisor is an optional second-model review of risky steps. Configure it under experimental.advisor. Set enabled to true and name a model; both are required. The advisor is off by default.

It runs in primary sessions. Each review has a 60-second timeout, and it returns notes only, without tool access. A review returns at most four notes.

The advisor is triggered by four counters, each of which can be set to 0 to turn it off:

  • files_touched: distinct file paths touched by file tools in the current turn.
  • tool_failures: tool errors, or shell commands that exit with a non-zero status.
  • same_error: repeats of the same error.
  • context_percent: percentage of the model context window in use.

OpenTelemetry

hordecode exports telemetry with the standard OTEL_EXPORTER_OTLP_* environment variables, including OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_ENDPOINT and OTEL_EXPORTER_OTLP_HEADERS, along with OTEL_RESOURCE_ATTRIBUTES. Setting OTEL_SDK_DISABLED=true turns every signal off.

Nothing is exported without an endpoint. Metrics, traces and logs are each exported only when an endpoint for that signal exists.

Setting experimental.openTelemetry to true turns on telemetry spans for model calls.

When experimental.openTelemetry is on, spans can include prompt text, so send them to an endpoint you trust.