#!/usr/bin/env bash # SPEC: wp-snippets/README.md#verification # Compliance date: 2026-05-20 # Launch type: manual post-deployment verification # Registry: iqon Phase 1 hardening verification set -u BASE_URL="${1:-https://iqon.com}" FAILED=0 note() { printf '\n[%s] %s\n' "$1" "$2" } fail() { FAILED=1 printf '[FAIL] %s\n' "$1" } pass() { printf '[PASS] %s\n' "$1" } fetch_headers() { curl -sS -I -L "$BASE_URL/" } fetch_home() { curl -sS -L "$BASE_URL/" } note CHECK "Security headers" if ! HEADERS="$(fetch_headers)"; then HEADERS="" fail 'could not fetch homepage headers' fi printf '%s\n' "$HEADERS" | rg -qi '^x-content-type-options:\s*nosniff' \ && pass 'X-Content-Type-Options present' \ || fail 'X-Content-Type-Options missing' printf '%s\n' "$HEADERS" | rg -qi '^x-frame-options:\s*SAMEORIGIN' \ && pass 'X-Frame-Options present' \ || fail 'X-Frame-Options missing' printf '%s\n' "$HEADERS" | rg -qi '^referrer-policy:' \ && pass 'Referrer-Policy present' \ || fail 'Referrer-Policy missing' printf '%s\n' "$HEADERS" | rg -qi '^permissions-policy:' \ && pass 'Permissions-Policy present' \ || fail 'Permissions-Policy missing' printf '%s\n' "$HEADERS" | rg -qi '^content-security-policy:' \ && pass 'Content-Security-Policy present' \ || fail 'Content-Security-Policy missing' note CHECK "Homepage HTML" if HOME="$(fetch_home)"; then printf '%s\n' "$HOME" | rg -q 'name=["'\'']viewport["'\'']' \ && pass 'viewport present' \ || fail 'viewport missing' printf '%s\n' "$HOME" | rg -q 'iqon-skip-link' \ && pass 'skip link present' \ || fail 'skip link missing' printf '%s\n' "$HOME" | rg -q 'http://www\.iqon\.com|http://iqon\.com|http://maps\.google\.com|http://maps\.googleapis\.com' \ && fail 'known HTTP URLs still present' \ || pass 'known HTTP URLs absent' printf '%s\n' "$HOME" | rg -q 'property=["'\'']og:site_name["'\''][^>]*content=["'\'']- IQON["'\'']' \ && fail 'og:site_name still has - IQON' \ || pass 'og:site_name no longer has - IQON' else fail 'could not fetch homepage HTML' fi note CHECK "REST users endpoint" if USERS_BODY="$(curl -sS -L "$BASE_URL/wp-json/wp/v2/users")"; then printf '%s\n' "$USERS_BODY" | rg -q '"slug"\s*:\s*"(admin|iqnadm01)"' \ && fail 'public REST users still exposed' \ || pass 'public REST users not exposed' else fail 'could not fetch REST users endpoint' fi note CHECK "Install documents" README_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' -L "$BASE_URL/readme.html")" case "$README_STATUS" in 403|404) pass "readme.html blocked with $README_STATUS" ;; *) fail "readme.html returned $README_STATUS" ;; esac note CHECK "XML-RPC HEAD smoke" XMLRPC_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' -I --http1.1 "$BASE_URL/xmlrpc.php")" XMLRPC_CURL_STATUS=$? case "$XMLRPC_STATUS" in 403|404|405) pass "xmlrpc.php not plainly usable via HEAD: $XMLRPC_STATUS" ;; 000) if [ "$XMLRPC_CURL_STATUS" -eq 52 ]; then pass "xmlrpc.php returned empty reply via HEAD: $XMLRPC_STATUS" else fail "xmlrpc.php check failed with curl status $XMLRPC_CURL_STATUS" fi ;; *) fail "xmlrpc.php returned $XMLRPC_STATUS; run safe POST check" ;; esac printf '\n' if [ "$FAILED" -eq 0 ]; then printf '[OK] iqon Phase 1 verification passed for %s\n' "$BASE_URL" else printf '[FAIL] iqon Phase 1 verification failed for %s\n' "$BASE_URL" fi exit "$FAILED"