UntrustedLdapFilter
warning native on by defaultGroup: Security
Request data inserted directly into an LDAP filter can alter its syntax. Escape values for the LDAP filter context.
Example
php
<?php
ldap_search($ldap,$base,"(uid=".$_GET["user"].")");Reported:
- line 2: Escape request data for LDAP filter syntax.
Detection
- Resolved ldap_search/list/read filter contains a direct request-superglobal value by concatenation or interpolation, not wrapped in a resolved ldap_escape call that escapes for the filter context. Limit propagation to unmodified locals, concatenation and the parts of a double-quoted or heredoc string.
- A request value is an element of
$_GET,$_POST,$_REQUEST,$_COOKIEor$_SERVERread with a statically known key: a quoted string, a literal, or the bare word or number of simple interpolation such as"$_GET[user]". - ldap_escape protects the filter when its flags argument is omitted or is the integer zero (every byte is escaped), or when the flags provably include LDAP_ESCAPE_FILTER. When the flags are a known constant, integer or bitwise-or tree without that bit (for example LDAP_ESCAPE_DN alone, which leaves
*,(and)intact), the escaped argument is examined as if the call were absent. Positional and named arguments are both read. - Source provenance additionally requires an untouched lexical superglobal prefix. Exclude earlier explicit writes to or reference escapes of that superglobal and any earlier write or reference target involving GLOBALS. Reject all earlier object construction and unknown calls, including calls with no arguments, method calls and static calls; only resolved strlen, is_string, ctype_alnum, ctype_digit or in_array are supported pure-call exceptions. Traverse at most 4096 AST nodes, excluding nested variable scopes; exhaustion or unsupported source mutation discards the request-origin proof.
- Resolve builtin functions, classes, constants and methods; user-defined lookalikes are excluded. Follow only bounded local proof in one lexical scope.
- Emit one finding per violating operation, not per supporting evidence statement. When the proof is inconclusive, nothing is reported.
Exceptions (no report)
- Do not report unresolved or shadowed builtin names, unknown values, or incomplete receiver/type provenance. Unknown calls, aliases escaping, and intervening writes invalidate local proof. Similar code outside the stated detection contract is not a finding.
$_SERVERentries produced by the SAPI or by server configuration carry no client-chosen text and are not request values: REQUEST_TIME, REQUEST_TIME_FLOAT, SERVER_ADDR, SERVER_PORT, REMOTE_PORT, SERVER_SOFTWARE, GATEWAY_INTERFACE, SERVER_PROTOCOL, DOCUMENT_ROOT, SCRIPT_FILENAME and argc. Every other known key stays a request value, because many non-HTTP_entries (SERVER_NAME, REQUEST_METHOD, CONTENT_TYPE, REMOTE_USER, argv) can be influenced by the client.- ldap_escape with flags that cannot be evaluated, any other call wrapping the value, and a superglobal read with a dynamic key are unproven and not reported.
- A backtick command passes its interpolated parts to the shell, not to the filter; it is not reported here.
- Both standard suppression forms suppress this native ID.
Fix
None. Choosing a repair requires intent or additional runtime information.
PHP versions
Available throughout supported PHP 5.3–8.5 where the referenced builtin/extension is available. Respect syntax/version-specific receiver contracts; unavailable APIs are not this rule’s concern.
Configure
In custos.json:
json
{
"rules": {
"UntrustedLdapFilter": {
"enabled": false
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore UntrustedLdapFilter