Skip to content

zn-gate 1.8.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 12:31
· 330 commits to main since this release

zn-gate 1.8.0 adds Warn rules for zn Team: an organization can have a secret use go ahead with a notice and an audit record instead of blocking it. Organization policy now also applies to secrets_render_file and to marker restores in the agent hooks. zn-gate shield pins the tools of the MCP servers it wraps, and block messages are written in plain words.

After updating, run zn unlock once. A vault that is still running from an older version keeps secrets as markers and tokens in the agent hooks until it is restarted; zn unlock restarts it.

Going back to 1.7.1 in a zn Team organization with Warn rules: an organization policy with warn rules stored by 1.8.0 is refused by 1.7.1, which then applies only your local settings until the next policy sync downloads a copy it can read. Stay on 1.8.0 or later in such an organization.

Added

  • Codex plugin layout: plugins/tools/check-plugins.js now checks the root manifest's extensions.com.openai.hooks path and the repository marketplace entry against OpenAI's Codex plugin documentation.
  • MCP tool pinning: zn-gate shield records a hash of each tool of a wrapped server (the whole tool definition) from the first tool list it sees for that server (all its pages), and compares every later list with it. By default a tool that is new or changed since gets a notice at the start of its description that tells the model to ask you first, and the shield writes a warning; tools with a duplicated or invalid name are refused. With "mcpPinning": "block" in ~/.zn/config.json (or ZN_MCP_PINNING=block) such tools are removed and calls to any tool that is not approved are refused. Only your own ~/.zn/config.json can make the mode weaker than warn; the environment of an MCP server can only make it stricter. zn-gate pins lists the servers and what changed; zn-gate pins approve <server> accepts the changes, only in an interactive terminal, and the agent hooks refuse it from an agent. Pins are kept in ~/.zn/mcp-pins/ (the program, its arguments with secrets redacted, tool names and hashes). Limits: pinning covers tool definitions, not the server's code; the first list of a server is trusted, and so is the first list after its command line changes (for example a new package version); approving accepts the tools as they are listed then (the pins hold names and hashes, not the tool text); an agent that can run code on your machine can edit the pins or start a server without the shield, and the hooks only stop the commands they recognise (POLICY_RULES_VERSION is now 2026-10-15.13).
  • CI: a Public facts check fails a pull request when the release version, the agents with hooks, the license or the install command differ between the package and plugin manifests, the MCP Registry files and the pinned versions in the documentation (.github/public-facts.json).
  • zn Team: a policy rule can warn instead of block ("warn": true). The use goes ahead, an audit record with the decision warn is written and uploaded to your organization, and you and the agent see zn: your team policy would block <NAME> here (policy note: "<reason>"). It was allowed and recorded for your organization. It applies wherever a block applies (zn run, secrets_http_request, secrets_render_file); a rule with both deny and warn makes the policy invalid. zn-gate now sends X-ZN-Policy-Features: warn when it downloads the policy, so the server sends warn rules only to versions that understand them. The OpenTelemetry export maps warn to severity WARN.

Changed

  • Block messages in plain words. When zn cannot read a credential file for the agent, the message names the file, says why and how to use the value instead (zn secret set NAME, then __ZN_NAME__ in the command). A secret used in the wrong place of a shell command gets one short explanation and an example. When a command is not allowed to use a secret, zn run says so and gives the command to allow it. When the hook itself fails, the agent reads that the action was blocked and, if it happens again, to ask you to run zn hooks install, followed by the error detail. The text that replaces a tool output with instructions aimed at the agent now tells the agent not to act on it and to tell you.
  • Block messages in plain words, second batch. PowerShell refusals, MCP and Monitor notices, and the notes on commands with secret placeholders now say what happened and give one next step. Errors a person reads gain a specific next step where they are raised, written for a person first and for an agent second; the "Not allowed" and "Not found" prefixes are unchanged. The Python guard returns one message with the reason and a next step: a blocked input says not to retry with reworded text, and a blocked tool result says not to use that result. The Python block text no longer shows the confidence value; read the rule and reason from the exception's assessment attribute. The default CrewAI fallback text changed: pass fallback= to keep a fixed string. (POLICY_RULES_VERSION is now 2026-10-15.14.)
  • Python 3.8 and 3.9 are no longer supported (both are past their end of life); pip on those versions keeps installing zn-gate 1.7.1.
  • When an MCP call is too large for zn to check (arguments over 1 MB), the message now tells the agent to tell you and not to resend the content in parts.

Fixed

  • zn Team: secrets_render_file now applies an organization deny. Before, a file mode secret blocked by the organization policy could still be written to a file through this tool.
  • Plugin repository checks: the Verify workflow no longer stops without a message on a release pull request (the comparison of the two trees ended the step under pipefail).

Security

  • A value the scrubber replaced with a token is not put back when it is also a stored secret that the organization's policy blocks. When the vault process was started by an older zn-gate, the hooks keep tokens as they are instead of restoring them and say so to you and the agent; zn unlock now restarts such a vault, and zn vault status shows the running vault's zn-gate version and flags an outdated one.
  • Marker restores in the agent hooks now apply the organization's policy. When an agent writes a __ZN_NAME__ marker into a git-ignored file, a secret the zn Team policy blocks stays a marker and the hook says why; a secret under a warn rule is restored, recorded with the decision warn, and the hook's message shows the warning.
  • When an event cannot be read or part of zn-gate is missing, the message the agent reads no longer says how to let actions pass unchecked (hooks.whenUnavailable). That setting is still documented and is shown only to you (as the hook's message to the user in Claude Code).
  • When an agent event is not valid JSON, the refusal no longer quotes the part of it that Node's parser shows, which could be tool output.
  • The agent hooks again refuse zn admin commands written with a Windows path or .cmd (for example C:\Users\me\AppData\Roaming\npm\zn.cmd secret reveal NAME or .\zn.cmd hooks uninstall).
  • Shell, PowerShell and Monitor commands over 100 KB are blocked instead of checked. Checking a command that long could take longer than the agent waits for the hook, and a hook that times out lets the command run unchecked. The message tells the agent to tell you and not to resend the command in parts (POLICY_RULES_VERSION is now 2026-10-15.15).
  • zn Team: a warn rule now also applies when the agent hooks put back a value the scrubber replaced with a token and that value is a stored secret under the rule: you and the agent see the notice, and the audit record has the decision warn.

How to verify these files: docs/verify-release.md