diff --git a/.git-hooks/_helpers.sh b/.git-hooks/_helpers.sh new file mode 100644 index 000000000..169aa6740 --- /dev/null +++ b/.git-hooks/_helpers.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Shared helpers for git hooks. +# Sourced by .git-hooks/commit-msg, pre-commit, pre-push. +# +# Constants +# --------- +# ALLOWED_PUBLIC_KEY Real public API key shipped in socket-lib test +# fixtures. Safe to appear in commits anywhere in +# the fleet. +# FAKE_TOKEN_MARKER Substring marker used in fleet test fixtures +# (see socket-lib/test/unit/utils/fake-tokens.ts). +# FAKE_TOKEN_LEGACY Legacy lib-scoped marker — accepted during the +# rename from `socket-lib-test-fake-token` to +# `socket-test-fake-token`. Drop when socket-lib's +# fixture rename PR lands. +# SOCKET_SECURITY_ENV Env var name used in shell examples; not a token. +# +# Functions +# --------- +# filter_allowed_api_keys Reads stdin, drops allowlist matches (public +# key, fake-token markers, env var name, +# `.example` paths), prints the rest. +# +# Colors +# ------ +# RED, GREEN, YELLOW, NC + +# shellcheck disable=SC2034 # constants sourced by other hooks +ALLOWED_PUBLIC_KEY="sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api" +FAKE_TOKEN_MARKER="socket-test-fake-token" +FAKE_TOKEN_LEGACY="socket-lib-test-fake-token" +SOCKET_SECURITY_ENV="SOCKET_SECURITY_API_KEY=" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Strips lines that match the allowlist: public key, current fake-token +# marker, legacy lib-scoped marker, env-var name, or `.example` paths. +filter_allowed_api_keys() { + grep -v "$ALLOWED_PUBLIC_KEY" \ + | grep -v "$FAKE_TOKEN_MARKER" \ + | grep -v "$FAKE_TOKEN_LEGACY" \ + | grep -v "$SOCKET_SECURITY_ENV" \ + | grep -v '\.example' +} diff --git a/.git-hooks/_lib.sh b/.git-hooks/_lib.sh deleted file mode 100644 index b82771a4b..000000000 --- a/.git-hooks/_lib.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -# Shared helpers for git hooks. -# -# Keep this file minimal — only expose constants and pure filter functions -# that more than one hook needs. Per-hook logic stays in its own file. -# -# Constants -# --------- -# ALLOWED_PUBLIC_KEY — the real public API key shipped in socket-lib -# test fixtures. Safe to appear in commits. -# FAKE_TOKEN_MARKER — substring marker used in test fixtures -# (see test/unit/utils/fake-tokens.ts). Any line -# containing this string is treated as a test fixture -# by secret scanners. -# SOCKET_SECURITY_ENV — name of the env var used in shell examples; not -# a token value itself. Exempted from scanners. -# -# Functions -# --------- -# filter_allowed_sktsec — reads stdin, strips known-allowed sktsec lines -# (lines containing ALLOWED_PUBLIC_KEY, the marker, -# or the env var name). -# Colors -# ------ -# RED, GREEN, NC - -# shellcheck disable=SC2034 # constants are sourced by other hooks -ALLOWED_PUBLIC_KEY="sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api" -FAKE_TOKEN_MARKER="socket-lib-test-fake-token" -SOCKET_SECURITY_ENV="SOCKET_SECURITY_API_KEY=" - -RED='\033[0;31m' -GREEN='\033[0;32m' -NC='\033[0m' - -# Strips lines that legitimately contain sktsec_ but are not real secrets. -# Usage: echo "$text" | filter_allowed_sktsec -# grep ... | filter_allowed_sktsec -filter_allowed_sktsec() { - grep -v "$ALLOWED_PUBLIC_KEY" \ - | grep -v "$FAKE_TOKEN_MARKER" \ - | grep -v "$SOCKET_SECURITY_ENV" \ - | grep -v '\.example' -} diff --git a/.git-hooks/commit-msg b/.git-hooks/commit-msg index 0b18a8cf0..9775d4f9d 100755 --- a/.git-hooks/commit-msg +++ b/.git-hooks/commit-msg @@ -4,8 +4,8 @@ set -e -# shellcheck source=./_lib.sh -. "$(dirname "$0")/_lib.sh" +# shellcheck source=./_helpers.sh +. "$(dirname "$0")/_helpers.sh" ERRORS=0 @@ -17,7 +17,7 @@ if [ -n "$COMMITTED_FILES" ]; then for file in $COMMITTED_FILES; do if [ -f "$file" ]; then # Check for Socket API keys (except allowed). - if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | filter_allowed_sktsec | grep -q .; then + if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | filter_allowed_api_keys | grep -q .; then printf "${RED}✗ SECURITY: Potential API key detected in commit!${NC}\n" printf "File: %s\n" "$file" ERRORS=$((ERRORS + 1)) @@ -32,8 +32,25 @@ if [ -n "$COMMITTED_FILES" ]; then done fi -# Auto-strip AI attribution from commit message. +# Block Linear issue references in the commit message. +# Linear tracking lives in Linear; keep commit history tool-agnostic. +# Team keys enumerated from the Socket workspace. PATCH listed before PAT so +# the engine matches the longer prefix first on strings like "PATCH-123". COMMIT_MSG_FILE="$1" +LINEAR_TEAM_KEYS='ASK|AUTO|BOT|CE|CORE|DAT|DES|DEV|ENG|INFRA|LAB|MAR|MET|OPS|PAR|PATCH|PAT|PLAT|REA|SALES|SBOM|SEC|SMO|SUP|TES|TI|WEB' +if [ -f "$COMMIT_MSG_FILE" ]; then + LINEAR_HITS=$(grep -vE '^#' "$COMMIT_MSG_FILE" 2>/dev/null \ + | grep -oE "(^|[^A-Za-z0-9_])($LINEAR_TEAM_KEYS)-[0-9]+($|[^A-Za-z0-9_])|linear\.app/[A-Za-z0-9/_-]+" \ + | head -5 || true) + if [ -n "$LINEAR_HITS" ]; then + printf "${RED}✗ Commit message references Linear issue(s):${NC}\n" + printf '%s\n' "$LINEAR_HITS" | sed 's/^/ /' + printf "${RED}Linear tracking lives in Linear. Remove the reference from the commit message.${NC}\n" + ERRORS=$((ERRORS + 1)) + fi +fi + +# Auto-strip AI attribution from commit message. if [ -f "$COMMIT_MSG_FILE" ]; then # Create a temporary file to store the cleaned message. TEMP_FILE=$(mktemp) || { diff --git a/.git-hooks/pre-commit b/.git-hooks/pre-commit index b3e451bf1..ed7ad4c5f 100755 --- a/.git-hooks/pre-commit +++ b/.git-hooks/pre-commit @@ -4,11 +4,8 @@ set -e -# shellcheck source=./_lib.sh -. "$(dirname "$0")/_lib.sh" - -# pre-commit prints a warning color in addition to the shared RED/GREEN. -YELLOW='\033[1;33m' +# shellcheck source=./_helpers.sh +. "$(dirname "$0")/_helpers.sh" printf "${GREEN}Running Socket Security checks...${NC}\n" @@ -70,9 +67,9 @@ done printf "Checking for API keys...\n" echo "$STAGED_FILES" | while IFS= read -r file; do if [ -f "$file" ]; then - if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | filter_allowed_sktsec | grep -q .; then + if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | filter_allowed_api_keys | grep -q .; then printf "${YELLOW}⚠ WARNING: Potential API key found in: $file${NC}\n" - grep -n 'sktsec_' "$file" | filter_allowed_sktsec | head -3 + grep -n 'sktsec_' "$file" | filter_allowed_api_keys | head -3 printf "If this is a real API key, DO NOT COMMIT IT.\n" fi fi diff --git a/.git-hooks/pre-push b/.git-hooks/pre-push index 5bdb7ce69..8f8637b88 100755 --- a/.git-hooks/pre-push +++ b/.git-hooks/pre-push @@ -15,8 +15,8 @@ set -e -# shellcheck source=./_lib.sh -. "$(dirname "$0")/_lib.sh" +# shellcheck source=./_helpers.sh +. "$(dirname "$0")/_helpers.sh" printf "${GREEN}Running mandatory pre-push validation...${NC}\n" @@ -157,9 +157,9 @@ while read local_ref local_sha remote_ref remote_sha; do fi # Socket API keys (except allowed public key and test placeholders). - if echo "$file_text" | grep -E 'sktsec_[a-zA-Z0-9_-]+' | filter_allowed_sktsec | grep -q .; then + if echo "$file_text" | grep -E 'sktsec_[a-zA-Z0-9_-]+' | filter_allowed_api_keys | grep -q .; then printf "${RED}✗ BLOCKED: Real API key detected in: %s${NC}\n" "$file" - echo "$file_text" | grep -n 'sktsec_' | filter_allowed_sktsec | head -3 + echo "$file_text" | grep -n 'sktsec_' | filter_allowed_api_keys | head -3 ERRORS=$((ERRORS + 1)) fi