Source index · Technical reference · Home

UNRELEASED DEVELOPMENT SNAPSHOT · READ-ONLY EXCERPT

hooks/shared/customer-data-block/run.sh

This is the cited technical source at local revision 275a354, inspected on 22 September 2026. It differs from the public release. This reference publishes only the cited sections, not an installable release or the development branch.

Line numbers refer to the complete recorded file. Uncited lines are omitted. Full-file SHA-256: 09b545223e4b22abaf5c5aaec4f0ee203daf45962e54a3b9558bc4eba7ff39e6.

1#!/usr/bin/env bash
2# customer-data-block — Lintel JUSTIFIED-BLOCK hook
3# Blocks git commit/push if a customer-data pattern is in staged content.
5# NOT `set -e` (issue I1 / claude-code #60490): under -e an upstream grep/tr
6# returning non-zero would exit this script BEFORE the blocking `exit 2`, and
7# Claude Code treats any non-2 exit as NON-blocking — the secret commits through.
8# Explicit exits only (0 = allow, 2 = block); -u/pipefail kept for correctness.
9set -uo pipefail
11source "$(dirname "${BASH_SOURCE[0]}")/../_input.sh"
12CMD="$(hook_input command "${1:-}")"
13[ -z "$CMD" ] && exit 0
15# Flatten before matching — line-continuation + newline-forged override are the
16# L-012 class; rationale in secret-scan-block/run.sh (the sibling gate).
… omitted uncited lines …
19LINTEL_HOME="${LINTEL_HOME:-$HOME/.lintel}"
20mkdir -p "$LINTEL_HOME/audit"
22# Unified audit writer (hooks/shared/<name>/ → repo-root → bin/). Idempotent source.
23command -v audit_log >/dev/null 2>&1 || source "$(dirname "${BASH_SOURCE[0]}")/../../../bin/_audit.sh"
24# Shared customer-PII patterns (defined once in _patterns.sh).
25source "$(dirname "${BASH_SOURCE[0]}")/../_patterns.sh"
27# Fire on any git commit/push however phrased (battletest K2 — the `^git` anchor
28# was bypassed by `git -C`, abs paths, `&&` chains).
29if ! printf '%s' "$CMD_FLAT" | grep -qE '(^|[^A-Za-z0-9_-])git([[:space:]]|$).*\b(commit|push)\b'; then
30 exit 0
31fi
33# Override FIRST so it always audits (battletest H8). Honor env OR command-string token.
34# Override via env OR LEADING env-assignment prefix only — never a -m message (review P0).
35if [ "${LINTEL_OVERRIDE_CUSTOMER_DATA:-}" = "1" ] || printf '%s' "$CMD_FLAT" | grep -qE '^[[:space:]]*([A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*[[:space:]]+)*LINTEL_OVERRIDE_CUSTOMER_DATA=1([[:space:]]|=|$)'; then
36 reason="${LINTEL_OVERRIDE_REASON:-no-reason-given}"
37 audit_log "hooks" "customer_data_block" "hook=customer-data-block" "tier=OVERRIDDEN" "override=true" "reason=$reason" "blocked=false"
38 echo "INFO [Lintel hook]: customer-data-block OVERRIDDEN (reason: $reason). Audit-logged."
39 exit 0
40fi
42# Added lines from staged + unstaged-tracked diffs, cwd + every `git -C`
43# target in the command (helper in ../_input.sh — rationale there).