Skip to content

Fix verification bypasses, bound state, and clean up browser sessions - #50

Merged
cport1 merged 2 commits into
mainfrom
fix/security-performance-review
Sep 9, 2026
Merged

cport1 merged 2 commits into
mainfrom
fix/security-performance-review

Conversation

@cport1

@cport1 cport1 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

What and why

Malformed requests could terminate the Node server, npm library tokens could be replayed, and mismatched signal commitments or skipped challenge delays could still mint tokens. This change makes those verification prerequisites independent of the weighted bot score and fixes the associated performance and browser lifecycle issues across the supported implementations.

  • Catch async route failures and validate Node scoring requests; give independently issued tokens random signed IDs and enforce single use in the npm library.
  • Accept the current widget proof format in npm middleware, require the issued nonce for both legacy and committed proofs, enforce signal commitments and challenge minimum ages, and use the shared timestamp field when Node verifies Redis challenges issued by Go or Python.
  • Align Go commitment-failure scoring and proof consumption with Node/Python, distinguish full Node token stores from token replay, and scope request validation to scoring POST routes.
  • Bound fingerprint buckets and their member sets, expire their scoring state, and use atomic, capped Redis fingerprint updates.
  • Offload Python Redis request work from the event loop and configure connection/operation timeouts without retries.
  • Refresh challenges before capturing their nonce, serialize repeated invisible executions, avoid reusing spent form tokens, and release sensors, listeners, workers, timers, and retained widget registrations during cleanup.
  • Make Go and Python launcher access logs opt-in, document the settings and cleanup API, and add mixed-runtime Redis CI jobs.

Validation

  • Node unit and new security regression tests passed, including nonce omission/mismatch, token-store capacity diagnostics, and GET routing.
  • Go go vet ./... and go test -race ./... passed, including valid/tampered commitment requests through both HTTP scoring endpoints.
  • Python unit suite and new security/access-log regressions passed.
  • Browser suite plus targeted lifecycle regressions passed: 47 distinct tests.
  • End-to-end detection suite: 111 passed, 0 failed.
  • API conformance: 12 checks passed for each of Node, Go, and Python.
  • Cross-runtime Redis conformance passed for Node → Python, Python → Go, and Go → Node against a local miniredis server. The CI matrix exercises production images against Redis 7.
  • False-positive benchmark gate passed: 201 samples, no replay errors, 0/126 labeled human samples flagged, and 73/75 agent samples above the detection threshold. Existing corpus exemptions and the declared-crawler/source-patched class warnings remain; these are corpus results, not population-wide accuracy claims.
  • git diff --check passed.

Checklist

  • Shared verification and fingerprint changes applied to Go, Python, and Node.
  • Server unit tests and Go race checks pass.
  • End-to-end detection suite passes.
  • Benchmark false-positive gate passes.
  • No new detector scoring thresholds or weights introduced; storage saturation stays above the existing cardinality thresholds.
  • Paired before/after human-persona score comparison was not run. The current benchmark human panel has zero flagged samples.

Verification classification

These are precondition fixes: a bad signal commitment or unmet minimum challenge age prevents token issuance regardless of the weighted score. No new detector is added.

Compatibility notes

  • Custom clients must honor the advertised minAgeMs and provide the matching serialized signals when submitting a committed proof. Deploy the updated widget with the server fixes.
  • npm library tokens now verify only once; retries must follow the integrating application's retry/idempotency policy. Invisible form protection performs a fresh verification on every submission.
  • Direct npm engine.verify() calls throw an error with status: 400 for malformed signals. A full local Node replay store returns token_store_full, mapped to Siteverify internal-error.
  • Fingerprint cardinality uses fixed 15-minute windows capped at 16 members per bucket.
  • These behavior changes are documented in the changelog’s Unreleased section.
  • Go and Python launcher access logs now require FCAPTCHA_LOG_ACCESS=1. Verdict logging retains its separate setting.
  • Importing server-node/server.js now exports { app, start } without starting a listener; programmatic consumers should call start(). Running node server.js or npm start continues to start the server.

@cport1
cport1 merged commit c949c4e into main Sep 9, 2026
17 checks passed
@cport1
cport1 deleted the fix/security-performance-review branch September 9, 2026 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant