Fix AD provider LDAP escaping scope issue in ScriptMethod execution#158
Merged
Fix AD provider LDAP escaping scope issue in ScriptMethod execution#158
Conversation
Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix runtime error in IdLE.Provider.AD for Protect-LdapFilterValue
Fix AD provider LDAP escaping scope issue in ScriptMethod execution
Feb 8, 2026
blindzero
approved these changes
Feb 8, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a runtime failure in the AD provider by making the LDAP filter escaping helper available to adapter ScriptMethods (which don’t capture the parent function scope), and adds regression tests around escaping behavior.
Changes:
- Converts LDAP escaping helper into an adapter
ScriptMethod(ProtectLdapFilterValue) so other adapterScriptMethods can call it via$this. - Updates AD adapter methods (
GetUserByUpn,GetUserBySam,ListUsers) to call$this.ProtectLdapFilterValue(...). - Adds Pester coverage intended to validate escaping behavior and the ScriptMethod scoping regression.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/IdLE.Provider.AD/Private/New-IdleADAdapter.ps1 |
Moves LDAP escaping into an adapter ScriptMethod and updates callers to use $this. |
tests/Providers/ADIdentityProvider.Tests.ps1 |
Adds tests for escaping and for calling the helper from within another ScriptMethod. |
Comments suppressed due to low confidence (1)
src/IdLE.Provider.AD/Private/New-IdleADAdapter.ps1:78
- Same issue as above:
$escapedSamis injected into a single-quoted Get-ADUser-Filterstring without escaping'. This can cause parse errors or filter injection for sAMAccountName values containing an apostrophe.
$escapedSam = $this.ProtectLdapFilterValue($SamAccountName)
$params = @{
Filter = "sAMAccountName -eq '$escapedSam'"
Properties = @('Enabled', 'DistinguishedName', 'ObjectGuid', 'UserPrincipalName', 'sAMAccountName')
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
blindzero
requested changes
Feb 8, 2026
Owner
blindzero
left a comment
There was a problem hiding this comment.
@copilot check open suggestion comments from reviews
…am and test real implementation Co-authored-by: blindzero <13959569+blindzero@users.noreply.github.com>
blindzero
approved these changes
Feb 8, 2026
Owner
blindzero
left a comment
There was a problem hiding this comment.
@copilot check open suggestion comments from reviews
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.
Protect-LdapFilterValuein New-IdleADAdapter.ps1ProtectLdapFilterValueas a ScriptMethod on the adapter object$this.ProtectLdapFilterValue()instead ofProtect-LdapFilterValueProtect-LdapFilterValueto avoid confusionGetUserBySam(consistent withGetUserByUpnandListUsers)Original prompt
This section details on the original issue you should resolve
<issue_title>IdLE.Provider.AD fails at runtime because Protect-LdapFilterValue is not in scope for adapter ScriptMethods</issue_title>
<issue_description>## Description
The Active Directory identity provider fails at runtime when resolving an identity by sAMAccountName. The error indicates that the helper function
Protect-LdapFilterValueis not recognized, causing identity resolution to fail and consequently breaking steps likeIdLE.Step.DisableIdentity.This is a regression/defect in the AD adapter implementation:
Protect-LdapFilterValueis defined as a nested function withinNew-IdleADAdapter, but it is referenced fromScriptMethodmembers (e.g.,GetUserBySam). When these ScriptMethods are invoked later, the nested function is out of scope, so PowerShell cannot resolve it.Impact: AD-based workflows (e.g., Leaver
DisableIdentity) cannot execute reliably.Steps to Reproduce
IdLE.Step.DisableIdentitywith anIdentityKeythat resolves via sAMAccountName (e.g.,foo.bar).Example minimal workflow step:
Example plan creation (provider setup omitted here, see Additional Context):
Expected Behavior
IdLE.Step.DisableIdentityresolves the identity using the AD provider and disables the AD account.Actual Behavior
The step fails with an exception chain that ends in:
Example error (truncated):
Environment
Root Cause Analysis (Proposed)
Protect-LdapFilterValueis implemented as a nested function insideNew-IdleADAdapter.ps1.ScriptMethods (e.g.,GetUserBySam) on an object created byNew-IdleADAdapter.ScriptMethodruns, it does not retain the lexical scope ofNew-IdleADAdapter, therefore the nested function is not visible.Protect-LdapFilterValueinside theScriptMethodthrows a command not recognized error.Proposed Fix
Make the LDAP escaping helper available in the execution scope of the adapter ScriptMethods in a testable, non-global way.
Preferred approach (Option A):
ScriptMethodon the adapter object, e.g.ProtectLdapFilterValue, implemented directly on the adapter.GetUserBySam,GetUserByUpn, any search methods) to call:$this.ProtectLdapFilterValue($value)Alternative approach (Option B):
Protect-LdapFilterValueto a private module function file (e.g.,Private/Protect-LdapFilterValue.ps1) within the AD provider module and ensure it is dot-sourced/exported appropriately for internal use (no global pollution), then reference it from ScriptMethods.Acceptance Criteria
IdLE.Step.DisableIdentityagainst AD no longer fails with missingProtect-LdapFilterValue.Test Plan
Unit Tests (Pester)
GetUserBySamdoes not throw due to missing helper function.ProtectLdapFilterValuebehavior (escape sequences for\,*,(,), null byte).ResolveIdentitycan callGetUserBySamsuccessfully.Regression Coverage
DisableIdentity...✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.