#!/usr/bin/env bash # PreToolUse guard: never write infra/deploy/secrets/*.yaml directly. # # Every file matching that glob is SOPS-encrypted, and secrets-guard.yml fails the # build if one is not. This is the same rule enforced one step earlier: a direct # Write or Edit produces plaintext, and by the time CI catches it the secret has # already been written to disk and probably committed. # # The supported path is `sops edit `, which decrypts to a temp file, opens an # editor and re-encrypts on save — the plaintext never touches the working tree. # # Denies rather than asks: there is no legitimate reason to hand-write one of these, # so a prompt would only be an invitation to click through. set -uo pipefail payload=$(cat) command -v jq >/dev/null 2>&1 || exit 0 path=$(printf '%s' "$payload" | jq -r '.tool_input.file_path // ""') [ -n "$path" ] || exit 0 case "$path" in */infra/deploy/secrets/*.yaml) jq -n --arg p "$path" '{ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: ("Refusing to write \($p) directly — every file under infra/deploy/secrets/ is SOPS-encrypted and a direct write would land plaintext. Use `sops edit \($p)` instead, which re-encrypts on save. (secrets-guard.yml would fail the build on this anyway, but only after the secret was already on disk.)") } }' exit 0 ;; *) exit 0 ;; esac