Skip to content

Reject unescaped special characters in DN values per RFC 4514#588

Merged
cpuschma merged 1 commit into
go-ldap:masterfrom
t2y:refactor-parsedn2
May 16, 2026
Merged

Reject unescaped special characters in DN values per RFC 4514#588
cpuschma merged 1 commit into
go-ldap:masterfrom
t2y:refactor-parsedn2

Conversation

@t2y
Copy link
Copy Markdown
Contributor

@t2y t2y commented May 13, 2026

Background

I ran into a case where ldap.ParseDN accepted a DN like the following without returning an error:

uid=john<doe,ou=engineering,dc=example,dc=com

This prompted me to re-read the DN string specification, and I noticed that several of the special characters listed in RFC 4514 were not being checked for the unescaped form.

Summary

ParseDN previously accepted ", ;, <, >, and NULL (U+0000) in their raw, unescaped form, silently producing AttributeTypeAndValue values that violate the RFC 4514 grammar. Such values can be misinterpreted by downstream
LDAP servers or by string-comparison code that assumes a well-formed DN, which is both a correctness issue and a potential security concern (e.g. DN-based authorization checks operating on a value the server later parses differently).

Changes

  • decodeString now returns an error when it encounters any of ", ;, <, >, or NULL in unescaped form. The hex-escape (\XX) and backslash-escape (\X) forms continue to decode unchanged, so previously valid inputs are unaffected.
  • TestSuccessfulDNParsing is expanded to cover every RFC 4514 §2.4 escape target in both escape forms (e.g. \, and \2C). NULL is covered only in the hex form, as required by the RFC.
  • TestErrorDNParsing and TestDecodeString gain matching negative cases for each unescaped character, so the new rejection path has full coverage.

Notes / Caveats

  • Leading/trailing U+0020 (SPACE) is intentionally left lenient. RFC 4514 requires SPACE at the start/end of a value to be escaped, but the existing whitespace-stripping behavior is relied upon by many real-world inputs. Tightening this is deferred to a separate change to keep this PR backward-compatible for common usage.

Compatibility

This is a behavior change: callers that were (incorrectly) passing raw ", ;, <, >, or NULL into ParseDN will now receive an error instead of a silently malformed DN. Callers using properly escaped input are unaffected.

Disclosure on AI assistance

In the interest of transparency:

  • The core fix in v3/dn.go (rejecting unescaped special characters in decodeString) was designed and written by me.
  • The additional test cases in v3/dn_test.go and the wording of this PR description were drafted with the help of an AI agent. I reviewed every test case against RFC 4514 §2.4 and confirmed the expected behavior locally before submitting.

Happy to adjust or rewrite any part of the AI-assisted content if the maintainers prefer.

References

ParseDN previously accepted ", ;, <, > and NULL (U+0000) in raw form,
silently producing values that violate the RFC 4514 grammar and could
be misinterpreted by downstream LDAP servers or string-comparison code.
decodeString now returns an error when it encounters these characters
unescaped; their hex- and backslash-escaped forms continue to decode
as before. ParseDN tests are expanded to cover every RFC 4514 escape
target in both escape forms, plus the corresponding unescaped-error
cases.

Leading/trailing U+0020 (SPACE) is intentionally left lenient — the
existing whitespace-stripping behavior is depended on by many real
inputs, so enforcing it strictly is deferred.
@t2y
Copy link
Copy Markdown
Contributor Author

t2y commented May 13, 2026

If, for any reason, you would prefer not to change the behavior of ParseDN, would it be better to introduce a separate ValidateDN function instead?

@cpuschma cpuschma self-assigned this May 16, 2026
@cpuschma cpuschma added bug go Pull requests that update go code labels May 16, 2026
@cpuschma
Copy link
Copy Markdown
Member

If, for any reason, you would prefer not to change the behavior of ParseDN, would it be better to introduce a separate ValidateDN function instead?

Having multiple ParseDN functions could cause confusion. I suggest fixing the current implementation and adding a note to the next release instead. After all, the current behaviour is unintended and does not conform to the RFC.

@cpuschma cpuschma merged commit 35356e0 into go-ldap:master May 16, 2026
4 checks passed
@t2y t2y deleted the refactor-parsedn2 branch May 17, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants