#!/usr/bin/env bash # Fails the build if a production bundle contains anything that should only # ever exist server-side. # # Why this exists: the storefront used to send provider payment credentials # from the browser - an `authorization-key` header, a `userid-value` header, # and a hardcoded partner ID literal compiled into the bundle. That code is # gone (FH-1.3), and this check is what stops it coming back. A credential in # a JS bundle is not a leak you can revoke quietly; it is published. # # Usage: # npm run build && scripts/ci/scan-bundle.sh [dist-dir] set -euo pipefail DIST="${1:-dist}" if [[ ! -d "$DIST" ]]; then echo "scan-bundle: '$DIST' does not exist - build first" >&2 exit 2 fi # Each entry is "label|extended-regex". Keep patterns specific: a pattern that # fires on ordinary code trains people to ignore this check. PATTERNS=( "provider auth header|authorization-key" "provider user header|userid-value" "hardcoded partner id|web-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" "oauth client secret|client_secret[\"']?[[:space:]]*[:=]" "private key block|BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY" "aws access key|AKIA[0-9A-Z]{16}" "telegram bot token|[0-9]{8,10}:AA[0-9A-Za-z_-]{33}" ) failed=0 for entry in "${PATTERNS[@]}"; do label="${entry%%|*}" pattern="${entry#*|}" if matches="$(grep -rIlE "$pattern" "$DIST" 2>/dev/null)"; then if [[ -n "$matches" ]]; then echo "FAIL: $label found in the built bundle" >&2 echo "$matches" | sed 's/^/ /' >&2 failed=1 fi fi done if [[ $failed -ne 0 ]]; then echo >&2 echo "A credential reached the browser bundle. Move it behind the API." >&2 exit 1 fi echo "scan-bundle: clean ($DIST)"