Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
de3bb1d
adding azdo test suit and preview module
SebastianClaesson May 11, 2025
90404c8
Adding readme
SebastianClaesson May 11, 2025
8d9f3c2
adding updated readme
SebastianClaesson May 11, 2025
aa8b936
Adding Azdo tests
SebastianClaesson Dec 9, 2025
8d7318a
Updating readme and setting functions in the correct folder
SebastianClaesson Dec 9, 2025
94d7523
Merge branch 'maester365:main' into feature/azdo
SebastianClaesson Dec 9, 2025
fc83a14
Relocating parent folder
SebastianClaesson Dec 9, 2025
13c55d8
Merge branch 'feature/azdo' of https://github.com/SebastianClaesson/m…
SebastianClaesson Dec 9, 2025
86125a8
updating readmes and powershell scripts
SebastianClaesson Dec 11, 2025
0ba07d8
Fix typos and improve formatting in documentation
SamErde Jan 21, 2026
c12ab8b
Refine grammar in Test-AzdoArtifactsExternalPackageProtectionToken.md
SamErde Jan 21, 2026
bdfa2ff
Fix typo in description of security policy check
SamErde Jan 21, 2026
f4f68c7
Fix grammar and punctuation in Test-AzdoAuditStream.md
SamErde Jan 21, 2026
ca1d7da
Refine description for Test-AzdoAuditStream function
SamErde Jan 21, 2026
6005abd
Fix grammar and clarity in Test-AzdoEnforceAADConditionalAccess.md
SamErde Jan 21, 2026
0c4b342
Update README.md with clearer test descriptions
SamErde Jan 21, 2026
25dcaff
Update powershell/public/maester/azdo/Test-AzdoOrganizationLimitJobAu…
SamErde Jan 21, 2026
9d40147
Merge branch 'maester365:main' into feature/azdo
SebastianClaesson Jan 23, 2026
acd7ecc
Renaming Azdo to AzureDevOps
SebastianClaesson Jan 23, 2026
2fa5cb3
Fixed typo and information
SebastianClaesson Jan 23, 2026
046bfea
Updated description
SebastianClaesson Jan 23, 2026
223fa56
Removing dot sourcing as the test cmdlets are to be part of the module
SebastianClaesson Jan 23, 2026
5adefc1
Merge branch 'feature/azdo' of https://github.com/SebastianClaesson/m…
SebastianClaesson Jan 23, 2026
0a4eb89
Fix typo in SSH authentication documentation
SamErde Jan 31, 2026
09caf7f
Fix typo in Test-AzdoOrganizationStageChooser.md
SamErde Jan 31, 2026
04fd334
Update powershell/public/maester/azuredevops/Test-AzdoOrganizationLim…
SamErde Jan 31, 2026
a7e76b6
Merge branch 'maester365:main' into feature/azdo
SebastianClaesson Feb 5, 2026
0283fed
Corrected the remediation action, that it should toggle OFF.
SebastianClaesson Feb 18, 2026
ce324f0
Adding logic to manage region specific decimal separator.
SebastianClaesson Feb 18, 2026
3db1a0a
Changed function calls to be singular and not plural
SebastianClaesson Feb 18, 2026
9703bf6
Updating description and action
SebastianClaesson Feb 18, 2026
a1c92df
Removing white-space
SebastianClaesson Feb 18, 2026
4228988
Adding correct value returned by function to define success or fail
SebastianClaesson Feb 18, 2026
9f715eb
Removed whitespace
SebastianClaesson Feb 18, 2026
aa9fc65
Fixed typo
SebastianClaesson Feb 18, 2026
0d320a0
Added invert logic to keep cleaner code.
SebastianClaesson Feb 18, 2026
ed5968d
Fixed typo
SebastianClaesson Feb 18, 2026
a7cde22
Fixed typo
SebastianClaesson Feb 18, 2026
34c59e2
Removed whitespace
SebastianClaesson Feb 18, 2026
91d9279
Merge branch 'main' into feature/azdo
merill Feb 18, 2026
0c8dc85
Fixed missing comma, after merging conflicts
merill Feb 18, 2026
1f6f48a
Fix typo in remediation action for SSH policy
SamErde Feb 18, 2026
ec241a9
Fix spelling error in Test-AzdoOrganizationOwner.ps1
SamErde Feb 18, 2026
cf2a3d7
Clean up comments and documentation in PowerShell script
SamErde Feb 18, 2026
9667b94
Added severity configuration to maester-config instead
SebastianClaesson Feb 19, 2026
4bff7a1
Merge branch 'feature/azdo' of https://github.com/SebastianClaesson/m…
SebastianClaesson Feb 19, 2026
0fdb4f6
Fixed connection check, Fixed typos, Fixed grammar issues
SebastianClaesson Feb 19, 2026
08f7481
Fixed more grammar issues
SebastianClaesson Feb 19, 2026
d1c6100
Changing title to Maester contributor
SebastianClaesson Feb 19, 2026
4e3521c
Adding rowbreak in between to make the message look nicer
SebastianClaesson Feb 19, 2026
19a7c57
Adding whitespace
SebastianClaesson Feb 19, 2026
7c484f8
Fixed grammar and new instructions for Azure DevOps suite
SebastianClaesson Feb 19, 2026
e30c0e5
Changing severity and adding new tests
SebastianClaesson Feb 25, 2026
a724202
Adding more tests.
SebastianClaesson Feb 25, 2026
6142352
Adding WIP
SebastianClaesson Feb 25, 2026
9b7c637
Fix punctuation and wording in installation.md
SamErde Feb 25, 2026
0d0b169
Adding blogpost and proof read content
SebastianClaesson Feb 27, 2026
c109973
Merge branch 'feature/azdo' of https://github.com/SebastianClaesson/m…
SebastianClaesson Feb 27, 2026
edca956
Adding another iteration
SebastianClaesson Feb 27, 2026
3a6ecdd
Reverting maester-config
SebastianClaesson Feb 27, 2026
5f499e2
Adding azdo.1036
SebastianClaesson Feb 27, 2026
4138d8f
Fix typo in maester-config.json title
SamErde Feb 27, 2026
70946d7
Adding updated files, with grammar checks and spellchecks. Removed in…
SebastianClaesson Feb 27, 2026
e46b514
Merge branch 'feature/azdo' of https://github.com/SebastianClaesson/m…
SebastianClaesson Feb 27, 2026
3d5114c
Removing trailing backslashes.
SebastianClaesson Mar 3, 2026
c69daa4
Added logic for "AccessDeniedException".
SebastianClaesson Mar 3, 2026
ab1bcee
Update tests/Maester/AzureDevOps/Test-AzdoEnforceAADConditionalAccess…
SamErde Mar 9, 2026
ff2ae53
Update Test-Azdo.Tests.ps1
SebastianClaesson Mar 9, 2026
a414df8
Fix verbose output for group member descriptor
SamErde Mar 10, 2026
868bf2f
Remove Azure DevOps test entries from FunctionsToExport in module man…
SamErde Mar 10, 2026
5d8976e
Added ADOPS module availability check (Get-Command + Get-ADOPSConnect…
SebastianClaesson Mar 18, 2026
1ebcbc3
Update error handling for Get-ADOPSConnection command
SamErde Mar 19, 2026
a334f1c
Add 'NotConnectedAzureDevOps' to SkippedBecause parameter
SamErde Mar 19, 2026
c1cea53
Moving powershell helper functions
SebastianClaesson Mar 19, 2026
7a2e267
Add Azure DevOps functions to FunctionsToExport in module manifest
SebastianClaesson Mar 19, 2026
963a5af
Refactor currentQuantity assignment for backwards compatibility
SamErde Mar 30, 2026
e70c279
refactor: result handling for organization owner fetch failure
SamErde Mar 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion powershell/Maester.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,44 @@
'Test-MtEntitlementManagementInactivePolicies',
'Test-MtEntitlementManagementOrphanedResources',
'Test-MtEntitlementManagementValidApprovers',
'Test-MtEntitlementManagementValidResourceRoles'
'Test-MtEntitlementManagementValidResourceRoles',
'Test-AzdoAllowRequestAccessToken',
'Test-AzdoAllowTeamAdminsInvitationsAccessToken',
'Test-AzdoArtifactsExternalPackageProtectionToken',
'Test-AzdoAuditStream',
'Test-AzdoDisableGlobalPATCreation',
'Test-AzdoEnableLeakedPersonalAccessTokenAutoRevocation',
'Test-AzdoEnforceAADConditionalAccess',
'Test-AzdoExternalGuestAccess',
'Test-AzdoFeedbackCollection',
'Test-AzdoLogAuditEvent',
'Test-AzdoOrganizationAutomaticEnrollmentAdvancedSecurityNewProject',
'Test-AzdoOrganizationBadgesArePrivate',
'Test-AzdoOrganizationCreationClassicBuildPipeline',
'Test-AzdoOrganizationCreationClassicReleasePipeline',
'Test-AzdoOrganizationCreationRestriction',
'Test-AzdoOrganizationLimitJobAuthorizationScopeNonReleasePipeline',
'Test-AzdoOrganizationLimitJobAuthorizationScopeReleasePipeline',
'Test-AzdoOrganizationLimitVariablesAtQueueTime',
'Test-AzdoOrganizationOwner',
'Test-AzdoOrganizationProtectAccessToRepository',
'Test-AzdoOrganizationRepositorySettingsDisableCreationTFVCRepo',
'Test-AzdoOrganizationRepositorySettingsGravatarImage',
'Test-AzdoOrganizationStageChooser',
'Test-AzdoOrganizationStorageUsage',
'Test-AzdoOrganizationTaskRestrictionsDisableMarketplaceTask',
'Test-AzdoOrganizationTaskRestrictionsDisableNode6Task',
'Test-AzdoOrganizationTaskRestrictionsShellTaskArgumentValidation',
'Test-AzdoOrganizationTriggerPullRequestGitHubRepository',
'Test-AzdoProjectCollectionAdministrator',
'Test-AzdoPublicProject',
'Test-AzdoResourceUsageProject',
'Test-AzdoResourceUsageWorkItemTag',
'Test-AzdoRestrictFullScopePersonalAccessToken',
'Test-AzdoRestrictPersonalAccessTokenLifespan',
'Test-AzdoSSHAuthentication',
'Test-AzdoThirdPartyAccessViaOauth',
'Test-AzdoValidateSshKeyExpiration'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()
Expand Down
2 changes: 1 addition & 1 deletion powershell/public/Add-MtTestResultDetail.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function Add-MtTestResultDetail {
[ValidateSet('NotConnectedAzure', 'NotConnectedExchange', 'NotConnectedGraph', 'NotDotGovDomain', 'NotLicensedEntraIDP1', 'NotConnectedSecurityCompliance', 'NotConnectedTeams',
'NotLicensedEntraIDP2', 'NotLicensedEntraIDGovernance', 'NotLicensedEntraWorkloadID', 'NotLicensedExoDlp', "LicensedEntraIDPremium", 'NotSupported', 'Custom',
'NotLicensedMdo', 'NotLicensedMdoP2', 'NotLicensedMdoP1', 'NotLicensedAdvAudit', 'NotLicensedEop', 'Error', 'NotSupportedAppPermission', 'LimitedPermissions', 'NotLicensedDefenderXDR',
'NotLicensedCustomerLockbox','NotAuthorized', 'NotLicensedIntune'
'NotLicensedCustomerLockbox','NotAuthorized', 'NotLicensedIntune', 'NotConnectedAzureDevOps'
)]
[string] $SkippedBecause,

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Request access to Azure DevOps by e-mail notifications to administrators **should be** disabled.

Rationale: Access control to Azure DevOps is to be a controlled process where access is granted and tracked.

#### Remediation action:
Disable the policy to stop these requests and notifications.
1. Sign in to your organization.
2. Choose Organization settings.
3. Select Policies, locate the Request Access policy and toggle it to off.
4. Provide the URL to your internal process for gaining access. Users see this URL in the error report when they try to access the organization or a project within the organization that they don't have permission to access.

**Results:**
Comment thread
SamErde marked this conversation as resolved.
When users try to access a project without the required permissions, the error message includes the request access URL. This link is shown on the error page to maintain confidentiality, regardless of whether the project exists.

#### Related links

* [Azure DevOps Security - Disable your organization's Request Access policy](https://go.microsoft.com/fwlink/?linkid=2113172)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<#
.SYNOPSIS
Returns a boolean depending on the configuration.

.DESCRIPTION
Checks the status of the 'Request Access' policy in Azure DevOps to prevent users from requesting access to your organization or projects.
When this policy is enabled, users can request access, and administrators receive email notifications for review and approval.
Disabling the policy stops these requests and notifications, helping you control access more tightly.

https://go.microsoft.com/fwlink/?linkid=2113172

.EXAMPLE
```
Test-AzdoAllowRequestAccessToken
```

Returns a boolean depending on the configuration.

.LINK
https://maester.dev/docs/commands/Test-AzdoAllowRequestAccessToken
#>

function Test-AzdoAllowRequestAccessToken {
[CmdletBinding()]
[OutputType([bool])]
param()

if ($null -eq (Get-ADOPSConnection)['Organization']) {
Write-Verbose 'Not connected to Azure DevOps'
Add-MtTestResultDetail -SkippedBecause Custom -SkippedCustomReason 'Not connected to Azure DevOps'
return $null
}

$UserPolicies = Get-ADOPSOrganizationPolicy -PolicyCategory 'User' -Force
$Policy = $UserPolicies.policy | where-object -property name -eq 'Policy.AllowRequestAccessToken'
$result = $Policy.effectiveValue
if ($result) {
$resultMarkdown = "When enabled, this policy allows users to request access, triggering email notifications to administrators for review and approval."
} else {
$resultMarkdown = "Disabling the policy stops these requests and notifications."
}

Add-MtTestResultDetail -Result $resultMarkdown

return $result
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Access to Azure DevOps **should be** a controlled process managed by the IAM team or the appropriate Azure DevOps administrator roles.

Rationale: By default, all administrators can invite new users to their Azure DevOps organization. Disabling this policy prevents Team and Project Administrators from inviting new users.
Project Collection Administrators (PCAs) can still add new users to the organization regardless of the policy status. Additionally, if a user is already a member of the organization, Project and Team Administrators can add that user to specific projects.

#### Remediation action:
Disable the policy to stop these invitations.
1. Sign in to your organization.
2. Choose Organization settings.
3. Select Policies, locate the **Allow team and project administrators to invite new users** policy and toggle it to off.
4. Now, only Project Collection Administrators can invite new users to Azure DevOps.

> Project and Team Administrators can directly add users to their projects through the permissions blade. However, if they attempt to add users through the Add Users button located in the Organization settings > Users section, it's not visible to them. Adding a user directly through Project settings > Permissions doesn't result in the user appearing automatically in the Organization settings > Users list. For the user to be reflected in the Users list, they must sign in to the system.

#### Related links

* [Azure DevOps Security - Restrict administrators from inviting new users](https://aka.ms/azure-devops-invitations-policy)
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<#
.SYNOPSIS
Returns a boolean depending on the configuration.

.DESCRIPTION
By default, all administrators can invite new users to their Azure DevOps organization.
Disabling this policy prevents Team and Project Administrators from inviting new users or adding Entra groups.
However, Project Collection Administrators (PCAs) can still add new users and Entra groups to the organization regardless of the policy status.
Additionally, if a user is already a member of the organization, Project and Team Administrators can add that user to specific projects.

https://aka.ms/azure-devops-invitations-policy

.EXAMPLE
```
Test-AzdoAllowTeamAdminsInvitationsAccessToken
```

Returns a boolean depending on the configuration.

.LINK
https://maester.dev/docs/commands/Test-AzdoAllowTeamAdminsInvitationsAccessToken
#>

function Test-AzdoAllowTeamAdminsInvitationsAccessToken {
[CmdletBinding()]
[OutputType([bool])]
param()

if ($null -eq (Get-ADOPSConnection)['Organization']) {
Write-Verbose 'Not connected to Azure DevOps'
Add-MtTestResultDetail -SkippedBecause Custom -SkippedCustomReason 'Not connected to Azure DevOps'
return $null
}

$PrivacyPolicies = Get-ADOPSOrganizationPolicy -PolicyCategory 'User' -Force
$Policy = $PrivacyPolicies.policy | where-object -property name -eq 'Policy.AllowTeamAdminsInvitationsAccessToken'
$result = $Policy.effectiveValue
if ($result) {
$resultMarkdown = "Team and project administrators are allowed to invite new users"
} else {
$resultMarkdown = "Enrolling to your Azure DevOps organization should be a controlled process."
}

Add-MtTestResultDetail -Result $resultMarkdown

return $result
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Externally sourced package versions **should be** manually approved for internal use to prevent malicious packages from a public registry being inadvertently consumed.

Rationale: Previously, Azure Artifacts feeds presented package versions from all of its upstream sources. This includes package versions that were originally pushed to an Azure Artifacts feed (internally sourced) and package versions from common public repositories like npmjs.com, NuGet.org, Maven Central, and PyPI (externally sourced).

Configure a policy for additional security for your private feeds by limiting access to externally sourced packages when internally sourced packages are already present. This change provides a new layer of protection and prevents malicious packages from a public registry being inadvertently consumed. It does not affect any package versions that are already in use or cached in your feed.

#### Remediation action:

Enable the policy to opt-in for additional protective behavior.

1. Sign in to your organization.
2. Choose Organization settings.
3. Select policies under the security section
4. In the security policies section, toggle on ‘Additional protections when using public package registries’

**Results:**
The security behavior applies:
when an internally sourced version is already in your feed, or
when consuming a package from your feed for the first time (i.e. it is not yet in your feed), and at least one of the versions available from an upstream is internally sourced.
With the new behavior, any versions from the public registry will be blocked and not made available to download. You are able to configure the upstream behavior to allow externally sourced package versions if you choose to.

#### Related links

* [Microsoft Devblogs - Changes to Azure Artifacts Upstream Behavior](https://devblogs.microsoft.com/devops/changes-to-azure-artifact-upstream-behavior/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<#
.SYNOPSIS
Returns a boolean depending on the configuration.

.DESCRIPTION
Checks the policy for additional security for your private feeds by limiting access to externally sourced packages when internally sourced packages are already present.
This provides a new layer of security, which prevents malicious packages from a public registry being inadvertently consumed.
These changes will not affect any package versions that are already in use or cached in your feed.

https://devblogs.microsoft.com/devops/changes-to-azure-artifact-upstream-behavior

.EXAMPLE
```
Test-AzdoArtifactsExternalPackageProtectionToken
```

Returns a boolean depending on the configuration.

.LINK
https://maester.dev/docs/commands/Test-AzdoArtifactsExternalPackageProtectionToken
#>

function Test-AzdoArtifactsExternalPackageProtectionToken {
[CmdletBinding()]
[OutputType([bool])]
param()

if ($null -eq (Get-ADOPSConnection)['Organization']) {
Write-Verbose 'Not connected to Azure DevOps'
Add-MtTestResultDetail -SkippedBecause Custom -SkippedCustomReason 'Not connected to Azure DevOps'
return $null
}

$SecurityPolicies = Get-ADOPSOrganizationPolicy -PolicyCategory 'Security' -Force
$Policy = $SecurityPolicies.policy | where-object -property name -eq 'Policy.ArtifactsExternalPackageProtectionToken'
$result = $Policy.effectiveValue
if ($result) {
$resultMarkdown = "Your Azure DevOps tenant limits access to externally sourced packages when internally sourced packages are already present."
} else {
$resultMarkdown = "Your tenant should prefer to use internal source packages when present"
}

Add-MtTestResultDetail -Result $resultMarkdown

return $result
}
24 changes: 24 additions & 0 deletions powershell/public/maester/azuredevops/Test-AzdoAuditStream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Audit logs **should be** retained according to your organization's needs and protected from purging.

Rationale: Send auditing data to other Security Incident and Event Management (SIEM) tools and open new possibilities, such as the ability to trigger alerts for specific events, create views on auditing data, and perform anomaly detection. Setting up a stream also allows you to store more than 90-days of auditing data, which is the maximum amount of data that Azure DevOps keeps for your organizations.

#### Remediation action:

Create an audit stream, which sends data to other locations for further processing.

1. Sign in to your organization.
2. Choose Organization settings.
3. Select Auditing.
> If you don't see Auditing in Organization Settings, then auditing is not currently enabled for your organization. Someone in the organization owner or Project Collection Administrators (PCAs) group must enable Auditing in Organization Policies. You will then be able to see events on the Auditing page if you have the appropriate permissions.
1. Go to the Streams tab, and then select New stream.
2. Select the stream target that you want to configure, and then select from the following instructions to set up your stream target type.
1. Splunk
2. Event Grid
3. Azure Monitor Log

**Results:**
Audit streams represent a pipeline that flows audit events from your Azure DevOps organization to a stream target. At least every half hour, new audit events are bundled and streamed to your targets.

#### Related links

* [Azure DevOps Security - Create audit streaming](https://learn.microsoft.com/en-us/azure/devops/organizations/audit/auditing-streaming?view=azure-devops)
62 changes: 62 additions & 0 deletions powershell/public/maester/azuredevops/Test-AzdoAuditStream.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<#
.SYNOPSIS
Returns a boolean depending on the configuration.

.DESCRIPTION
Sends auditing data to Security Incident and Event Management (SIEM) tools and opens new possibilities,
such as the ability to trigger alerts for specific events, create views on auditing data, and perform
anomaly detection. Setting up a stream also allows you to store more than 90-days of auditing data,
which is the maximum amount of data that Azure DevOps keeps for your organizations.

https://learn.microsoft.com/en-us/azure/devops/organizations/audit/auditing-streaming?view=azure-devops

.EXAMPLE
```
Test-AzdoAuditStream
```

Returns a boolean depending on the configuration.

.LINK
https://maester.dev/docs/commands/Test-AzdoAuditStream
#>

function Test-AzdoAuditStream {
[CmdletBinding()]
[OutputType([bool])]
param()

if ($null -eq (Get-ADOPSConnection)['Organization']) {
Write-Verbose 'Not connected to Azure DevOps'
Add-MtTestResultDetail -SkippedBecause Custom -SkippedCustomReason 'Not connected to Azure DevOps'
return $null
}

$AuditStreams = Get-ADOPSAuditStreams -ErrorAction SilentlyContinue

if ($null -eq $AuditStreams) {
$Message = "Audit Streams was not found. This may be due to insufficient permissions or the Azure DevOps Organization is not backed by an Entra ID tenant.
Please see [Manage Audit Streams](https://learn.microsoft.com/en-us/azure/devops/organizations/audit/auditing-streaming?view=azure-devops#prerequisites)"
Write-Verbose $Message
Add-MtTestResultDetail -SkippedBecause Custom -SkippedCustomReason $Message
return $null
} else {
if ($AuditStreams) {
if ('Enabled' -in $AuditStreams.status) {
$resultMarkdown = "Audit logs have been configured for long-term storage and purge protection."
$result = $true
} else {
$resultMarkdown = "Audit Streams have been configured for long-term storage and purge protection but is not enabled."
$result = $false
}
} else {
$resultMarkdown = "Audit Streams have not been configured for long-term storage and purge protection."
$result = $false
}

Add-MtTestResultDetail -Result $resultMarkdown

return $result
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Restrict creation of global Personal Access Tokens (PATs) **should be** enabled.

#### Prerequisites

- Your organization must be linked to a Microsoft Entra tenant.
- You must be an Azure DevOps Administrator to configure tenant policies.

#### Rationale

Global PATs can be used across all accessible organizations. Restricting their creation ensures tokens are confined to a single org, enforcing least privilege and reducing cross-org exposure risk.

#### Remediation action

Enable the tenant policy to stop creation of global PATs.
1. Sign in to your organization (https://dev.azure.com/{Your_Organization}).
2. Select Organization settings (gear icon).
3. Select Microsoft Entra, locate the "Restrict global personal access token creation" policy.
4. Move the toggle to On.

#### Allowlist and exceptions

- Add Microsoft Entra users or groups to the allowlist to exempt them from the restriction.
- Prefer groups over individual users to avoid identity residency problems.

**Existing PATs:**

Existing global PATs remain valid until they expire; the policy affects only newly created tokens.

**Results:**

When enabled, new PATs must be associated with a single Azure DevOps organization. Users not on the allowlist cannot create global tokens.


#### Related links
* [Learn - Restrict creation of global PATs (tenant policy)](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/manage-pats-with-policies-for-administrators?view=azure-devops#restrict-creation-of-global-pats-tenant-policy)
Loading