CVE-2026-52767: YesWiki Vulnerable to Unauthenticated ActivityPub Signature-Verification Bypass via `!openssl_verify(...)` accepting `int(-1)`
HttpSignatureService::verifySignature() checks the result of PHP’s openssl_verify() with a loose boolean negation - if (!openssl_verify(...)) { throw ... }. PHP’s openssl_verify has four possible return values:
| return | meaning | !return |
|---|---|---|
1 | signature is valid | false |
0 | signature is invalid | true ✓ |
-1 | the verify call itself failed (internal error) | false ❌ |
false | input rejected by PHP’s argument validation | true ✓ |
The -1 row is the bypass: PHP’s truthiness rules make -1 a truthy value, so !(-1) === false, the throw is skipped, and the controller proceeds to processActivity(). Any condition that makes OpenSSL’s EVP_VerifyFinal() return -1 triggers the bypass.
The two practical paths to -1 we are aware of:
- DSA / EC public key with an RSA-only algorithm.
openssl_verify(..., $dsaKey, "RSA-SHA256")returnsint(-1)on PHP 8.3 + OpenSSL 3.x. This is the path the PoC uses; it works against an unmodifiedphp:8.3-apachelab and against any deployment using the runtime stack YesWiki’s own docker image ships. - Older PHP + older OpenSSL where any unrecognised digest name returned
-1rather thanfalse. The reporting research mentions this path; on current stacksfalseis returned instead and the throw fires correctly. The DSA path replaces it.
The reachable consequence is the same in both cases - the controller silently treats a failed verification as success and processes the attacker’s payload.
References
Code Behaviors & Features
Detect and mitigate CVE-2026-52767 with GitLab Dependency Scanning
Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →