Invoke-PSUScript called from an API endpoint ignores scoped script permissions and requires a parent-scope automation permission ("The role specified does not have access to this resource")

Invoke-PSUScript called from an API endpoint ignores scoped script permissions and requires a parent-scope automation permission ("The role specified does not have access to this resource")

avatar

------------------------------------------------------------

Product: PowerShell Universal
Version: 2026.3.3
Hosting: IIS
OS: Windows Server 2025
Database: SQL Server

------------------------------------------------------------

CONTEXT

The script is not run directly by the user. The user calls an authenticated API endpoint, and it is the endpoint code that runs the script with Invoke-PSUScript:

User (AD group member, role DLG-PSU_2424)
-> calls API endpoint (Authentication enabled, restricted to DLG-PSU_2424)
-> endpoint code runs Invoke-PSUScript
-> script Add-UserToADGroup.ps1

Endpoint code (simplified):

param($Param1)

Invoke-PSUScript -Name '<Folder>\Add-UserToADGroup\Add-UserToADGroup.ps1' -Parameters $Param -Wait

The endpoint itself is reachable and executes correctly: the access denied error is raised by the Invoke-PSUScript call inside the endpoint. Replacing the Invoke-PSUScript line with $ClaimsPrincipal returns the expected identity, role and permissions (see EVIDENCE below), and replacing it with Get-PSUScript on the same script succeeds.

------------------------------------------------------------

SUMMARY

When a custom role is granted scoped permissions on a single script (or even the global automation.scripts/execute permission), calling Invoke-PSUScript from an API endpoint fails with:

"Permission denied. The role specified does not have access to this resource"

Get-PSUScript on the same script, from the same endpoint, succeeds with the same role, which shows that the scoped permission is matched correctly for read access. The call only succeeds when a parent-scope permission is added to the role: either automation/read or automation/execute. Both grant access to all automation resources, which defeats folder/script-level delegation.

EXPECTED BEHAVIOR

A role with automation.scripts/view + read + execute permissions scoped to a single script should be able to run that script through Invoke-PSUScript from an API endpoint, without needing access to the whole automation scope.

ACTUAL BEHAVIOR

Invoke-PSUScript, called from the API endpoint, is denied unless the role has automation/read or automation/execute.

------------------------------------------------------------

CONFIGURATION

Role: DLG-PSU_2424
- Claim type: http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid
- Claim value: AD group SID
- Role permissions: automation.scripts/view

Scoped permissions (created from the script's Permissions dialog, assigned to the role):
- automation.scripts.<Folder>\Add-UserToADGroup\Add-UserToADGroup.ps1/read
- automation.scripts.<Folder>\Add-UserToADGroup\Add-UserToADGroup.ps1/execute

API endpoint:
- Authentication: enabled
- Roles: DLG-PSU_2424, DLG-PSU_Administrator
- Execution roles: DLG-PSU_2424, DLG-PSU_Administrator

------------------------------------------------------------

EVIDENCE: CLAIMS ARE CORRECTLY RESOLVED

Returning $ClaimsPrincipal from the endpoint (called by a member of the AD group) shows:

Type : http://schemas.microsoft.com/ws/2008/06/identity/claims/role
Value : DLG-PSU_2424

Type : PSUPermission
Value : automation.scripts/view

Type : PSUPermission
Value : automation.scripts.<Folder>\\Add-UserToADGroup\\Add-UserToADGroup.ps1(.*)/read

Type : PSUPermission
Value : automation.scripts.<Folder>\\Add-UserToADGroup\\Add-UserToADGroup.ps1(.*)/execute

The role and permissions are correctly present in the identity. Cached claims were ruled out (new sign-in after every change).

------------------------------------------------------------

STEPS TO REPRODUCE

1. Create a custom role with only automation.scripts/view.
2. Create a script in a subfolder, open its Permissions dialog and grant read and execute to the role.
3. Create an authenticated API endpoint restricted to that role, containing:

Get-PSUScript -Name '<Folder>\Add-UserToADGroup\Add-UserToADGroup.ps1' # Test A
Invoke-PSUScript -Name '<Folder>\Add-UserToADGroup\Add-UserToADGroup.ps1' # Test B

4. Call the endpoint as a user holding only that role.

------------------------------------------------------------

TEST MATRIX (all tests run from inside the API endpoint)

Additional permissions on the role Get-PSUScript Invoke-PSUScript
-------------------------------------------------------------------------------------------
1. none OK DENIED
2. none, with -Wait OK DENIED
3. none, with -Integrated OK DENIED
4. automation.jobs/read OK DENIED
5. automation.scripts/execute + automation.jobs/create OK DENIED
6. automation.environments/read OK DENIED
7. automation.jobs/* OK DENIED
8. automation.computers/read OK DENIED
9. automation/read OK OK
10. automation/execute OK OK
11. automation/* OK OK

------------------------------------------------------------

ANALYSIS

- The scoped permission pattern is matched correctly for read (test A succeeds from the endpoint).
- The failure is not related to jobs, environments or computers (tests 4, 6 to 8).
- Even the global automation.scripts/execute is not sufficient (test 5).
- Any permission at the parent automation level, regardless of access type (read or execute), unlocks the call (tests 9 and 10).

This suggests that the authorization check performed by Invoke-PSUScript, when called from an API endpoint, evaluates a resource at the automation scope level instead of automation.scripts.<path>, so scoped permissions are never considered.

------------------------------------------------------------

IMPACT

Folder- and script-scoped delegation (as described in the Permissions documentation) cannot be used for scripts invoked from API endpoints. The only working workaround is granting automation/read or automation/execute, which exposes or allows execution of every script on the instance, including scripts running under privileged credentials.

All Comments (0)