Safely detect whether a Strapi instance is vulnerable to CVE-2026-27886 without performing the full account-takeover chain. See the full write-up on the Bishop Fox blog.
CVE-2026-27886 is an unauthenticated parameter sanitization bypass in Strapi versions 4.0.0 through 5.36.1 that allows remote, unauthenticated attackers to leak administrator secrets through the public Content API. The framework's query sanitizer in @strapi/utils processes only the documented filters, sort, fields, and populate query keys and silently preserves every other top-level key on the request. The unknown keys are then forwarded through transformQueryParams and land on strapi.db.query(...) as the SQL WHERE clause. By probing where[updatedBy][resetPasswordToken][$startsWith]=<prefix> against any public Content API collection, an attacker can leak administrator secrets one character at a time through the response's meta.pagination.total field.
This tool performs non-destructive vulnerability testing by:
- Sending a baseline
GET /api/<collection> - Sending the same
GETwith?where[id][$lt]=-1appended - Comparing the two
meta.pagination.totalvalues to determine if thewhereclause reached the database layer
The where[id][$lt]=-1 predicate cannot match any real row, so when the clause is honored at the database layer the response collapses to zero rows. When the patch is in place, the unknown where key is dropped by the sanitizer's allowlist before the query is built and the response is identical to the baseline. The probe never touches private admin columns and never modifies any data.
- Vulnerable servers return different totals: the baseline returns at least one row while the predicate request returns zero, because the
whereclause was honored at the database layer. - Patched servers (Strapi 5.37.0 or later) return identical totals for both requests, because
sanitizeQueryremoves any unrecognized top-level keys before they reach the database. - Non-Strapi servers, unreachable endpoints, or empty collections will report an
INCONCLUSIVEresult.
On a vulnerable server the tool then enumerates the administrator's email address character by character via where[updatedBy][email][$startsWith]=<prefix>. It does not chain to administrator account takeover.
git clone https://github.com/BishopFox/CVE-2026-27886-check
cd CVE-2026-27886-checkNo external dependencies. The scanner uses only Python standard library modules.
Test a Strapi server's public Content API collection endpoint. Strapi maps the content type's pluralName to the URL path, so the exact name varies by deployment.
python3 CVE-2026-27886-check.py <ENDPOINT>$ python3 CVE-2026-27886-check.py http://target.example.com/api/articles
[+] Target: http://target.example.com/api/articles
[+] Differential confirmed: baseline total=1, where-test total=0 -> VULNERABLE
[+] Enumerating admin email
admin email = admin@example.com
[+] Done. To remediate, upgrade to Strapi 5.37.0 or later.$ python3 CVE-2026-27886-check.py http://target.example.com/api/articles
[+] Target: http://target.example.com/api/articles
[+] Differential check: baseline total=1, where-test total=1 -> NOT VULNERABLEThe tool can only detect the vulnerability if the following conditions are met:
- The target is running Strapi 4.0.0 through 5.36.1
- The Public role has been granted
findon at least one content type - At least one row in that content type has a non-NULL
updated_by_id - The target collection URL is reachable
If any condition isn't met, the tool will report an INCONCLUSIVE result.
This code is distributed under an MIT license.
Usage of this tool for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state, and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program.