94 findings. 20 reproduced live.
A 273 MB breach anyone can download.
WordPress 7.0 + WooCommerce 10.4.4 — pregnancy-expo ticketing & seat-selection. Custom "luc1f3r" MVC theme.
Audited 2026-07-02 · HTTP/2 · nginx · PHP 8.1.33
Right now, anyone on the internet can download your entire website — your customer list, your payment secrets, and an administrator password — with no login and no special tools.
273 MB — the entire site in one anonymous download, no login.
123 MB debug log left web-readable to the open internet.
1 credential file served in the clear over plain HTTP.
The database password + 8 salts all readable — takeover-grade secrets.
The clear mathematics
Every one of 94 distinct items carries exactly one final verdict — 100% checked, 0 unchecked. 228 raw findings were absorbed into that partition through deduplication.
| Verdict | Items |
|---|---|
| Live-confirmed | 20 |
| Code-confirmed | 60 |
| Blocked | 11 |
| Not-reproduced | 2 |
| Refuted | 1 |
| Total (each carries exactly one verdict) | 94 |
| Raw findings absorbed via dedup | 228 |
P0–P3 weight, raw vs distinct
How the 228 raw findings (P0–P3 plus one refuted) collapse into 94 distinct items — shown side by side, with the source audit's one-item discrepancy surfaced, not silently corrected.
| Severity | Raw findings | Distinct items |
|---|---|---|
| P0 · Critical | 62 | 31 |
| P1 · High | 80 | 30 |
| P2 · Medium | 63 | 28 |
| P3 · Low | 22 | 5 |
| Total | 227 | 94 |
Honesty note: the original audit's own distinct P-counts summed to 91 against 92 pre-D93 defects — a one-item discrepancy carried from the source. The counts shown here are freshly tallied from the 94 dossier headers and sum to 94; we surface the original discrepancy rather than silently 'correct' it.
The live-breach evidence wall
Twenty findings were reproduced over plain HTTP on production — no login, no tooling. Each proof binds only its HTTP status and byte-size; never a value.
The live-breach evidence wall
Full-site backup archives downloadable (273MB + www.zip)
A full-site backup archive (about 273 MB) plus a smaller zip download freely, exposing source, data and secrets.
full-site archive; plus www.zip at 551,965 b
Public 123MB `debug.log` (attendee PII + checkout internals)
A very large debug log is publicly downloadable and contains attendee personal data and checkout internals.
Public PII exports (customers/failed/integromat JSON, tels.csv)
Several exported data files holding customer contact details are downloadable by anyone, no login required.
seatgen JSON: 465+43 attendee records + 54 order/customer pairs
Seat-generation data files listing hundreds of attendee records are publicly downloadable without authentication.
`wp-config-bkp.pjp` downloads as plaintext (DB password + 8 salts)
A backup of the main config file downloads in plain text, exposing the database password and secret keys.
`app/config/dump` — plaintext admin credential (if served)
A config file returns a plaintext administrator credential to anyone who requests it.
God-router: no nonce + no capability check, nopriv-exposed (whole app surface)
A single catch-all endpoint runs for anonymous users with no security token or permission check, exposing the whole app.
`ajax_get_map`/`ajax_get_state` unauthenticated seat-state read
Anyone can read live seat-state data through the open endpoint without logging in.
Secrets in webroot: second `wp-config-bkp.php` + live `wp-config.php` (DB password + salts)
The web root exposes config backups and the live config file containing the database password and secret keys.
ACF Extended 0.9.2.3 < 0.9.2.6 (unauthenticated privilege escalation, exploited in the wild)
A plugin is several versions behind and vulnerable to an actively exploited unauthenticated privilege-escalation flaw.
WooCommerce 10.4.4 < 10.5.3 (CVE-2026-3589)
The store platform runs an outdated version affected by a known published security vulnerability.
WPCode 2.3.3 < 2.3.6 (CVE-2026-8832 Author+ RCE, live `eval()`)
A code-snippet plugin runs an outdated version affected by a known remote-code-execution vulnerability.
Query Monitor 3.20.2 active in production (reflected XSS + info disclosure)
A developer debugging plugin is left active in production, leaking internal info and enabling reflected cross-site scripting.
Simple History 5.22.0 (sensitive-data exposure) + 3 redundant activity loggers
An activity-logging plugin runs an outdated version with a known sensitive-data-exposure issue.
WP All Export (free) 1.4.14 `eval()` on admin-configured export queries
An export plugin evaluates admin-configured query code, an outdated version with a code-execution surface.
Framework bootstrap hard-depends on the abandoned/EOL `mobble` plugin
The site's framework hard-depends on an abandoned, end-of-life plugin that no longer receives fixes.
Two divergent theme copies (`www/luc1f3r` vs `wp-content/themes/luc1f3r`)
Two divergent copies of the theme are served publicly, doubling exposure and causing code drift.
Raw `session_start()` on init after output; legacy `session_id()` guard; sha256 ownership
A raw PHP session is started on every request with a weak guard, confirmed live by the session cookie.
Redundant migration/backup tooling (3 plugins)
A redundant migration/backup plugin is installed alongside two others, confirmed present in production.
Public sitemap + ticket slug leaks customer email addresses
The public sitemap lists ticket URLs whose slugs leak fragments of customer email addresses.
Findings explorer
Slice every finding across verdict, severity, vector, impact and remediation tier; search and sort, then open any card for its full 12-point dossier. Filters are shareable — they live in the URL.
Findings explorer
94 of 94 findings
Unauthenticated full attendee-PII dump via `?luc1_override`
An unauthenticated visitor can trigger a hidden parameter that dumps every attendee's name and phone number at once.
Ticket IDOR: any buyer's name + phone by sequential ID
Anyone could page through sequential ticket IDs to read other buyers' names and phone numbers without logging in.
`wp-config-bkp.pjp` downloads as plaintext (DB password + 8 salts)
A backup of the main config file downloads in plain text, exposing the database password and secret keys.
Public 123MB `debug.log` (attendee PII + checkout internals)
A very large debug log is publicly downloadable and contains attendee personal data and checkout internals.
Public PII exports (customers/failed/integromat JSON, tels.csv)
Several exported data files holding customer contact details are downloadable by anyone, no login required.
seatgen JSON: 465+43 attendee records + 54 order/customer pairs
Seat-generation data files listing hundreds of attendee records are publicly downloadable without authentication.
~97 wpallexport CSVs (national ID / pregnancy / kids)
Around a hundred exported spreadsheets holding sensitive customer data sit in a publicly reachable folder.
Full-site backup archives downloadable (273MB + www.zip)
A full-site backup archive (about 273 MB) plus a smaller zip download freely, exposing source, data and secrets.
`app/config/dump` — plaintext admin credential (if served)
A config file returns a plaintext administrator credential to anyone who requests it.
`export-attendees.php` — pregnancy/EDD CSV, no auth, remote-URL require (RFI)
An export script builds a sensitive attendee spreadsheet with no login and can pull in a remote file (RFI risk).
God-router: no nonce + no capability check, nopriv-exposed (whole app surface)
A single catch-all endpoint runs for anonymous users with no security token or permission check, exposing the whole app.
`lcf_seater` engine table: no schema-in-code, missing UNIQUE(event_id,seat)/indexes
The core seat table has no schema in code and likely lacks the unique key and indexes needed to prevent double-booking.
`lcf_seater.time` written in SECONDS by ticket-sync but MILLISECONDS everywhere else
Seat timestamps are written in seconds by one path but milliseconds everywhere else, corrupting time logic.
Payment cURL TLS certificate verification disabled on PAN+CVV request
The server sends card number and security code to the payment gateway with TLS certificate checking turned off.
Payment cURL has no connect/read timeout (worker hang, double-charge risk)
The payment request has no timeout, so a slow gateway can hang server workers and risk double charges.
Raw gateway response + full `$_SERVER` + national ID persisted to order meta
Raw payment data, the full server request, and a national ID are saved into order records that should never store them.
Secrets in webroot: second `wp-config-bkp.php` + live `wp-config.php` (DB password + salts)
The web root exposes config backups and the live config file containing the database password and secret keys.
ACF Extended 0.9.2.3 < 0.9.2.6 (unauthenticated privilege escalation, exploited in the wild)
A plugin is several versions behind and vulnerable to an actively exploited unauthenticated privilege-escalation flaw.
Hardcoded payment bypass: `cc_id == 317330009` marks order paid with no charge
A hardcoded magic value lets an order be marked paid with no actual charge.
babyland-checkout binds non-existent `save_kids_count_meta_box` → fatal on order save
Saving an order calls a callback that does not exist, causing a fatal error.
Stored XSS: buyer `full_name` unescaped in event-guests wp-admin metabox
A buyer's name is shown unescaped in an admin screen, allowing stored cross-site scripting.
Price tampering: client `seatPrice` trusted verbatim → free/underpriced tickets
The checkout trusts the price sent by the browser, letting an attacker buy tickets for free or underpriced.
`ajax_tickets` force-deletes an arbitrary order via forgeable cart-cookie
A forgeable cart cookie lets an attacker force-delete any order through the open endpoint.
`ajax_seat_state` lets an anonymous user free/overwrite any (paid) seat and NULL a ticket
An anonymous user can free, overwrite, or blank out any paid seat through the open endpoint.
`ajax_reassign_seat` has no capability check, reachable by anonymous users
Seat reassignment runs with no permission check and is reachable by anonymous users.
SQL injection in `exit_ticket()`: `event_id`/`seat` interpolated unprepared into SELECT
A seat parameter is placed into a database query unsafely, allowing SQL injection.
Seat reservation race (read-check-write, no lock/unique) → double-booking
Seat reservation checks and writes without a lock, so two buyers can end up booking the same seat.
`Tickets::ajax_render` (nopriv) regenerates/overwrites any ticket
An open endpoint lets anyone regenerate and overwrite any existing ticket.
Stored XSS via buyer name/NID into ticket SVG served `image/svg+xml`
A buyer's name flows unescaped into an SVG ticket served as an image, allowing stored cross-site scripting.
`execute_seater_cleaner` `return` not `continue` → hold-expiry stops → inventory shrink
A loop uses return instead of continue, so hold-expiry cleanup stops early and seat inventory shrinks.
`seater_cleaner`/`seater_updater` run synchronously on EVERY init (full scan + disk I/O)
Heavy seat cleanup and sync jobs run synchronously on every request, scanning data and hitting disk each load.
`ajax_get_map`/`ajax_get_state` unauthenticated seat-state read
Anyone can read live seat-state data through the open endpoint without logging in.
WooCommerce 10.4.4 < 10.5.3 (CVE-2026-3589)
The store platform runs an outdated version affected by a known published security vulnerability.
WPCode 2.3.3 < 2.3.6 (CVE-2026-8832 Author+ RCE, live `eval()`)
A code-snippet plugin runs an outdated version affected by a known remote-code-execution vulnerability.
Query Monitor 3.20.2 active in production (reflected XSS + info disclosure)
A developer debugging plugin is left active in production, leaking internal info and enabling reflected cross-site scripting.
Framework bootstrap hard-depends on the abandoned/EOL `mobble` plugin
The site's framework hard-depends on an abandoned, end-of-life plugin that no longer receives fixes.
Plaintext deploy credentials in `mom2be/.env`
Plaintext deployment credentials are stored in an environment file inside the codebase.
DISABLE_WP_CRON absent, wp-cron runs on every visitor load
Scheduled tasks run on every visitor page load instead of on a real schedule, hurting performance.
`SELECT * ... GROUP BY user` violates `ONLY_FULL_GROUP_BY` (empty exports)
A database strict-mode setting can make grouped export queries fail and return empty results.
WooCommerce block-pattern cache holds stale absolute paths (open_basedir spam)
A cached list holds stale absolute file paths, spamming error logs after the site was moved.
HPOS: babyland compat undeclared + metabox/kids_count store mismatch
Order metaboxes may read from or write to the wrong storage when the modern order-storage mode is enabled.
No SMTP/DKIM/Return-Path → ticket emails to spam; `wp_mail()` return value ignored
Ticket emails lack sender-authentication setup so they land in spam, and send failures are silently ignored.
Stored XSS in admin dashboards (guests/tickets/leads) + reflected XSS in seatgen
Several admin dashboards render buyer input unescaped, allowing stored and reflected cross-site scripting.
Admin CSV export + mark-used are CSRF-able GET state-changes, no nonce
Admin export and mark-used actions run on simple links with no security token, enabling cross-site request forgery.
`ajax_remail` un-throttled mail-bomb + ticket-exfil to attacker email
An open re-email action can be abused to mail-bomb or send tickets to an attacker's address.
Gate `qr_confirm` marks used + fires Make webhook, no auth/throttle, forgeable QR
A gate confirmation marks tickets used and fires a webhook with no authentication or throttling.
Unauth GET `?luc1_reset_cron` wipes the seat-sync/cleanup cron
An unauthenticated link can wipe the site's seat-sync and cleanup scheduled task.
Coupon single-use reuse guard is dead code (email ignored)
The coupon single-use guard is dead code, so single-use coupons can be reused.
`every_second` wp-cron schedule (self-DoS / event pile-up)
A once-per-second scheduled task can pile up and overload the site.
Raw `session_start()` on init after output; legacy `session_id()` guard; sha256 ownership
A raw PHP session is started on every request with a weak guard, confirmed live by the session cookie.
No DB transaction over order+tickets+seater → charged-but-undelivered
Order, tickets, and seat updates aren't wrapped in one transaction, risking charged-but-undelivered orders.
`execute_seater_updater` non-atomic JSON write (truncated reads)
A data file is written non-atomically, so readers can catch truncated content.
Unbounded `SELECT * FROM lcf_seater` (cleaner + admin)
The code reads the entire seat table with no limit, wasting memory as the data grows.
`ImagickException` caught in wrong namespace → real failures fatal
An image exception is caught in the wrong namespace, so real failures become fatal errors.
`occupy()` re-marks ALL seats per ticket, O(n²), mislabels ownership
A ticket routine re-marks all seats each time, running slowly and mislabeling seat ownership.
`post_exists` dedup omits `order_id` → repeat order clobbers prior ticket
Duplicate-check for tickets ignores the order ID, so a repeat order can clobber an earlier ticket.
`ticket.php` `die('no seat')` inside buffered template aborts post-payment
A template aborts the whole request when a seat is missing, breaking the post-payment page.
Two divergent QR engines / non-standard `LcfQRCode` → scan drift/unreliable
Two divergent QR engines produce inconsistent codes, causing unreliable gate scans.
No WP privacy erasure/exporter hooks; lead CPT public; no retention
No privacy erasure or export hooks exist and lead records are public, with no data-retention controls.
`lcf_seater` grows unbounded (cleaner never DELETEs)
The seat table grows forever because cleanup never deletes old rows.
Public sitemap + ticket slug leaks customer email addresses
The public sitemap lists ticket URLs whose slugs leak fragments of customer email addresses.
seatgen json dir has no directory-listing deny (enumeration)
The exports folder lacked directory-listing protection, which could let visitors enumerate its files.
Simple History 5.22.0 (sensitive-data exposure) + 3 redundant activity loggers
An activity-logging plugin runs an outdated version with a known sensitive-data-exposure issue.
WP All Export (free) 1.4.14 `eval()` on admin-configured export queries
An export plugin evaluates admin-configured query code, an outdated version with a code-execution surface.
Two divergent theme copies (`www/luc1f3r` vs `wp-content/themes/luc1f3r`)
Two divergent copies of the theme are served publicly, doubling exposure and causing code drift.
`wp-config.php` hardening gaps: `WP_MEMORY_LIMIT=128M`, `UPLOADS='src/media'`, `DISALLOW_FILE_MODS=false`
Config hardening gaps: a low memory limit, an unusual uploads path, and in-dashboard file edits left enabled.
Make.com webhook: no timeout, no HMAC, forwards PII synchronously
An outbound integration webhook forwards personal data with no timeout and no message signing.
HPOS admin: metaboxes no-op / wrong-store on order screen
Order metaboxes silently do nothing or read the wrong store under the modern order-storage mode.
`luc1ph3r` keyless Feistel = QR/gate authz boundary (forgeable tokens)
The QR/gate token scheme uses a keyless, reversible cipher, so tokens can be forged.
CSV formula injection in attendee/dashboard exports
Exported spreadsheets don't neutralize leading formula characters, allowing spreadsheet formula injection.
Freebie threshold `intval($sum)<=1` skips payment for ~1–1.99₪
A rounding bug lets very small cart totals skip payment entirely.
Stored XSS: event ACF fields + seat-map JSON unescaped into front templates
Event fields and seat-map data render unescaped into front-end templates, allowing stored cross-site scripting.
`generate-test-barcode.php` mints valid gate barcodes + leaks PII (if in webroot)
A leftover test script can mint valid gate barcodes and leak personal data if it is web-reachable.
N+1 `wc_get_product()` inside per-seat loop; dashboard N+1
Product lookups repeat inside a per-seat loop, creating an N+1 query slowdown.
`log_debug()` unbounded read-append-write into autoloaded ACF option
A debug logger reads, appends, and rewrites an auto-loaded option, bloating it without bound.
BabyLand Statistics `wc_get_orders(limit=-1)` unbounded per page load
A statistics screen loads all orders with no limit on every page view.
`App`/`Gate`/`Guests __construct` deref `$post->ID` with no null guard (fatal)
A constructor reads a post ID with no null check, causing a fatal error when it is absent.
Order created 'pending' before payment, no hold-expiry → stale orders/holds
Orders sit pending before payment with no hold expiry, leaving stale orders and locked seats.
Gate/qr writes `WHERE user+event` (no id/seat) → wrong rows
A gate update matches on user and event only, so it can update the wrong rows.
OR-precedence bug in event-leads guest query (wrong seats)
An operator-precedence bug in a guest query returns the wrong seats.
Front-end JS: NaN totals, overlapping intervals, holds leak on unload
The front-end checkout script has bugs: bad totals, overlapping timers, and holds leaking on page unload.
`SetupSec::luc1h4sh()` AES hardcoded key/bad IV every init
A helper reuses a hardcoded key and a bad initialization vector for encryption on every load.
No brute-force lockout/WAF; relies on WPS-Hide-Login obscurity
There is no brute-force lockout or web application firewall; security relies only on a hidden login URL.
Cancel/refund leaves lead PII + `lcf_seater` history; cleaner keeps `last_user`
Cancelled or refunded orders leave behind personal data and seat history, a data-retention gap.
Ajax router doesn't validate class/method exist; unused allowlist
The endpoint router doesn't verify the target class or method exists and keeps an unused allowlist.
Redundant migration/backup tooling (3 plugins)
A redundant migration/backup plugin is installed alongside two others, confirmed present in production.
`ajax_seat_state` block() insert has no availability guard
A seat-block insert has no availability guard, allowing conflicting seat states.
No root `.htaccess`/`.user.ini` (no app-layer hardening/headers)
There is no root-level hardening file, so no app-layer access rules or security headers are set.
CPT Hebrew display-name as rewrite slug; lead/ticket public + archives
Public archives and a display-name-based URL slug expose lead and ticket records.
`?luc1sh1n3` reflects a decrypted author string (fingerprint)
A public parameter reflects a decoded author fingerprint string, a low-severity information leak.
Tech-debt cluster: bundled jQuery, hardcoded paths, dead code, console.logs
A cluster of maintainability issues: bundled jQuery, hardcoded paths, dead code, and leftover console logs.
Commented-out hardcoded Tranzila password in source
A commented-out hardcoded payment-gateway password remains in the source code.
HTML-only ticket email, unescaped names, no text/plain alt
Ticket emails are HTML-only with unescaped names and no plain-text alternative.
"Seater bootstrap calls undefined `xxx()`" (REFUTED)
A reported call to an undefined function was disproven; the function is actually defined. No real defect.
How the application is actually reachable
One anonymous request lands on a catch-all router with no nonce and no capability check, then fans out to the seat, checkout and ticket engines and the seat database. Below: the live data-flow, the vector × safety coordinate space, and the six verification buckets.
aData flow — anonymous internet to the seat database
One unauthenticated request reaches a catch-all router and fans out to every engine.
The renamed REST namespace /luc1-json/ and the raw PHPSESSID session are both live on production.
bCoordinate space — attack vector × safety class
Every finding carries a vector (who can trigger it) and a safety class (how risky it is to test). Cell size and hue track count and the highest severity present. Select a cell to open it in the explorer.
| Vector by safety class | S1 read-only | S2 active-safe | S3 destructive | S4 server / DB read |
|---|---|---|---|---|
A Unauth GET | ||||
B Unauth POST | Vector B Unauth POST, safety S4: no findings | |||
C Authenticated | Vector C Authenticated, safety S1: no findings | |||
D Internal | Vector D Internal, safety S1: no findings | Vector D Internal, safety S2: no findings | Vector D Internal, safety S3: no findings |
- AUnauth GET — Anonymous URL in a browser
- BUnauth POST — Anonymous crafted request (the god-router)
- CAuthenticated — Needs a login / admin session
- DInternal — No external trigger (background / data-layer)
- S1read-only — Safe to observe — no state change
- S2active-safe — Sends a request but mutates nothing
- S3destructive — Mutates real data — staging only
- S4server / DB read — Confirmed via a server, DB or config read
cVerification buckets — the testing order, safest first
How the 94 items were queued for live verification: read-only proofs first, destructive and code-only work last.
Safe to prove live — the client-facing proofs
Prove the CSRF/authz class without mutating
One WP-CLI / SQL / config read each
Needs an admin session to demonstrate
Mutates real data — reproduce on a copy
Confirmed in code; not externally observable
The tiered fix plan — T1 → T2 → T3
A phased plan you can ship tier by tier. T1 stops the active bleeding in days; T2 removes double-booking and scales the checkout; T3 rebuilds the platform, privacy and monitoring foundation. Each work-item lists the defects it closes — select a defect chip to find it in the explorer.
Stop the bleeding
Contain the breach, rotate every secret + all 8 salts, lock the god-router, restore payment security, patch CVEs, tame the cron.
- T1-00/06Medium effort20h
Containment & breach response (delete artifacts, rotate all secrets + 8 salts, deny rules, log audit, PPL runbook)
Closes 7 defects - T1-01Medium effort16h
Plugin CVE patching + WooCommerce upgrade with staged regression of the custom order flow
Closes 6 defects - T1-02High effort28h
God-router hardening (nonce + endpoint allowlist + per-action capability + move admin ops off nopriv + rate limiter)
Closes 2 defects - T1-03Medium effort16h
PCI stop-bleed at config layer (TLS verify + timeouts + idempotency, remove bypass, stop persisting card/SAD)
Closes 4 defects - T1-04Low effort10h
Cleaner fix + cron neutralization (return→continue, remove per-init calls, kill every-second schedule, system cron)
Closes 3 defects - T1-05Low effort10h
Unauth IDOR / backdoor kill (HMAC-gate view_ticket_svg + rate limit; remove override/debug params)
Closes 4 defects - T1-hwLow effort8h
Performance quick-wins (memory limit, OPcache, page-cache marketing pages, hot-path N+1)
Closes 3 defects
Concurrency & scale
Atomic seat reservation (no double-booking), async offload, caching, HPOS correctness, output escaping, email deliverability.
- T2-08Medium effort24h
Schema-in-code + InnoDB conversion + UNIQUE(event,seat) + indexes + time-unit normalization migration
Closes 2 defects - T2-09High effort44h
Atomic seat-reservation service (ReserveStock pattern, retry) collapsing 4 paths + SQLi + OR-precedence fixes
Closes 5 defects - T2-10High effort28h
Action Scheduler offload (QR/Imagick, email, Make webhook HMAC, set-based hold-expiry) + Imagick/ticket fixes
Closes 4 defects - T2-11Medium effort16h
HPOS correctness (compat declaration, order-meta API, missing metabox, register on HPOS screen)
Closes 3 defects - T2-12Medium effort20h
Redis object cache + sessions to Redis + session guard + mobble removal + no-store on dynamic paths
Closes 3 defects - T2-13Medium effort20h
Output escaping across ~12 templates + CSV/JSON hygiene + CPT public=>false + GROUP BY fix
Closes 7 defects - T2-14Medium effort18h
Email deliverability (SMTP/DKIM/DMARC, wp_mail return-check) + HMAC gate tokens + idempotent qr_confirm
Closes 3 defects
Platform, security & privacy foundation
Re-home into a maintainable mu-plugin, remove card data from your servers, harden infra, build privacy controls + monitoring + tests.
- T3-W1High effort70h
Re-home logic into a must-use plugin + PSR-4 + endroid/qr-code + delete the duplicate theme + open_basedir/deploy
Closes 4 defects - T3-W2High effort40h
Complete PCI scope reduction (Tranzila hosted-fields/redirect so only a token touches PHP; SAQ)
Closes 4 defects - T3-W3High effort40h
Infra hardening (nginx deny + headers + WAF + 2FA + brute-force + FPM sizing) and VPS/managed migration
Closes 3 defects - T3-W4Medium effort32h
Retention + WP Privacy API (erasers/exporters, retention job, minimization) + security policy + breach runbook
Closes 3 defects - T3-W5aMedium effort24h
Load testing (k6/Locust harness + runs on the uncacheable seat-hold + checkout path at 5–20× peak)
- T3-W5bLow effort16h
Observability (Sentry or equivalent, PII-scrubbed) + move debug logging outside the webroot
Closes 2 defects - T3-W5cLow effort12h
Backup + tested rollback framework per migration
- T3-W5dLow effort12h
Privacy compliance coordination (data-tier classification, DPO liaison)
What we need from you to close every open item
Eleven findings are real but BLOCKED — each needs exactly one external read to reach a final live/staging verdict. Below, the eleven reads on the left; the five things to grant or decide on the right.
The 11 reads that unblock
11 BLOCKED- D30one read to close it
SELECT @@sql_mode;ONLY_FULL_GROUP_BY on → empty exports/dashboards
- D32/D42one read to close it
wp wc hpos statusHPOS on → order-meta/metabox fix path
- D15one read to close it
SHOW CREATE TABLE lcf_seaterInnoDB vs MyISAM → concurrency fixes are no-ops on MyISAM
- D16one read to close it
SELECT id,time FROM lcf_seater LIMIT 20seconds vs ms → hold-expiry
- D19one read to close it
order-meta field-name grepraw PAN/CVV + national ID persisted? (names only)
- D31one read to close it
woocommerce_blocks_patterns transient + open_basedirstale-path cache → log spam
- D35one read to close it
dig TXT (SPF/DKIM/DMARC) + test sendemails to spam / spoofable
- D33one read to close it
wp option get template / stylesheetwhich theme copy is live
- D10one read to close it
allow_url_include / open_basediris export-attendees a live RFI/SSRF
- D07one read to close it
one export filenameconfirm the ~97 attendee CSVs download
- D01one read to close it
one live exe()-routed URLsafely confirm the attendee-PII dump
Commands are illustrative and read-only — no secrets, credentials, or customer values are shown or requested.
Access & decisions — Sections A–E
Breach determination
Server + CDN log audit for untrusted hits + rogue-admin check — decides whether PPA notification fires now.
Server / DB one-line reads
Eleven copy-paste, read-only reads; each closes one BLOCKED finding.
Isolated staging copy
Required to demonstrate the 17 destructive findings safely, never on live customers.
Admin session
For the six admin-gated findings (D37–D42).
Two decisions
Scale target (routine vs flash-sale) and infra (shared vs tuned VPS).
Illustrative — approvals happen over your existing secure channel, not this page.
Completing the full picture
Everything below is what I need from you to turn this audit into a fully-verified, delivery-ready picture. I have already accounted for 100% of the findings (94 items, each with an evidence-backed verdict); what remains is a short, precise set of accesses and answers — each one closes a specific open item. I have deliberately kept this minimal: no fishing expeditions, every request maps to a reason. The first block is legally time-critical and should happen today, independent of everything else.
Breach determination (do first — legally time-critical)
We proved live that sensitive medical PII and secrets are downloadable right now. Under Israel's Privacy Protection Law (Amendment 13), the duty to notify the Authority is immediate on suspicion. The access logs convert 'suspicion' into a determined fact — did any untrusted IP already pull these files before we contain them?
- Server + CDN access logs
Widest retention available, so we can count untrusted-IP hits on the exposed .zip/.log/.json/.csv and on the backdoor query params — metadata only, never customer data.
closesscopes the breach - wp_users / lcf_users review
Check for injected/rogue administrators created via the leaked salts or the ACF-Extended CVE, and confirm the salts + DB passwords were rotated.
closesD20 · D21
Eleven one-line server / DB reads
Eleven findings are real in code but their live/runtime state depends on one value each. These are copy-paste, read-only, and non-destructive — together they take BLOCKED items to a final LIVE/CODE verdict and reach a full 100%.
- SELECT @@sql_mode
Is ONLY_FULL_GROUP_BY on? Decides whether exports/dashboards silently return empty.
closesD30 - wp wc hpos status
Is High-Performance Order Storage on? Decides the entire order-meta / metabox fix path.
closesD32 · D42 - SHOW CREATE TABLE lcf_seater
InnoDB or MyISAM? On MyISAM every concurrency fix is a silent no-op — we must convert first.
closesD15 - SELECT id,time FROM lcf_seater LIMIT 20
Are times in seconds or milliseconds? The mismatch breaks hold-expiry.
closesD16 - Order-meta field-name grep
Confirms raw PAN/CVV + gateway response + national ID are persisted (field names only, never a value).
closesD19 - woocommerce_blocks_patterns transient + open_basedir
Confirms the stale-path cache driving the log-spam.
closesD31 - DNS TXT (SPF / DKIM / DMARC) + one test send
Confirms why ticket emails go to spam / are spoofable.
closesD35 - wp option get template / stylesheet
Which of the two theme copies is LIVE — decides where every fix must land.
closesD33 - allow_url_include / open_basedir
Confirms whether the export-attendees remote-include is a live RFI/SSRF.
closesD10 - One export filename under wpallexport/exports/
The dir is 200 but listing is 403 — one real path confirms the ~97 CSVs download.
closesD07 - One live event/product URL that routes through exe()
Lets us safely confirm the attendee-PII dump on the live copy.
closesD01
An isolated staging copy
The 17 destructive findings mutate real data — creating orders, blocking paid seats, deleting, marking tickets used, injecting SQL. They can only be demonstrated safely on an isolated, sanitized copy, never on live customers. Their reachability is already proven live via the open god-router (D13); staging is only to show the mutation safely.
- Sanitized code + DB copy in an isolated environment
Built from the archive as a read-only source (the archive itself must NEVER be restored to production).
closesD43–D59
A shop-manager / admin session
Six findings are admin-gated and can only be demonstrated from inside wp-admin (preferably on the staging copy).
- Dedicated demo admin account
For the six authenticated findings — the payment bypass, the fatal-on-save metabox, the stored-XSS dashboards, the CSRF exports.
closesD37–D42
Two decisions from you
These are not access — they are business decisions that set how deep the scaling and platform work must go.
- Scale target
Routine day-to-day traffic, or flash-sale / on-sale spikes (hundreds contending for the same seats)? This sets the load-testing and stateless-node depth.
closesgates T2/T3 depth - Infrastructure
Stay on the current shared host (which structurally caps scalability), or move to a tuned VPS / managed WooCommerce host?
closesgates infra scope
Can we return a 100% working system?
Yes. You do not need to leave WordPress, and every fault we found maps to a specific, bounded, industry-standard fix. This is a recoverable system — not a write-off.
What I mean by ‘100% working’
No active exposure — the public archive, logs, exports, and credential files are gone and every leaked secret is rotated.
No unauthenticated attack surface — the god-router is behind a nonce + capability checks; the backdoors are removed.
Payment done correctly — TLS verification on, no card data stored server-side, PCI scope reduced to a token.
Zero double-booking under load — seat reservation is atomic at the database level, proven by load testing.
Correct end-to-end flow — no fatal-on-save, orders/tickets/QR agree, emails deliver, dashboards return real data.
Built to last — the code is restructured and covered by an automated regression test suite, with monitoring in place.
I will be precise about the words: I can deliver 100% of the identified defects remediated, verified, and guarded by tests + monitoring — that is a concrete, checkable bar. No one can honestly promise a system that is bug-free forever; what I promise is that the known defects are fixed, the fixes are proven, and new regressions are caught automatically. Two things also gate the final 'perfect' state and are partly outside my hands: your access + the two decisions above, and the PCI SAQ type, which your acquirer/QSA sets.
What it involves
Stop the bleeding
Contain the breach (delete exposed files, rotate every secret + all 8 salts), lock the god-router, restore payment security, patch the vulnerable plugins, and neutralize the runaway cron. High relief, low risk.
Concurrency & scale
Make seat reservation atomic (impossible to double-book), move slow work off the buyer's click, add caching, correct the store's data handling, escape all output, and fix email deliverability. This is the fix for the freezing and double-booking.
Platform, security & privacy foundation
Restructure the custom code into a maintainable must-use plugin, remove card data from your servers entirely, harden the infrastructure, and build the privacy controls the law expects — plus load testing, monitoring, and backups.
- The system is a bespoke, single-file architecture with no tests today — defect density stays elevated until the T3 restructure + the test suite land. That is exactly why T3 exists.
- '100%' is bounded by you granting the access above and answering the two decisions; some depth (scale, PCI SAQ type) follows those answers.
- Change windows matter: we schedule risky migrations around your event calendar so no live on-sale is disrupted.
Timeline & investment
A bottom-up estimate — every work item priced separately, grouped by the tiers you can ship independently, with a low / expected / high band. Set your own hourly rate and every total recomputes live.
- T1Stop the bleeding
- 86–150108 h
- T2Concurrency & scale
- 134–224170 h
- T3Platform, security & privacy
- 186–340246 h
- XCross-cutting
- 58–11680 h
- Build subtotal
- 464–830604 h
- Overhead (PM & docs 15% + QA & verify 10%)
- +25%+151 h
The hours and the calculation are complete and defensible. The monetary figure is intentionally a placeholder — enter your own hourly rate and every total on this page updates instantly.
The line items
Hours per work item, low / expected / high. Grouped by the tier it ships in; cross-cutting (X) spans all tiers.
Containment & breach response (delete artifacts, rotate all secrets + 8 salts, deny rules, log audit, PPL runbook)
D03·D04·D05·D06·D08·D09·D20
Plugin CVE patching + WooCommerce upgrade with staged regression of the custom order flow
D21·D22·D23·D24·D25·D26
God-router hardening (nonce + endpoint allowlist + per-action capability + move admin ops off nopriv + rate limiter)
D13·D14
PCI stop-bleed at config layer (TLS verify + timeouts + idempotency, remove bypass, stop persisting card/SAD)
D17·D18·D19·D37
Cleaner fix + cron neutralization (return→continue, remove per-init calls, kill every-second schedule, system cron)
D60·D61·D62
Unauth IDOR / backdoor kill (HMAC-gate view_ticket_svg + rate limit; remove override/debug params)
D02·D01·D11·D52
Performance quick-wins (memory limit, OPcache, page-cache marketing pages, hot-path N+1)
D29·D34·D74
Schema-in-code + InnoDB conversion + UNIQUE(event,seat) + indexes + time-unit normalization migration
D15·D16
Atomic seat-reservation service (ReserveStock pattern, retry) collapsing 4 paths + SQLi + OR-precedence fixes
D43·D45·D47·D48·D80
Action Scheduler offload (QR/Imagick, email, Make webhook HMAC, set-based hold-expiry) + Imagick/ticket fixes
D64·D65·D67·D70
HPOS correctness (compat declaration, order-meta API, missing metabox, register on HPOS screen)
D32·D38·D42
Redis object cache + sessions to Redis + session guard + mobble removal + no-store on dynamic paths
D63·D31·D27
Output escaping across ~12 templates + CSV/JSON hygiene + CPT public=>false + GROUP BY fix
D39·D40·D53·D55·D58·D89·D30
Email deliverability (SMTP/DKIM/DMARC, wp_mail return-check) + HMAC gate tokens + idempotent qr_confirm
D35·D54·D51
Re-home logic into a must-use plugin + PSR-4 + endroid/qr-code + delete the duplicate theme + open_basedir/deploy
D33·D71·D82·D90
Complete PCI scope reduction (Tranzila hosted-fields/redirect so only a token touches PHP; SAQ)
D17·D18·D19·D91
Infra hardening (nginx deny + headers + WAF + 2FA + brute-force + FPM sizing) and VPS/managed migration
D83·D88·D34
Retention + WP Privacy API (erasers/exporters, retention job, minimization) + security policy + breach runbook
D72·D84·D89
Load testing (k6/Locust harness + runs on the uncacheable seat-hold + checkout path at 5–20× peak)
verifies T2-09
Observability (Sentry or equivalent, PII-scrubbed) + move debug logging outside the webroot
D04·D75
Backup + tested rollback framework per migration
supporting
Privacy compliance coordination (data-tier classification, DPO liaison)
supporting
Discovery & access completion (run the 11 reads, the breach-log audit, close BLOCKED → verified)
closes 11 BLOCKED
Staging environment build + sanitized dataset (isolated, archive as read-only source)
enables D43–D59 demos
Automated regression / integration test suite for the critical flows (checkout, reservation, ticketing, gate)
guards everything
How I calculated this
- 1
Bottom-up, not top-down. I priced each work item in the remediation plan (T1-00…T3-W5) separately, not the project as a lump sum.
- 2
Complexity-banded. Each line carries a low / expected / high band tied to its complexity, cross-checked against the per-finding effort and complexity fields recorded in the 94 dossiers.
- 3
Grouped by the tiers you can ship independently, so you see cost per phase, not just a single number.
- 4
Overhead added transparently on top of build hours: project management + documentation + handover at 15%, and QA + per-tier verification at 10%.
- 5
Timeline derived from the hours assuming a small senior team (≈2 engineers + fractional PM/QA), then adjusted for real dependencies (your access, the two decisions, and event-calendar change windows).
- A senior WordPress/WooCommerce engineer with security and concurrency experience does the work — not a generalist (a generalist would be cheaper per hour but far more hours and higher risk here).
- You grant the access in Task 1 promptly; long access delays extend the calendar, not the hours.
- Staging is available for all destructive/regression work; nothing risky is proven on live customers.
- The rate is a placeholder — set your own hourly rate and the totals below recompute live.
- The single-file 'god' architecture can hide coupling — the high band absorbs surprises found once we are inside.
- The WooCommerce upgrade + HPOS state (a BLOCKED read) can widen T1-01/T2-11 if the custom order flow fights the newer core.
- PCI SAQ type is set by your acquirer; a stricter determination adds scope to T3-W2.
Timeline
Containment starts today and does not wait for the rest. Below is the elapsed calendar with a small senior team; each phase is a shippable milestone, and each 'gated on' note is where your input sets the pace.
- Phase 0 — Containmentimmediate → a few days
Exposure stopped, secrets rotated, breach determination underway.
Gated on: server access + your go-ahead - Phase 1 — Tier 1 complete~2–3 weeks
No unauth attack surface, payment secured, CVEs patched, cron sane.
Gated on: staging + the 11 reads - Phase 2 — Tier 2 complete~8–9 weeks (cumulative)
A secure, correct, non-breaking, faster system: zero double-booking, deliverable emails, correct data.
Gated on: HPOS + engine reads; scale-target decision - Phase 3 — Tier 3 complete~16–20 weeks (cumulative)
The complete, maintainable, PCI-reduced, privacy-compliant, load-tested platform with monitoring + tests.
Gated on: infra decision; PCI SAQ; event windows
A secure, working system (through Tier 2) in roughly two months; the complete, 'perfect' platform (through Tier 3) in roughly four to five months elapsed — the difference between the two is entirely the depth of the foundation and scale work.
How 228 raw signals became 94 verified items
Twelve expert lenses, one dedup pass, and a verdict for every item — measured without ever touching a real value.
The pipeline
expert lenses
Twelve independent review lenses swept the custom theme, plugins, database schema, and the live HTTP surface.
raw signals — 227 confirmed + 1 refuted
227 code-confirmed raw findings plus one that was later disproven — 228 raw signals entering triage.
Deduplication
12 expert lenses produced 227 raw findings; systemic issues (the god-router flagged 8×) collapse to distinct defects. Each distinct defect is verified once; the lens counts sum back to 227, +1 refuted = 228.
distinct items
Systemic issues collapse to distinct defects; each distinct defect is then verified exactly once.
One final verdict each
Each of the 94 items carries exactly one final verdict: 20 LIVE / 60 CODE / 11 BLOCKED / 2 NOT-REPRODUCED / 1 REFUTED = 94 (100%).
228 → 94
The raw bar collapses into the distinct bar, split by final verdict.
| Stage | Count |
|---|---|
| Raw findings (227 confirmed + 1 refuted) | 228 |
| Distinct · Live-confirmed | 20 |
| Distinct · Code-confirmed | 60 |
| Distinct · Blocked | 11 |
| Distinct · Not-reproduced | 2 |
| Distinct · Refuted | 1 |
| Distinct total | 94 |
- Raw 228
- Live-confirmed 20
- Code-confirmed 60
- Blocked 11
- Not-reproduced 2
- Refuted 1
Every item carries a verdict. The partition — 20 + 60 + 11 + 2 + 1 — sums to 94, i.e. 100% of items are accounted for; none left unchecked.
Live verification measured only HTTP status + content-type + byte-size; for data-reality we counted field-name/phone-pattern occurrences — never printed or stored a single PII value or secret.
- verification/00-triage-register.md
- verification/03-live-verification-results.md
- verification/04-summary-index.md
- verification/findings/D01–D93 + R01 (94 dossiers)
- deliverables/00-client-access-and-decisions-request.md
- deliverables/01-client-proof-pack.md
- remediation/T1-00…T1-06, T2-00, T3-00