This Skill inventories the GitHub Advanced Security for Azure DevOps enablement state for an organization or a single project, and finds repositories that are not protected. It only reads enablement settings, not alerts (for alerts use security-alert-review), and it does not enable any feature: enabling starts billing, so the user must always do it on the web page.
Scope
- By default, audit the entire organization.
- When the user specifies a project (for example "Contoso project"), audit only that project; when specifying repositories, query only those repositories.
- There is no need to list projects first: the repository list already includes the project name.
Connection and authentication
Always use curl to call the Azure DevOps REST API directly; every command carries its own authentication parameters.
- Organization: read the environment variable
AZURE_DEVOPS_ORG(organization name, for examplecontoso). If it is not set, ask the user once; if the user gives a URL, extract the organization name fromhttps://dev.azure.com/{org}orhttps://{org}.visualstudio.com. - Host: apart from
dev.azure.com, the host for the Advanced Security enablement settings API isadvsec.dev.azure.com。 - Token: send the PAT with Basic authentication:
-u ":$AZURE_DEVOPS_PAT"; if onlyAZURE_DEVOPS_EXT_PATis set (the variable used by the Azure CLI azure-devops extension), use that instead. When using a Microsoft Entra ID token instead, switch to-H "Authorization: Bearer $AZURE_DEVOPS_TOKEN". If neither is set, ask the user to setAZURE_DEVOPS_PATin their own terminal and retry, then stop. Read the token only from environment variables: do not ask the user to paste the token into the conversation, and do not print it or write it to a file. - PAT scopes: Advanced Security (Read), Code (Read). This Skill does not need any write permissions.
- Encoding: URL-encode project and repository names in paths (write spaces as
%20); write$in the query string as%24(for example%24top), to avoid expansion by the shell. - Errors: HTTP 401, 403, 203, or an HTML sign-in page in the response means the token is invalid, expired, or lacks permissions; report it and stop. HTTP 404 means the organization, project, or repository is wrong. HTTP 400 with a message containing
VssVersionOutOfRangeExceptionmeans the api-version is not accepted; use the version from the "legacy response" section. - Windows PowerShell: call
curl.exe(not thecurlalias), and write environment variables as$env:AZURE_DEVOPS_PAT; PowerShell does not support<<'EOF', so first write the JSON body to a temporary file, then send it with--data-binary "@body.json".
Field descriptions
Based on Configure GitHub Advanced Security for Azure DevOps features and the REST reference Org Enablement - Get. Advanced Security is now split into two products:GitHub Secret Protection for Azure DevOps(push protection, secret scanning alerts) and GitHub Code Security for Azure DevOps(dependency alerts, CodeQL scanning, security results from third-party tools). The table below describes only what Learn documents:
| Field | Description |
|---|---|
secretProtectionFeatures.secretProtectionEnabled |
Whether Secret Protection is enabled. Once enabled, push protection and repository secret scanning start automatically |
secretProtectionFeatures.blockPushes |
Whether pushes containing secrets are blocked (push protection); only has a value when includeAllProperties=true is present, otherwise it is null |
codeSecurityFeatures.codeSecurityEnabled |
Whether Code Security is enabled |
codeSecurityFeatures.dependencyScanningInjectionEnabled |
Dependency Scanning Injection: automatically adds dependency scanning jobs to pipelines and PR builds targeting the default branch (the UI's Scan for vulnerable dependencies / dependency scanning default setup) |
codeSecurityFeatures.codeQLEnabled |
Whether CodeQL is used default setup;false only means default setup is not used; advanced setup in the pipeline may be used instead |
codeSecurityFeatures.autofixEnabled |
Copilot Autofix (Learn labels it as a limited public preview) |
codeSecurityFeatures.malwareAlertsEnabled |
Whether alerts are generated for malware in dependencies |
enablementOnCreateSettings.enableSecretProtectionOnCreate、enableCodeSecurityOnCreate |
Whether newly created repositories automatically enable the corresponding products; sub-features have additional enableBlockPushesOnCreate、enableCodeQLOnCreate and other flags |
*LastChangedDate、*ChangedBy |
The time and user VSID of the last change to the enabled status |
- The REST documentation explains the boolean field "Null is never explicitly set":
nullmeans it has never been explicitly set, is treated as not enabled, and is noted as "not set" in the results. - The response may also contain
isBundledSKUandcodeSecurityFeatures.dependabotEnabled; the REST reference does not define their meaning: list them as-is without using them to make judgments.
Steps
-
Get the repository name mapping(retrieved once for the entire organization):
curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/git/repositories?api-version=7.1"Use
idto mapname、project.id、project.name、webUrl。isDisabledastrueand mark it "disabled"; those without thedefaultBranchfield are empty repositories and are marked "empty repository". These two categories are not included in the coverage denominator and are listed separately. -
Get the enabled status. For the entire organization:
curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://advsec.dev.azure.com/$AZURE_DEVOPS_ORG/_apis/management/enablement?includeAllProperties=true&api-version=7.2-preview.3"Query only one project:
curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://advsec.dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/management/enablement?includeAllProperties=true&api-version=7.2-preview.3"Query only one repository (
{repository}can be a name or ID):curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://advsec.dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/management/repositories/{repository}/enablement?includeAllProperties=true&api-version=7.2-preview.3"- These resources only have a preview version, so the preview version number must be included.
- Organization and project responses have
enablementOnCreateSettingsandreposEnablementStatus[]; each entry hasprojectId、repositoryId、secretProtectionFeatures、codeSecurityFeatures. The repository response is a single entry. - The project response's
enablementOnCreateSettingsmay benull, meaning the project does not have its own automatic enablement settings; use the organization-level value instead and note this.
-
Evaluate one by one(disabled and empty repositories are skipped):
# Check ✅ ❌ ❓ 1 Secret Protection secretProtectionEnabledistruefalseornull— 2 Push protection blockPushesistruefalse(write "—" when Secret Protection is not enabled)null(withoutincludeAllProperties=true)3 Code Security codeSecurityEnabledistruefalseornull— 4 Dependency scanning automatically added dependencyScanningInjectionEnabledistrue— falseornull: scanning jobs may have been manually added in the pipeline, please confirm5 CodeQL default setup codeQLEnabledistrue— falseornull: advanced setup may be used, please confirm6 Copilot Autofix, malware alerts Only list the current values, do not make judgments When Code Security is not enabled, items 4–6 are written as "—".
-
Automatic enablement for new repositories: at the organization level (and for the user-specified project),
enableSecretProtectionOnCreate、enableCodeSecurityOnCreateistruemarked ✅,falseornullmarked ❌. -
Legacy response:
7.2-preview.3is rejected, instead useapi-version=7.2-preview.1. The legacy response has no product breakdown; the fields areenableOnCreate、reposEnablementStatus[].advSecEnabled、advSecEnablementLastChangedDate, andadvSecEnablementFeatures(dependencyScanningInjectionEnabled、codeQLEnabled, etc.); useadvSecEnabledto determine items 1 and 3 at the same time, mark item 2 as ❓, and note in the result that the legacy API was used.
Examples: "How many repositories in the Contoso organization do not have Advanced Security enabled?", "Check whether secret scanning and push protection are fully enabled for the Contoso project", "Will newly created repositories automatically enable Code Security?"
Present the results
The date format is YYYY/MM/DD, convert times to the user's local time zone, and indicate UTC when it cannot be determined. Present in order:
-
Summary: audit scope, total number of repositories (excluding disabled and empty repositories), enabled counts and coverage rates for Secret Protection and Code Security, number with push protection enabled, and the automatic enablement status for new repositories.
-
Aggregate by project:
Project Repositories Secret Protection Push protection Code Security Dependency scanning CodeQL default setup Contoso 12 3(25%) 3 1(8%) 1 0 -
Repositories not enabled: grouped by project, list repository names (link
webUrl) and the missing products; when all are enabled, state this clearly. If there are many, list the first 50 and give the total count. -
Feature status of enabled repositories: one row for each repository with any product enabled, with columns for checks 1–6, plus the last change date.
-
Enablement steps(per Learn; before enabling, remind the user that billing will begin based on active committers,Begin billing to be confirmed by the user):
- Single repository:Project settings > Repos > Repositories > Repository, toggle Secret Protection or Code Security, then select Begin billing; for dependency scanning, under Options select dependency scanning default setup.
- Entire project:Project settings > Repos > Settings tab > Enable all, after selecting the product Begin billing; also toggle Automatically enable Advanced Security for new repositories。
- Entire organization:Organization settings > Repositories > Enable all, after selecting the product Begin billing; also toggle Automatically enable Advanced Security for new projects。
- Push protection: enable push protection on the repository settings page; Learn explains that it only checks pushes after it is enabled, and existing secrets are found by the repository's secret scanning.
- To include Advanced Security results in PR gating after enabling, see the status check items in
repos-branch-policy-audit; to view alerts, usesecurity-alert-review。
Finally, note that this report did not modify any settings.