Some things it is not allowed to do, and we show you where that holds.

A policy file the agent cannot read or write, built-in deny rules for secrets and destructive commands, credential redaction, an OS sandbox where one is available, and a hash-chained audit log. Enforced at Warding's own gate. Unaudited by a third party. Here is exactly what is covered, what isn't, and what is still in development.

The charter

Four articles. Each one names the mechanism that holds it, and the scope table below says where each mechanism stops.

Article 1. The agent cannot read or write its own policy.

The keystone is our word for one deny list: the secret and policy paths the agent is refused, at read and at write. It is security._SENSITIVE_HOME_DIRS in the source. The policy, its profiles, and the admission and computer-use files sit on it, so no setting the agent can reach turns the ceiling off.

Warding's PreToolUse gate checks every file tool call against that list, and the shell-command matchers cover the read verbs (cat, head, base64, a python open()), the write verbs (redirection, cp, mv) and the extract verbs (tar -C, unzip -d) aimed at those paths. The audit log and its signing key are on the list too.

Under the data home

  • ~/.junction/security_policy.json
  • ~/.junction/profiles/
  • ~/.junction/admission_policy.json
  • ~/.junction/computer_use.json
  • ~/.junction/denied_commands.json
  • ~/.junction/.env
  • ~/.junction/trust/
  • ~/.junction/security_events.jsonl

Under your home directory

  • ~/.ssh
  • ~/.aws
  • ~/.gnupg
  • ~/.gpg
  • ~/.config/gcloud
  • ~/.azure
  • ~/.docker/config.json
  • ~/.kube/config
  • ~/.npmrc
  • ~/.pypirc
  • ~/.netrc
  • ~/.git-credentials
  • … and the kiro-cli auth stores

Article 2. Secrets are redacted before they reach the log.

Tool output passes one redaction chokepoint before anything is written or shown. It is always on; there is no policy key to turn it off. It matches credential shapes, including base64-encoded copies of them, and replaces each with [REDACTED: credential].

Redaction is pattern-based. A secret with no recognisable shape, such as a plain password in a config file, is not caught by it; that is what the keystone and the sandbox are for.

Shapes it recognises (excerpt)

  • AWS access key ids (AKIA… / ASIA…) and aws_secret_access_key / aws_session_token values
  • PEM private-key blocks, including encrypted and truncated ones
  • GitHub, GitLab, npm and PyPI tokens
  • Slack and Telegram bot tokens
  • Stripe, SendGrid, OpenAI and Anthropic API keys
  • database connection URLs with a password in them

Article 3. Tool decisions are appended to a hash-chained audit log you can verify.

The Security Event Log is append-only JSONL in the data home. Each entry carries an HMAC-SHA256 over the one before it, so an edited line breaks the chain at that line. The signing key lives in trust/, outside the log's directory, so something that can rewrite the log cannot also re-sign it.

The live log rotates at 32 MiB into independent segments, seven kept; each new log opens with a rotation record naming the closed segment's last hash. Retention is a fixed 365 days.

What an entry records

timestamp · caller · source · operation
tool_kind · outcome · resources (redacted)
prev_hash  entry_hash

Article 4. Anything not granted by both the policy and the profile is denied.

The policy is the ceiling; a profile narrows it for one surface, app or task (a cron job, a chat channel, a subagent). The effective permission is their intersection, tightest wins, and Warding's own gate enforces it even when the agent's config granted the tool. A profile file that fails to parse becomes deny-all, never the ceiling.

Next to it sit the built-in denied-command rules, grouped by category and enforced at the same gate. List them with warding security deny-list.

effective = POLICY ∩ PROFILE
# denied unless both grant it

Denied-command categories

  • aws-destructive
  • sensitive-file-read
  • credential-exfil
  • local-destructive
  • self-protection
  • git-publish
  • iac-teardown
  • sql
  • pipe-to-shell
  • reverse-shell
Render my charter · in development

warding charter in development : one page with your effective policy, profile by profile. Until it ships, warding policy show prints the active policy and the rule categories.

Plate I. The posture page
Capture pending: this plate will hold a real screenshot with its harness and date in the frame.

Plate I. The posture page — Dashboard · capture pending · 2026-10-07 · no agent connected

Scope: what is enforced where

"Fails closed" means that when the control cannot decide, the call is refused. "Fails open" means it is allowed. Both are listed.

ControlWhereFails
Keystone paths Warding's PreToolUse gate, for file tools and for read, write and extract verbs in shell commands. The OS sandbox also hides credential directories: ~/.gnupg, ~/.config/gcloud, ~/.azure and ~/.docker in every tier, ~/.aws and ~/.kube in the stricter tiers. Closed
Denied commands PreToolUse gate Closed
POLICY ∩ PROFILE for tools and MCP calls PreToolUse gate Mixed closed for denied calls; open for tools the harness pre-authorised (a pre-authorised tool can skip the hook)
Computer use in band on the tool dispatch path, never at the hook Closed closed; off by default; one operator opt-in on the keystone file
App manifest permissions advisory today Open open on an empty allowlist
Admission policy fleet seam Open an absent policy admits (the public edition ships none)
Owner lock on channels messaging identity Open no-op until JUNCTION_OWNER_ID is set
Credential redaction one chokepoint before the log Closed always on, no policy key
Audit write on nested sandbox passthrough best effort Open logs loudly and proceeds (the child stays inside the outer sandbox)

