v1.31.0
If you use FCaptcha as a Node library, read the threshold note before upgrading. Server, Docker and Helm deployments are unaffected by it.
Security
The npm entry point scored with an older engine than the bundled server.
require('@webdecoy/fcaptcha') and server.js had drifted into two separate implementations, and the library was the one that fell behind. It ran a reduced detector set and the confidence-weighted-mean aggregation that 1.18.0 replaced, without the dispositive floor that was added alongside it.
The practical effect: an automated browser could receive a passing verdict from the library that server.js would have refused.
Affected: integrations importing the package as a library, since 1.18.0.
Not affected: server.js, the Docker image, the Helm chart, and the Go and Python servers.
Both entry points now run one shared detection core, server-node/engine.js.
Re-check your thresholds. If you integrate the library directly, the same traffic now scores higher — that is the fix working, but it will move where your allow, challenge and block boundaries land. The HTTP API, the token format and the client are unchanged.
The proof-of-work precondition, challenge network binding and secret requirement added in recent releases are all preserved. The shared engine replaces the detector set, not the verification gate.
Fixed
Invisible scoring counted signals that only exist when there is a widget. Approach path, exploration ratio and overshoot corrections all come from the client's click analysis — which invisible mode never runs. The servers read those absent values as evidence against the visitor. Interaction duration means time on page in invisible mode rather than time spent solving, so ordinary reading tripped a captcha-farm signal.
All four are now gated on the interaction mode, which the server establishes from the endpoint it was called on rather than from client-supplied signals. Fixed in Go, Node and Python.
The library did not carry the accessibility exemptions the servers had. Touch, keyboard-only and screen-reader visitors were scored on mouse-trajectory checks that cannot apply to them, and visitors with slow or unsteady pointer movement were scored on the slow-pointer checks. The guards the servers already used are now shared.
Changed
- Node's detectors and score aggregation live in
server-node/engine.js, imported by bothindex.jsandserver.js.server.jsbehaviour is unchanged. version.test.jspins the release version across every file that carries it, the SECURITY.md supported-versions table, and a matching CHANGELOG entry — so the three cannot drift apart at release time.