Skip to content

v1.3.3: Unsafe tool calls are denied before they run

Choose a tag to compare

@fidpa fidpa released this 16 Aug 22:17
· 3 commits to main since this release

Security

  • An unsafe tool call is now prevented, not merely reported after the fact. A
    PreToolUse hook (buildSafetyHook() in src/security.ts) runs checkToolCallSafety()
    before the call executes and denies it with permissionDecision: "deny", which resolves
    before canUseTool and is therefore not overridden by
    permissionMode: "bypassPermissions". This covers the command blocklist (Layers 5/6),
    file and search path validation (Layer 7) and the ALLOWED_TOOLS / DISALLOWED_TOOLS
    lists, and it fires inside sub-agents as well (HookInput.agent_id). 1.3.0 named this as
    the missing piece and deferred it as its own change; this is that change. The hook fails
    closed: anything thrown inside the callback still denies
  • The layer count stays at 24. Nothing new is defended here. The same four checks now
    act where they previously only observed, and inventing a Layer 25 for a relocated
    enforcement point would overstate what changed. docs/SECURITY_AUDIT_REPORT.md is a dated
    document and is left untouched

Fixed

  • A blocked tool call no longer costs the user the whole answer. The stream check threw,
    which aborted the query: the user asked a question, the model reached for a route it was
    not allowed to take, and no answer ever arrived, with only the generic error to show for
    it. The denial now goes back to the model as a tool result and it picks another route. The
    stream check reports and continues. Measured against SDK 0.3.233, the tool_use block
    reaches the output stream before the hook fires, so the stream check cannot serve as a
    fallback and must not throw; prevention lives in the hook alone
  • The 1.3.2 release stopped after the tag, leaving the version and the changelog behind.
    package.json still read 1.3.1 after the 1.3.2 release, and CHANGELOG.md had no
    [1.3.2] section: its entries were left under [Unreleased]. The section has been written
    from the 1.3.2 commit and the version now reads 1.3.3. The v1.3.2 tag itself was never
    pushed and is published unchanged rather than moved; the package.json it carries still
    says 1.3.1, which cannot be corrected without rewriting history. Same failure mode as the
    drift that 1.2.0 had to clean up
  • Three documents described tool-call checking as it behaved before this release. They
    asserted that it "reports, it does not prevent" and that no hook was installed: README.md
    (Tool Control), SECURITY.md (bypass mode) and docs/security-limitations.md
    (limitation 4, now marked closed and kept in the list rather than deleted, as limitation 8
    was in 1.3.1)
  • src/session.ts had crossed the 800-line limit that CONTRIBUTING.md sets. It stood
    at 806 lines, because the new comment block duplicated the one it replaced. Condensed to
    797
  • The size claim in README.md and AGENTS.md was 200 lines short. Corrected from
    "~6,800 lines TypeScript" to ~7,000; measured across src/ and ask_user_mcp/: 7,052