v1.35.0
Security and correctness fixes across the Go, Node, and Python servers, the npm library, and the widget. Deploy the server and the widget together.
Fixed
Verification prerequisites are enforced independently of the score. A mismatched signal commitment, or a challenge submitted before its required minimum age, now withholds the token on all three servers rather than only lowering the score. The npm engine requires the server-issued challenge nonce for every proof, including proofs without a signal commitment, and reports the same diagnostics as the standalone server.
Tokens are unique and single-use in the npm library. Each token carries a random signed ID, and verifyToken refuses a token it has already accepted. A full local replay store reports token_store_full (Siteverify: internal-error) instead of reporting an unused token as a replay.
Node stays up on a malformed scoring request. Async route errors are caught, and the scoring POST routes validate request shape and answer invalid_request.
Runtime state is bounded. Fingerprint cardinality uses fixed 15-minute windows capped at 16 members per bucket, in memory and in Redis. Python Redis calls run off the event loop with connection and operation timeouts.
The widget cleans up after itself. FCaptcha.destroy(widgetId) and session.destroy() release listeners, sensors, workers, and timers. Challenges are refreshed before their nonce is captured, repeated invisible executions are serialised, and a spent form token is never reused.
Affected: every release up to and including 1.34.1.
Behaviour changes
- Invisible form protection runs a fresh verification on every submission.
- Direct npm
engine.verify()callers get an exception withstatus: 400for malformed signals. - Go and Python access logs are off unless
FCAPTCHA_LOG_ACCESS=1. Verdict logging keeps its own setting. - Importing
server-node/server.jsexports{ app, start }without opening a listener.node server.jsandnpm startare unchanged.
Upgrading
Deploy the updated widget with the server. Custom clients must honour the advertised minAgeMs and submit the serialised signals that match a committed proof. If you load the widget from the CDN, bump the pinned version and the integrity digest.
Subresource Integrity
fcaptcha.js sha384-8Yl4oQnQaAjKwsu0CXcZ10wo30QlIjLr4rd2inPQHNdjS6DsUjfpUXZFMITUIgBS
dist/fcaptcha.min.js sha384-tdnaXev76Qi2egBL8thvxH1YB97wnC53VoHGRd62gChhyMY75Hl1Nhw2vLR0ee+r