Summary
- RFC 1558 gave LDAP's binary search Filter a human-readable prefix notation. Parentheses,
&,|,!, comparison marks and*were executable structure, not descriptive punctuation. - The filter was only one field in a SearchRequest. Base object, scope, aliases, limits, schema matching, access controls, requested attributes, entries, references and the final result each changed what a readable string could actually produce.
- Later RFCs refined the notation from IA5-era escaping to LDAPv3, UTF-8 and hexadecimal octet escapes. RFC 1558 was Informational and discussed no security issues; the documentary chain proves neither deployment nor a current vulnerability.
The asterisk had three lives
The smallest revealing example in RFC 1558 is not a company, a directory or an incident. It is one character.
In attr=*, the asterisk means presence: return entries for which the named attribute is present. In a value such as the RFC's (o=univ*of*mich*), asterisks divide a substring pattern into initial, middle and final components. If a value itself contains *, the 1993 memo says to precede it with a backslash so that it remains data rather than an operator.
Those are not typographic variations. They are different instructions. The visible string can ask an equality question, widen the candidate set, test presence or nest one condition inside another. A reviewer who sees only familiar words may miss the authority carried by punctuation.
RFC 1558's Datatracker record and RFC Editor record place the memo in December 1993 and preserve its Informational status. Its archival text provides a separate textual check, while the errata surface keeps later corrections distinct. The memo explicitly did not specify an Internet standard, and its security section said security issues were not discussed.
That limit matters. The notation makes an injection-shaped risk easy to recognize today, but RFC 1558 did not document a breach, name a vulnerable product or measure misuse. A historical account should not smuggle later vocabulary back into the evidence.
Readable did not mean inert
LDAP already had a network Filter. RFC 1487 defined it as an ASN.1 choice carried inside the SearchRequest and encoded for the network using BER. RFC 1558 did something narrower: it supplied a common human-readable rendering for applications that needed to store, display or exchange filters as text.
The grammar used prefix notation. Every filter sat inside parentheses. & introduced a list whose members all had to match; | introduced alternatives; ! negated the following filter. Simple items supported equality, approximate, greater-or-equal and less-or-equal comparisons. Presence and substring forms gave * its two operator roles.
The examples make the structure visible:
(cn=Babs Jensen)is an equality item.(!(cn=Tim Howes))negates an equality item.(&(objectClass=Person)(|(sn=Jensen)(cn=Babs J*)))combines a required object class with either a surname or a common-name prefix.
The third line resembles punctuation-heavy text. Parsed, it is a tree: AND at the root, one equality branch, then an OR branch containing equality and substring conditions. The server does not need to agree with a human's visual impression. It acts on the grammar it accepts.
RFC 1558 limited LDAPString to IA5 and relied on RFC 1488 for the string forms of attribute values. The visible notation was therefore not a universal rendering of every future directory value. It belonged to a particular protocol and syntax epoch.
A filter was not the whole search
Even a perfectly reconstructed Filter does not reproduce an LDAP search. The original SearchRequest also named a base object, chose base-only, one-level or whole-subtree scope, set an alias-dereferencing policy, supplied size and time limits, chose whether values should be returned and selected attributes.
That surrounding envelope changes the work. The same predicate below a different base object visits a different part of the directory. The same base and filter with whole-subtree scope considers more entries than a one-level search. Alias dereferencing can bring other objects into traversal. Limits can stop a search before every potential match has been returned. Attribute selection controls what the client asks to see after an entry matches.
The current protocol, RFC 4511, states the separation directly: a search asks a server to return, subject to access controls and other restrictions, entries matching a complex criterion. Its official record identifies the document; it is not a receipt for any particular operation.
Under RFC 4511, filter evaluation is three-valued: TRUE, FALSE or Undefined. An entry is returned only when the filter evaluates TRUE, and even then access controls apply. An unrecognized attribute description, unsuitable or unknown matching rule, or invalid assertion value can produce Undefined. A syntactically accepted string therefore does not prove that the server understood every item as the author expected.
Match, return and completion were different events
LDAP search output is not a single verdict. RFC 4511 defines zero or more SearchResultEntry and/or SearchResultReference messages followed by one SearchResultDone. Entries and references can arrive in any order. A reference marks an area not yet explored by that search. The final message reports success or error.
An entry can also arrive without every value the client might imagine. The request may ask for types only; access controls may suppress values; administrative policy may restrict them; operational attributes are not automatically returned. “The filter matched” and “the client received a complete record” are different claims.
The distinction prevents a chain of false promotions:
- a filter string parsed;
- a BER Filter was sent;
- a server evaluated it;
- one entry evaluated TRUE;
- an entry message was returned;
- selected attributes survived access policy;
- the search completed without a limiting error or unexplored reference;
- the application selected an entry;
- a principal was authenticated and authorized for a later act;
- the act succeeded.
Each step needs its own receipt. None is implied merely because the first line looked sensible.
The syntax kept changing because the boundary was real
RFC 1960, whose status record shows that it replaced RFC 1558 on the Standards Track, retained the recognizable prefix form and character-escape approach. It was itself replaced by RFC 2254.
RFC 2254 extended the notation for LDAPv3, including extensible matching, and moved into a UTF-8 setting. Its document record preserves that place in the sequence. Special octets were represented with a backslash followed by two hexadecimal digits rather than the earlier memo's looser instruction to precede three special characters with a backslash.
The current filter-string specification, RFC 4515, identified by its RFC Editor record, makes the encoding boundary more precise. It requires octets for *, (, ), backslash and NUL to be escaped and constrains generated strings to valid UTF-8. Its example (cn=*\2a*) searches for a literal asterisk within a common name: the outer asterisks remain substring operators while \2a represents data.
This is not merely defensive punctuation. It is a reproducibility rule. If a capture stores only a decoded display string and discards its original octets, escape routine and parser result, an investigator may be unable to tell whether an asterisk widened a predicate or belonged to the asserted value.
The thin contract was valuable
The lesson is not that readable representations are unsafe. Without a common text form, applications would invent incompatible syntaxes or expose opaque BER. Operators would have a harder time reviewing configuration, exchanging search templates and diagnosing behavior.
RFC 1558 standardized a narrow translation surface: one protocol object could be written in a shared textual form. It did not standardize the directory contents, schema epoch, access policy, base object chosen by an application or the action taken with a result. That restraint is the strength of a thin contract.
Heng Lu's Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption provides the editorial lens: common structure should be minimal and deterministic; decisions that depend on local policy should remain identifiable and reversible. The analogy is retrospective, not a claim about the RFC author's intent.
His Running-Code Primacy points the evidence inquiry toward the parser and server that actually ran. The RFC tells us what a notation meant on paper. It does not tell us which grammar a product accepted or which search a server executed. Reality-layer discipline then keeps the displayed string, parsed tree, BER request, evaluation, returned data and application outcome from collapsing into one reassuring label.
What the 1993 sources cannot prove
The evidence names no exploit, affected installation, exposed directory, current product or user outcome. It measures no adoption and supplies no packet capture. RFC 1558's Informational status is documentary classification, not evidence that software conformed to it. The later standards show a technical succession, not universal migration.
Nor does correct escaping authorize broad access. A perfectly encoded filter can still ask an expansive question. A server may correctly evaluate it and correctly refuse data. Conversely, a narrow filter may operate over an unexpectedly broad subtree because scope or alias policy changed. Security review belongs to the complete operation, not one string.
The durable contribution of RFC 1558 was to make a hidden protocol object discussable. Its durable warning is quieter: as soon as operators enter executable structure through readable text, the control surface begins at the parser and ends only after the result is bounded, attributed and acted upon.
Sources
- https://datatracker.ietf.org/doc/rfc1558/
- https://www.rfc-editor.org/info/rfc1558/
- https://www.rfc-editor.org/rfc/rfc1558.html
- https://www.rfc-editor.org/rfc/rfc1558.txt
- https://errata.rfc-editor.org/rfc1558
- https://www.rfc-editor.org/rfc/rfc1487.html
- https://www.rfc-editor.org/rfc/rfc1488.html
- https://www.rfc-editor.org/info/rfc1960/
- https://www.rfc-editor.org/rfc/rfc1960.html
- https://www.rfc-editor.org/info/rfc2254/
- https://www.rfc-editor.org/rfc/rfc2254.html
- https://www.rfc-editor.org/info/rfc4511/
- https://www.rfc-editor.org/rfc/rfc4511.html
- https://www.rfc-editor.org/info/rfc4515/
- https://www.rfc-editor.org/rfc/rfc4515.html
- https://heng.lu/running-code-primary-the-patch-needed-to-preserve-the-internet-original-design/
- https://heng.lu/minimum-initial-specification-localized-future-decision-voluntary-adoption-internet-coordination-system/
- https://heng.lu/on-reality-layers-symbolic-power-and-why-clarity-feels-so-hostile/
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
