# INTAKE · Security subscriptions

Drafted Thu Oct 22, 2026 (PT). Hand-off only. The crew adds these fields to the existing `/contact/` form (read `?topic=site-security` and `?topic=php-patch`) or a separate form. No checkout on the form.

---

## 1. Intake form fields

**Required**
| Field | Type | Notes |
|---|---|---|
| Your name | text | |
| Business name | text | |
| Email | email | Reply goes here |
| Website address | url | One site per form; "add another site" button optional |
| Who hosts the site? | select + text | GoDaddy, Bluehost, SiteGround, WP Engine, Kinsta, Hostinger, own server/VPS, "Not sure", Other (text). Options are just a list for the form, not a recommendation. |
| What is the site built with? | select | WordPress, WooCommerce, Drupal, Joomla, other PHP, "Not sure" |
| What are you looking for? | radio | Free site check only · One-time patch check · Monthly plan · Not sure |
| Permission | checkbox | "I own this site or am authorized to ask for it to be checked." Required. |

**Optional**
| Field | Type | Notes |
|---|---|---|
| Phone | tel | |
| Can you log in to the hosting account? | radio | Yes · No · Someone else manages it (name) |
| Who updates the site today? | radio | Me · My host · A developer/agency · Nobody right now · Not sure |
| Does the site take payments, bookings or logins? | checkboxes | Payments · Bookings · Member/customer logins · None |
| Do you know your PHP version? | text | Hint: WordPress Tools → Site Health → Info → Server |
| Has the host told you anything about the October PHP update? | textarea | Paste their message if you have one |
| Anything odd lately? | textarea | Hint: "slow pages, new admin users, emails from your host, anything". Neutral wording, no leading questions. |
| Is Cloudflare in front of the site? | radio | Yes · No · Not sure |
| Where do backups live? | radio | Host does them · A plugin · Nowhere I know of · Not sure |
| How did you hear about us? | text | Store as-is; feeds the `client_reference_id` source tag (see STRIPE-PLAN.md) |

**Hidden**
- `topic` (from URL), `utm_*` if present, `ref` (outreach tag such as `em2`), submit time PT.

**Thank-you text:** "Thanks. We'll run a few public, read-only checks on {site} and reply in writing {reply time, DECISION D2}. We won't log in or change anything."

---

## 2. Free site check script (read-only, public checks only)

File: `site-check.sh` in this folder (same code as below). Tested Oct 22, ~2:47 PM PT against `example.com` and `wordpress.org` only.

