Repository navigation
FIX: Detect percent-encoded filters and hex-escaped wildcards in LDAPInjectionOutputScorer (#3324) - #3682
Merged
Roman Lutz (romanlutz) merged 6 commits intoNov 2, 2026
Conversation
…InjectionOutputScorer (microsoft#3324)
…PInjectionOutputScorer (microsoft#3324) Signed-off-by: Hrushikesh Ramilla <ramillahrushikesh@gmail.com>
Preserve custom pattern matching and decode only LDAP filter fields once. Add persisted-score and boundary regressions for encoded attribute names, benign filters, literal escapes, and double encoding. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Integrate microsoft/PyRIT main at f02928e. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Roman Lutz (romanlutz)
approved these changes
Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR addresses the LDAP injection detection gaps reported in #3324 for
LDAPInjectionOutputScorer(pyrit/score/true_false/regex/ldap_injection_output_scorer.py):RFC 4515 hex-escaped wildcards (
\2a/\2A):Under RFC 4515 Section 3, asterisks inside search filter assertion values can be escaped as
\2aor\2A. Previously,Filter Break SequenceandAlways-True Clauseexpected literal*, so payloads with hex-escaped wildcards (such as\2a)(uid=*)or)(cn=\2a)) and the all-wildcards-encoded case (such as\2a)(uid=\2a)) bypassed detection completely.Filter Break SequenceandAlways-True Clauseto support\2aand\2A.Percent-encoded filter delimiters and characters:
In web requests and endpoints, LDAP metacharacters are commonly URL/percent-encoded (
%28for(,%29for),%2afor*,%3dfor=,%7cfor|,%26for&,%21for!).Filter Break Sequence,Always-True Clause,Boolean Operator Injection, andNull Byte Filter Terminationto recognize both plain and percent-encoded characters (e.g.,%2a%29%28uid=%2a%29,%29%28cn=%2a%29,%29%7c%28objectClass=%2a%29,admin*%29%00).LDAP URLs with search filter queries (RFC 4516):
Added a new
LDAP URL Filter Injectionpattern that detectsldap://andldaps://URLs carrying search filter queries (e.g.,ldap://127.0.0.1/dc=example,dc=com???%28uid=%2a%29orldap://localhost:389/???%2a%29%28uid=%2a%29).Addresses the LDAP injection portion of #3324 (following the split PR guidance in #3324 and sister PRs #3262, #3326, #3597, #3679).
Tests and Documentation
tests/unit/score/regex/test_ldap_injection_output_scorer.py:\2a,\2A), URL-encoded wildcards (%2a,%2A), all-wildcards-encoded filter breaks, percent-encoded clauses, and LDAP/LDAPS URLs.Always-True ClauseandLDAP URL Filter Injection.ldap_injection_output_scorer.py.uv run pytest tests/unit/score/regex/test_ldap_injection_output_scorer.py: 84 passed.uv run pytest tests/unit/score/regex/: 1,242 passed (100% green).uv run ruff check pyrit/score/true_false/regex/ldap_injection_output_scorer.py tests/unit/score/regex/test_ldap_injection_output_scorer.py: Clean.uv run ruff format --check pyrit/score/true_false/regex/ldap_injection_output_scorer.py tests/unit/score/regex/test_ldap_injection_output_scorer.py: Clean.uv run ty check pyrit/score/true_false/regex/ldap_injection_output_scorer.py tests/unit/score/regex/test_ldap_injection_output_scorer.py: Clean.