Skip to content

UntrustedLdapFilter ​

warning native on by default

Group: 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, $_COOKIE or $_SERVER read 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.
  • $_SERVER entries 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

Released under the MIT License. Native rules and rules modeled on Php Inspections (EA Extended); independent clean-room implementation.