#!/bin/bash set -Eeuo pipefail GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' FAILURES=0 fail() { echo -e "${RED}✗ $1${NC}"; FAILURES=$((FAILURES+1)); } pass() { echo -e "${GREEN}✓ $1${NC}"; } require_header() { local headers=$1; local name=$2; local pattern=${3:-} if ! echo "$headers" | grep -qi "^$name:"; then fail "$name header not found"; return; fi if [ -n "$pattern" ] && ! echo "$headers" | grep -i "^$name:" | grep -qiE "$pattern"; then fail "$name does not match expected pattern: $pattern"; return; fi pass "$name present" } require_header_absent() { local headers=$1; local name=$2 if echo "$headers" | grep -qi "^$name:"; then fail "$name should be absent"; else pass "$name absent as expected"; fi } assert_http_status() { local url=$1; local expected=$2 local code; code=$(curl -s -o /dev/null -w "%{http_code}" -I "$url") if [ "$code" != "$expected" ]; then fail "HTTP status $url expected $expected, got $code"; else pass "HTTP $expected for $url"; fi } DEV_URL="http://localhost:5005" PROD_URL="https://ploughshares.nixc.us" URL=${1:-$DEV_URL} echo -e "${BLUE}Testing API Security Headers for ${URL}${NC}" echo "==================================================" test_api_headers() { local endpoint=$1; local description=$2; local full_url="${URL}${endpoint}" echo -e "\n${YELLOW}${description} (${endpoint})${NC}" echo "------------------------------------------------" assert_http_status "$full_url" 200 headers=$(curl -s -I "$full_url") echo -e "${BLUE}Headers:${NC}"; echo "$headers" | grep -v "Date:" | grep -v "Server:" require_header "$headers" "Content-Security-Policy" require_header "$headers" "Access-Control-Allow-Origin" "\*" require_header "$headers" "Access-Control-Allow-Methods" require_header "$headers" "Access-Control-Allow-Headers" require_header "$headers" "Cross-Origin-Resource-Policy" "cross-origin" require_header_absent "$headers" "Cross-Origin-Embedder-Policy" } test_api_headers "/api/test" "API test endpoint headers" echo -e "\n${YELLOW}OPTIONS preflight for /api/test${NC}" echo "------------------------------------------------" preflight_code=$(curl -s -o /dev/null -w "%{http_code}" -X OPTIONS -I "${URL}/api/test") if [ "$preflight_code" != "200" ]; then fail "OPTIONS /api/test expected 200, got $preflight_code"; else pass "OPTIONS /api/test returns 200"; fi preflight_headers=$(curl -s -X OPTIONS -I "${URL}/api/test") require_header "$preflight_headers" "Access-Control-Allow-Origin" "\*" require_header "$preflight_headers" "Access-Control-Allow-Methods" require_header "$preflight_headers" "Access-Control-Allow-Headers" if [ "$FAILURES" -gt 0 ]; then echo -e "${RED}API header tests failed: $FAILURES issue(s).${NC}"; exit 1 else echo -e "${GREEN}All API header tests passed.${NC}" fi