If you rely on a control that reads "open" here, do not run unattended. We list these so you don't have to find them.

Sandbox status by OS

The sandbox wraps each agent process. With no backend and the sandbox not switched off, it refuses to spawn rather than run unconfined.

  • Linux with unprivileged user namespaces

    Sandboxed

    A user namespace plus a mount namespace; sensitive directories are bind-mounted empty. The child keeps your UID, so toolchains work.

  • Ubuntu 23.10 and newer

    Fails closed

    The default AppArmor setting blocks the mount namespace. Run warding service install: it asks for sudo and installs a narrow profile that grants only userns, attached to the service by systemd. A gateway started by hand stays unconfined, so it refuses to spawn.

  • Containers without user namespaces

    Fails closed

    Usually the container's own seccomp filter denies unshare. Nothing spawns until you fix that or opt in.

  • macOS (Seatbelt)

    Sandboxed

    sandbox-exec with a generated profile, including macOS 26. Availability is probed empirically at runtime, not gated on a version number.

  • Windows

    Fails closed

    There is no sandbox backend of ours, so agent processes refuse to start until you opt in. A reviewed kiro-cli spawn uses kiro-cli's own sandbox instead.

Opting in: agent.sandbox_allow_unsandboxed_exec lets agents run without a sandbox on a host that has none. It prints a loud warning and the decision lands in the log. warding setup asks about it, default no, when it finds no backend.

Break the charter

In development

A public, reproducible script that tries to read or rewrite the policy through the usual doors (read, write, sed, symlink, hardlink, archive extract, python -c open(), redirection, mv over, chmod) and shows the refusal for each. It is in preparation. There is no script to run yet and no reward on offer. Until then, report what you find through the process below.

Verify the log

warding security verify checks the chain today: it reports how many entries verify, how many were tampered with, and says so plainly when a rotated segment could not be checked.

What a green chain will mean: nothing without the key edited the log after the fact. What it will not mean: that every action was logged. The nested-sandbox passthrough row in the scope table is a case where a failed write logs loudly and carries on.

Some things never reach your phone

A built-in deny rule refuses a call before any human is asked. At 03:05 the agent tries git push origin main; the git-publish rule refuses it at the gate, no Approve button is sent, and one line lands in the log:

Refused · built-in rule · 03:05:41
{
  "event_id": "6c1d0e9a7f3b2a54",
  "timestamp": "2026-09-27T03:05:41.208113+00:00",
  "event_type": "tool_invocation",
  "caller_identity": "acp:3f2a9c…",
  "agent": "junction",
  "source": "acp",
  "operation": "execute_bash",
  "tool_kind": "execute",
  "outcome": "denied",
  "resources": "git push origin main",
  "error": "denied command (git-publish)",
  "prev_hash": "b71e42…",
  "entry_hash": "9f2c8d…"
}

The fields are the log's real ones (SecurityEvent in sel.py); the values are illustrative. agent reads junction, the package's internal name.

What does reach your phone, per chat app

Report a vulnerability

Please don't post vulnerabilities in public issues. A publicly accessible private reporting channel is pending with source publication. No response-time commitment is verified for this beta.

Third-party services such as model providers are out of scope. Read the source status and the scope statement above. A reporting channel must be established before a public source launch.

What we don't claim.

  • Chat runs the one harness you choose. Sending a spawned subagent to another installed harness is registered and unit-tested, not verified at runtime; the router picks a harness and forwards no provider traffic.
  • The model catalog lists names; it forwards nothing and holds no keys.
  • Approve buttons on five chat apps; WhatsApp is typed; four apps are chat-only.
  • Cron and subagents from chat, and the agent's mid-turn questions, work on kiro-cli today; on other harnesses create jobs and spawn subagents from the dashboard or CLI, and the agent cannot ask you a question mid-turn.
  • The OS sandbox fails closed — it refuses to run rather than run unconfined — on Windows, in containers without user namespaces, and on Ubuntu ≥ 23.10 until warding service install adds its AppArmor profile (it asks for sudo); you can opt in to unsandboxed execution with a loud warning.
  • Unaudited by a third party. Single owner. No hosted service. No signed installers yet.
  • Your vendor's terms and any future metering of unattended use apply and may change.
  • The default build contacts no server of ours. One address inherited from the upstream codebase remains: the embedding model is fetched from it on first embedding use, checked against a pinned hash. The lsof run: /verified.

Security reporting status: Publication and reporting limits.

Last checked against the code on 2026-09-30.

Review the local beta.

Apache-2.0 source publication is pending. Read the setup notes and verification limits.

Source publication pending

Public source, install commands and downloads are not available yet. A clean install and live workflow are not yet verified.

Source status Read beta notes