Skip to content

Developer notes

Overview · Installation · Configuration · Usage · FAQ

CS-Cart has an antibot service (Tygh::$app['antibot'], Tygh\Web\Antibot) with replaceable drivers, the rule schema security/antibot_rules (which POST requests are checked under which scenario) and the template common/image_verification.tpl that forms include. Captcha Pro uses all three instead of a parallel mechanism:

  • init.php extends the service with Tygh\Addons\KvCaptchaPro\Antibot (a subclass of the core class) and its driver Driver (IAntibotDriver, IErrorableAntibotDriver), only while the add-on is enabled, licensed and Google reCAPTCHA has no keys. The driver cannot be replaced by another add-on afterwards.
  • The subclass reads the form settings of the add-on instead of Image verification: Use for, never writes session flags (every submission is checked, so cached pages stay identical for all guests) and skips signed-in users per the settings.
  • schemas/security/antibot_rules.post.php adds rules core does not ship (auth.recover_password, product_reviews.add, products.product_notifications) and makes every rule end the request on failure: rules that “redirect” without a URL get a real target and terminate_process becomes a denial. Without this, a failed check on auth.login without redirect_url still ran the sign-in controller.
  • The template override common/image_verification.tpl renders the widget while Captcha Pro is active and otherwise the reCAPTCHA template or the unchanged core content.
  • The admin and vendor panel sign-in (not covered by core) is checked in controllers/backend/auth.pre.php.
  1. Allow-list: the visitor IP (IpList::visitorIp(): REMOTE_ADDR; forwarded headers only from loopback, private or configured proxies, X-Forwarded-For walked from the right) against the allowed addresses.
  2. Rate limit: fixed window per form and IP (kv_cp_rate, one atomic INSERT … ON DUPLICATE KEY UPDATE; the IP is stored only as an HMAC).
  3. Honeypot: the hidden field kv_cp_website must be empty.
  4. Ticket: kv_captcha_pro.ticket (storefront) or auth.kv_cp_ticket (panels) returns a signed ticket base64url(JSON {v, f, ts, n, d, c}) . "." . HMAC; no session, no database write. The browser finds a nonce so that SHA-256(ticket ":" nonce) starts with d zero bits (12/15/18, +3 when the visitor used half the attempts). The server checks the signature (key derived from the install secret and crypt_key), form, storefront, age (minimum time, 30-minute lifetime), the work, and single use (kv_cp_used).
  5. Provider: Turnstile (challenges.cloudflare.com/turnstile/v0/siteverify, action must equal the form, idempotency_key) or hCaptcha (api.hcaptcha.com/siteverify, sitekey). In provider mode the ticket carries the time check and, with the built-in fallback, the work; a provider outage or a widget that cannot load (kv_cp_fallback=1) is accepted only with a solved ticket.

Outcomes are counted per day in kv_cp_stats.

The widget markup and the script settings depend only on the add-on settings. Tickets come from a non-cacheable dispatch; checks write only own tables on POST. No ?:storage_data writes.

Table Content
kv_cp_forms form, company_id, status (A check, L rate limit only, D off), attempts, window_min
kv_cp_rate bucket (HMAC of storefront, form, IP), hits, window_start, expires_at
kv_cp_used SHA-256 of used tickets until they expire
kv_cp_stats day, company_id, form, outcome, hits

index.php?dispatch=kv_captcha_pro.ticket&form=<form> and admin.php|vendor.php?dispatch=auth.kv_cp_ticket (JSON). Templates: storefront override common/image_verification.tpl, index:scripts / index:styles (.post); admin auth:login_form (.post), index:styles, addons:tabs_content, addons:manage. Controllers: frontend init.post, kv_captcha_pro; backend auth.pre, auth.post, kv_captcha_pro. Schemas: security/antibot_rules, menu/menu, permissions/admin, gdpr/klaro_config (Turnstile/hCaptcha listed as strictly necessary in the GDPR add-on’s consent dialog). No PHP hooks besides the generated upgrade hook.

To protect a form of your own add-on, include common/image_verification.tpl with your scenario in the form, add a rule in your schemas/security/antibot_rules.post.php and register the scenario with the settings_variants_image_verification_use_for hook: it then appears on the Spam protection page.

Tygh\Addons\KvCaptchaPro\License\Client (generated) verifies the license. Gate: Config::isActive(), which decides whether Captcha Pro takes over the antibot service, renders the widget, issues tickets and checks the panel sign-in.

Google reCAPTCHA as a provider (use the built-in add-on), Friendly Captcha / ALTCHA widgets, per-country rules, IP reputation lists.

Path Purpose
app/addons/kv_captcha_pro/addon.xml Settings, tables
init.php, func.php Service extension, install secret, ticket responder, settings status
Tygh/Addons/KvCaptchaPro/Antibot.php, Driver.php Antibot service subclass and driver
Ticket.php, ProviderVerifier.php, RateLimiter.php, IpList.php Checks
Forms.php, Stats.php, Coexist.php, Config.php, Bootstrap.php, Admin.php Form settings, statistics, Google reCAPTCHA, settings, view data, admin page
License/, controllers/backend/kv_captcha_pro_license.php License check (generated)
Upgrade/Synchronizer.php Self-healing upgrades (generated)
controllers/, schemas/ Endpoints, admin page, rules, menu, permissions, consent
var/themes_repository/responsive/templates/addons/kv_captcha_pro/ Widget, template override, scripts
design/backend/templates/addons/kv_captcha_pro/ Admin page, settings status, panel sign-in widget
js/addons/kv_captcha_pro/func.js Widget script: SHA-256 proof of work, provider loading, form hold and resend