**Rules for the crew**
- Run it only on a site whose owner asked for the check (intake checkbox ticked), or on JKCA's own sites.
- It sends about 4 ordinary requests (HEAD, GET of the home page, GET of `/readme.html`) plus TLS handshakes. Nothing else.
- **Do not** run the Searchlight Cyber / Assetnote `php2shell-scanner` (https://github.com/assetnote/php2shell-scanner) as part of the free check. It is free and good, but it deliberately triggers PHP's memory-exhaustion condition with up to ~29 MiB of multipart probes and can crash a PHP worker. Its authors say to take care. Use it only on sites under a paid plan, with the owner's written OK, at a quiet time, and note it in the report.
- php2shellcheck.com (https://php2shellcheck.com) is a browser-only version comparer; it never contacts the site. Fine to point clients to.
- The script can't see inside the server and can't see build dates. The reply must say so.

**Usage**
```bash
chmod +x site-check.sh
./site-check.sh clientsite.com > checks/clientsite.com-$(date +%Y%m%d).txt
```

**What it reports**
1. Final HTTP status, `Server`, `X-Powered-By`, Cloudflare (`cf-ray`). If a PHP version is exposed, compares it with 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35; for 8.1, 8.0, 7.4 it says the build date must be checked with the host; older says no official patch.
2. TLS certificate issuer, expiry date and days left; whether TLS 1.0/1.1 is still accepted.
3. Security headers present or missing: HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy.
4. WordPress detection, generator tag version, common `?ver=` value on wp-includes assets, `/readme.html` status.

**Script**
```bash
#!/usr/bin/env bash
# JKCA free site check: read-only, public checks only.
# Sends a handful of ordinary GET/HEAD requests, like a browser would.
# It does NOT log in, submit forms, POST, fuzz, or run exploit/scanner probes.
# Usage: ./site-check.sh example.com   (only for sites the owner asked us to check)
set -u
host="${1:?usage: site-check.sh domain.com}"
host="${host#http://}"; host="${host#https://}"; host="${host%%/*}"
url="https://$host/"
ua="JKCA-site-check/1.0 (+https://jkca.studio/contact/)"
now=$(date '+%Y-%m-%d %H:%M %Z')
echo "JKCA free site check: $host  ($now)"
echo "Read-only: public GET/HEAD requests only."
echo

hdr=$(curl -s -I -L --max-time 15 -A "$ua" "$url")
if [ -z "$hdr" ]; then echo "Could not reach $url over HTTPS. Stop and note it."; exit 1; fi
last=$(printf '%s' "$hdr" | awk 'BEGIN{RS="\r?\n\r?\n"} NF{b=$0} END{print b}')
get(){ printf '%s\n' "$last" | grep -i "^$1:" | head -1 | cut -d: -f2- | sed 's/^ *//;s/\r$//'; }

echo "== 1. Server and PHP version (headers) =="
status=$(printf '%s\n' "$last" | head -1 | tr -d '\r')
echo "Final status: $status"
srv=$(get server); xpb=$(get x-powered-by); cf=$(get cf-ray)
echo "Server: ${srv:-not shown}"
echo "X-Powered-By: ${xpb:-not shown}"
[ -n "$cf" ] && echo "Cloudflare: yes (cf-ray present)" || echo "Cloudflare: not detected"
php=$(printf '%s' "$xpb" | grep -oiE 'php/[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 | cut -d/ -f2)
if [ -n "$php" ]; then
  maj=$(echo "$php" | cut -d. -f1-2); pat=$(echo "$php" | cut -d. -f3)
  case "$maj" in
    8.5) fix=12;; 8.4) fix=27;; 8.3) fix=36;; 8.2) fix=35;; *) fix="";;
  esac
  if [ -n "$fix" ] && [ -n "$pat" ]; then
    if [ "$pat" -ge "$fix" ]; then echo "PHP $php: at or above the fixed release ($maj.$fix). Still confirm PHP was restarted."
    else echo "PHP $php: BELOW the fixed release ($maj.$fix). Needs the patch, or the host's backport confirmed in writing."; fi
  elif [ "$maj" = "8.1" ] || [ "$maj" = "8.0" ] || [ "$maj" = "7.4" ]; then
    echo "PHP $php: end of life. Official minimal patch exists, but the number doesn't change. Can't tell from outside: ask the host for the package build date (needs Oct 21, 2026 or later)."
  else
    echo "PHP $php: no official patch for this branch. Upgrade to 8.2 or later."
  fi
  echo "Note: the site is showing its PHP version publicly. Hiding it (expose_php=Off) is a small hardening step."
else
  echo "PHP version: not shown in headers (normal and fine). Check inside: WP Site Health or hosting panel."
fi
echo

echo "== 2. TLS certificate =="
cert=$(echo | timeout 15 openssl s_client -servername "$host" -connect "$host:443" 2>/dev/null)
echo "$cert" | openssl x509 -noout -enddate -issuer 2>/dev/null | sed 's/^/  /'
end=$(echo "$cert" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -n "$end" ]; then days=$(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 )); echo "  Days until expiry: $days"; fi
for v in tls1 tls1_1; do
  if echo | timeout 10 openssl s_client -"$v" -servername "$host" -connect "$host:443" >/dev/null 2>&1; then echo "  Old protocol $v accepted (worth turning off)"; fi
done
echo "  (TLS 1.0/1.1 test depends on this machine's OpenSSL; 'nothing printed' means not accepted or not testable.)"
echo

echo "== 3. Security headers =="
for h in strict-transport-security content-security-policy x-frame-options x-content-type-options referrer-policy permissions-policy; do
  v=$(get "$h"); [ -n "$v" ] && echo "  [present] $h" || echo "  [missing] $h"
done
echo

echo "== 4. WordPress version exposure =="
body=$(curl -s -L --max-time 15 -A "$ua" "$url")
gen=$(printf '%s' "$body" | grep -oiE '<meta name="generator" content="WordPress[^"]*"' | head -1)
isw=$(printf '%s' "$body" | grep -c -iE 'wp-content|wp-includes')
if [ "$isw" -gt 0 ]; then
  echo "  WordPress: likely (wp-content/wp-includes paths in the home page)"
  [ -n "$gen" ] && echo "  Version shown in generator tag: $gen" || echo "  Generator tag: not shown (good)"
  ver=$(printf '%s' "$body" | grep -oE 'wp-includes/[^"]*\?ver=[0-9.]+' | grep -oE 'ver=[0-9.]+' | sort | uniq -c | sort -rn | head -1)
  [ -n "$ver" ] && echo "  Most common wp-includes ?ver= value: $ver (often the WP version)"
  rd=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 -A "$ua" "${url}readme.html")
  echo "  /readme.html status: $rd (200 means the default readme is public; low risk, easy to remove)"
else
  echo "  WordPress: not detected on the home page"
fi
echo
echo "Done. This check can't see inside the server. It is not proof a site is safe or unsafe."
```

**Reply template after the check** (crew fills, json or crew sends after review)
> Hi {name},
> We ran a few public, read-only checks on {site} on {date}. Here's what we saw from outside:
> - PHP version: {shown as X / not shown, which is normal}
> - Certificate: valid until {date}
> - Security headers: {n} of 6 in place
> - WordPress version: {shown / not shown}
>
> What we can't see from outside: whether your host has installed the October PHP fix and restarted PHP. {If 8.1/8.0/7.4: On your PHP version the number doesn't change after the fix, so the thing to ask your host for is the build date; it should be Oct 21, 2026 or later.}
> {Suggested next step: none needed / a one-time patch check / Watch / Patch / Harden, one line on why.}
> No pressure either way. Reply with any questions.
> {json}, JKCA Studio, Seal Beach

---

## 3. Written question for hosts (used in every tier)

> Hello, I'm writing about {site} on account {account}.
> 1. Which PHP version and package build is serving this site right now (from a web request, not the command line)?
> 2. Does that build include the fixes for CVE-2026-109618 and CVE-2026-109619? If it's PHP 8.1, 8.0 or 7.4, what is the package build date?
> 3. Has PHP (php-fpm, Apache or LiteSpeed) been restarted since that build was installed?
> 4. Can you give us read access to the access and error logs for this site?
> Thank you.

Record the reply verbatim, with date and time PT, in the client's report.
