hook

package
v0.9.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package hook installs and manages integration hooks for Envault: the Git pre-commit hook (git.go), the Claude Code PreToolUse hook (claude.go), and the PreToolUse request handler that blocks sensitive commands (preuse.go). Secret detection rules live in the sibling package internal/scan.

Index

Constants

This section is empty.

Variables

View Source
var ErrBlockToolCall = fmt.Errorf("tool call blocked by envault hook")

ErrBlockToolCall is returned by RunHookPreuse when the tool call must be blocked. The caller must exit non-zero so Claude Code denies the tool call — any text already written to the output writer is shown to Claude as the reason.

Functions

func InstallGitHook

func InstallGitHook(repoRoot string) error

InstallGitHook installs the Envault pre-commit hook in the Git repo at repoRoot.

  • If no pre-commit hook exists, a new one is created with a #!/bin/sh shebang.
  • If one exists, the Envault block is appended after the existing content.
  • If the Envault block is already present, the call is a no-op.

The resulting file is always made executable (0755).

func IsEnvaultDir

func IsEnvaultDir(root string) bool

IsEnvaultDir returns true when .envault/ exists under root.

func IsGitHookInstalled

func IsGitHookInstalled(repoRoot string) bool

IsGitHookInstalled reports whether the Envault block is present in the pre-commit hook for the Git repo at repoRoot.

func IsSensitiveEnvaultCmd

func IsSensitiveEnvaultCmd(cmd string) bool

IsSensitiveEnvaultCmd reports whether cmd invokes `envault cat` or `envault export` as the primary command (not as an argument to another tool) without the --force override flag.

func IsSensitiveEnvaultWriteCmd added in v0.9.4

func IsSensitiveEnvaultWriteCmd(cmd string) bool

IsSensitiveEnvaultWriteCmd reports whether cmd invokes `envault add` or `envault set` as the primary command without the --force override flag. Unlike a plain read, sealing a value this way requires the plaintext to already be embedded in the command text (no interactive stdin over a tool call), so it is blocked the same way as a direct plaintext read.

func RunHookPostuse

func RunHookPostuse(r io.Reader, w io.Writer) error

RunHookPostuse reads Claude Code's PostToolUse JSON from r.

If the current user's private key is available — via the key-unlock agent (internal/agent; no passphrase needed, see envault agent unlock) or, failing that, ENVAULT_PASSPHRASE — decrypts all KindEnv vault secrets and scans the tool response for their plaintext values (and base64-encoded variants), replacing each match with a structured placeholder `<ENVAULT:NAME>` (or `<ENVAULT:NAME|base64>`) before writing to w and exiting with code 2 so Claude Code uses the masked output instead of the original.

When neither key source is available, or the vault is absent, the function returns nil (pass-through), logging the skip to the audit log.

func RunHookPreuse

func RunHookPreuse(r io.Reader, w io.Writer) error

RunHookPreuse reads Claude Code's PreToolUse JSON from r.

Blocking rules (in priority order):

  1. Read/Write/Edit/NotebookEdit tools whose file_path matches a protected pattern.
  2. Bash commands that reference a protected path (best-effort heuristic; full adversarial coverage is in v0.8.4).
  3. Bash commands that invoke `envault cat` or `envault export` without --force.

Each blocked call is appended to the audit log (.envault/ai-secure.log). Returns ErrBlockToolCall when a call is denied; nil otherwise.

func UninstallGitHook

func UninstallGitHook(repoRoot string) error

UninstallGitHook removes the Envault block from the pre-commit hook at repoRoot. If the file would be empty (or contain only a shebang) after removal, it is deleted to fully restore the prior state. Returns nil if the hook was not installed.

Types

type PostuseInput

type PostuseInput struct {
	ToolName     string          `json:"tool_name"`
	ToolInput    json.RawMessage `json:"tool_input"`
	ToolResponse json.RawMessage `json:"tool_response"`
}

PostuseInput is the Claude Code PostToolUse hook JSON.

type PreuseInput

type PreuseInput struct {
	ToolName  string                 `json:"tool_name"`
	ToolInput map[string]interface{} `json:"tool_input"`
}

PreuseInput is the subset of the Claude Code PreToolUse hook JSON we care about.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL