11 Commits

Author SHA1 Message Date
5f91b979eb feat: protect WP login, password reset, and fix Elementor AJAX bypass
- Move elementor_pro/forms/validation hook before is_admin() early return
  (same AJAX bypass bug as CF7 — Elementor submits to admin-ajax.php)
- Add login_head + login_footer hooks so CSS/JS HMAC token loads on
  wp-login.php (wp_head/footer do not fire on that page)
- Add lostpassword_form + woocommerce_lostpassword_form injection hooks
- Add authenticate filter (validate_wp_login) for WP native login,
  guarded to skip WC login and non-form auth calls
- Add lostpassword_post action (validate_lost_password) for password reset,
  covering both WP and WC My Account lost-password forms
- Exclude woocommerce-lost-password-nonce from generic catch-all to avoid
  double-processing WC lost-password submissions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 07:08:50 +01:00
07b5025b0b fix: CF7 bypass, auto-flush, layout, contrast, IP geo v2.4.0
CF7:
- Add wpcf7_spam filter registered before is_admin() early-return so
  CF7 AJAX submissions (admin-ajax.php) are properly validated
- Exclude CF7 posts from generic catch-all (prevent double-checking)

Auto-flush:
- Add maybe_flush_overdue() with 5-min transient lock, hooked to
  shutdown action so every PHP request can trigger a flush if overdue
- No longer depends solely on WP-Cron firing

Dashboard layout:
- Top Attackers moved into right column below live feed
- Viewport-fill layout: body/main use flex+overflow:hidden so content
  stays in view; left col scrolls independently if needed
- Feed panel takes flex:1, attackers panel capped at 260px

Colors:
- --dim: #006600 → #44bb77 (legible secondary text, ~5:1 contrast)
- --dim2: #228844 added for slightly darker secondary use
- --muted kept dark for backgrounds only; border lightened slightly

IP geo (server-side, async, non-blocking):
- country + asn columns added to blocks table (migration-safe)
- enrichIP() calls ip-api.com free HTTP API per unique IP, cached 1h
- Background job enriches historic rows missing country (5 per 20s)
- Stats and live feed now include country code + ASN
- Dashboard shows country flag emoji in feed rows and attackers table
- Full AS name shown as tooltip on ASN column

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 07:57:16 +01:00
01a15007cb fix: surface flush() errors in admin connection status
When WP-Cron's automatic queue flush fails (network error, wrong token,
non-200 response), update connection_ok=false and last_error with the
reason so the admin dot turns red and shows the exact failure message.
Previously failures were silent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 20:35:14 +01:00
f1c32e5060 feat: i18n (EN/ES/RO), HP_API_TOKEN constant, EU footer v2.3.0
- SmartHoneypotI18n class with EN/ES/RO string tables and flag switcher
- All WP admin UI strings translated (logs tab, settings tab, notices)
- Language preference stored per-user in user meta (hp_lang)
- Browser language auto-detection with localStorage persistence
- HP_API_TOKEN constant support: define in wp-config.php to keep
  token out of the database; UI shows read-only note when active
- resolve_token() checks constant first, falls back to DB setting
- API dashboard: EN/ES/RO language switcher with flag buttons
- API dashboard: data-i18n attributes on all static UI elements
- API dashboard: EU footer "Made & hosted in the EU by Cloud Host"
  with link to cloudhost.es
- Bump version to 2.3.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 20:34:35 +01:00
92e0522a03 feat: send local history to central API dashboard
- Add SmartHoneypotAPIClient::send_history_batch():
  reads local wp_honeypot_log in pages of 50, starting from
  hp_history_last_id option, sends to API, tracks progress
- Two new options: hp_history_last_id, hp_history_total_sent
- Action handlers: send_history (one batch), reset_history (start over)
- Settings tab: new 'Send History to API' section showing:
  * Local record count, sent count, remaining count
  * Progress bar (blue WP style)
  * 'Send History' / 'Send Next Batch' button with remaining count
  * 'Reset Progress' to re-send from beginning
  * Section only shown when API is enabled and URL is configured
- Notices: per-action feedback with 'Click Send Next Batch to continue'
2026-03-09 19:54:50 +01:00
b6be526b46 fix: real connection validation for Central API settings
- Add SmartHoneypotAPIClient::test_connection():
  1. GET /api/v1/health — verifies URL is reachable
  2. POST /api/v1/submit with empty blocks — verifies token:
     400 = auth passed (payload rejected as expected)
     403 = wrong or missing token
- Store connection_ok (null/true/false), last_verified, last_error in settings
- 'Active' dot now has 3 states: grey=untested, green=verified, red=failed
- Error message displayed inline when connection fails
- 'Test Connection' button appears as soon as URL is set
- Saving with changed URL or token resets connection status to untested
- Save action preserves verified status when URL/token unchanged
2026-03-09 19:40:18 +01:00
f4f28db8b2 fix: add package-lock.json so Docker npm ci succeeds 2026-03-09 19:31:04 +01:00
bd5a67b57f fix: full IPs, top attacked form banner, Bearer token auth on /submit
server.js:
- Remove maskIP() — store full IPs as submitted (sanitizeIP trims/truncates only)
- Add requireToken() middleware with constant-time comparison (timingSafeEqual)
  using 128-byte padded buffers to prevent length-based timing leaks
- API_TOKEN env var — if unset the endpoint stays open (dev mode); set it in prod
- /api/v1/submit now requires Authorization: Bearer <token>

docker-compose.yml / .env.example:
- Expose API_TOKEN env var with clear comment

index.html:
- Add red-bordered 'MOST ATTACKED FORM (30D)' banner between stats and content grid
  showing form name, hit count, and % of all 30d blocks
- Widen live feed IP column 90px → 130px to fit full IPv4 addresses
- Remove 'ALL DATA IS ANONYMISED' from footer (IPs are full now)

honeypot-fields.php:
- SmartHoneypotAPIClient: add api_token to defaults + send Authorization header
- save_api_settings: persist api_token field
- Settings tab: add password input for API token with description
2026-03-09 19:26:23 +01:00
6740180981 feat: centralized API dashboard + Docker container
API server (api/):
- Node.js + Express + SQLite (better-sqlite3, WAL mode)
- POST /api/v1/submit — receive blocks from WP sites (rate limited 30/min/IP)
- GET  /api/v1/stats  — public aggregated stats with 30s cache
- GET  /api/v1/stream — SSE live feed, pushed every 2s
- GET  /api/v1/health — health check
- IP masking: only first 2 octets stored (192.168.x.x)
- UA family detection: curl, Python, Go, bots, Chrome, etc.
- docker-compose.yml with named volume for SQLite persistence

Dashboard (api/public/index.html):
- Hacker/terminal aesthetic: black + matrix green, CRT scanlines
- Live stat cards: total blocked, today, 7d, 30d, sites reporting
- Canvas 24h activity trend chart with gradient bars
- CSS bar charts: form types, bot toolkit, block reasons
- Live SSE threat feed with countUp animation and auto-scroll
- Top 10 attackers table with frequency bars
- Polls /api/v1/stats every 6s, SSE for instant feed updates

WordPress plugin (honeypot-fields.php):
- SmartHoneypotAPIClient: queue (WP option) + WP-cron batch flush every 5min
- log_spam() now enqueues to central API after local DB write
- Admin 'Central API' tab: enable toggle, endpoint URL, sync stats, manual flush
- Cron properly registered/deregistered on activate/deactivate
2026-03-09 19:21:41 +01:00
a3e38faffa feat: add DB logging and admin UI for blocked attempts
- SmartHoneypotDB class: creates wp_honeypot_log table (id, blocked_at,
  ip_address, form_type, reason, request_uri, user_agent)
- SmartHoneypotAdmin class: admin menu page 'Honeypot Logs' with:
  * Stats cards (total blocked, blocked today, unique IPs, form types hit)
  * Filterable table (by IP, form type, free-text search)
  * Pagination (25 per page)
  * IP lookup link (ipinfo.io) and quick IP filter per row
  * Clear All Logs button
- log_spam() now writes to DB with form_type context
- current_form_type property threads form name into every log entry
- View Logs link added to plugin action links
- Auto-prune logs older than 90 days via WP cron
- DB schema versioning for future migrations
2026-03-09 17:11:09 +01:00
c2a29ffbbe feat: honeypot fields v2.0 with JS challenge, rate limiting, and proper WooCommerce hooks
- Require honeypot field presence (blocks direct POST bots)
- Add HMAC-based JavaScript proof-of-work token via SubtleCrypto
- Hook into woocommerce_process_registration_errors for proper validation
- Add IP-based rate limiting (3 registrations/hour) via transients
- Add timestamp validation (min 3s, max 2h)
- Use realistic field names to avoid bot detection
- Support WP core registration, comments, Elementor, Gravity Forms, CF7
2026-02-16 09:54:17 +01:00