Executive Summary
CVE-2026-42826 is a perfect-score (CVSS 10.0) critical information disclosure vulnerability in Microsoft Azure DevOps, published May 7, 2026. An unauthenticated remote attacker can exploit a broken access-control path to expose sensitive project data, source code, secrets, and pipeline credentials with no user interaction required. Microsoft has already deployed a server-side fix for the cloud-hosted service, but organizations running Azure DevOps Server on-premises must act immediately to verify patch status and apply compensating controls.
1. What Is This Vulnerability?
CVE-2026-42826 is catalogued under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor. Despite the "information disclosure" label, the CVSS 3.1 impact vector scores High across all three pillars — Confidentiality (C:H), Integrity (I:H), and Availability (A:H) — which puts it in the rare category of disclosures where exposed data can be weaponized to compromise integrity and cause outages.
Technical Breakdown
The vulnerability exists in how Azure DevOps validates (or fails to validate) access tokens and authorization headers on certain API endpoints. The CVSS vector — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — tells the full story:
| CVSS Attribute | Value | Meaning |
|---|---|---|
| Attack Vector | N | Exploitable over the network from anywhere |
| Attack Complexity | L | No special conditions or race-timing required |
| Privileges Required | N | No account or authentication needed |
| User Interaction | N | Fully automated, no victim action needed |
| Scope | C | Impact extends beyond the vulnerable component |
| Confidentiality | H | Full exposure of sensitive data |
| Integrity | H | Attacker may be able to modify data |
| Availability | H | Service disruption possible via the same path |
The root cause is a failure in the authorization layer for one or more REST API endpoints within the Azure DevOps platform. An unauthenticated HTTP request, potentially using a crafted authorization header or a missing/malformed token, bypasses access controls and returns responses containing protected resources — including repository contents, pipeline variables, deployment secrets, and user metadata.
Because Azure DevOps pipelines routinely store service account tokens, PATs (Personal Access Tokens), cloud provider credentials, and signing keys as pipeline variables or secret stores, an information disclosure at this layer is effectively equivalent to a credential compromise event.
Attack Vector
A simplified attack flow looks like this:
- Attacker identifies a publicly reachable Azure DevOps endpoint (cloud:
dev.azure.com; on-prem: any internet- or intranet-exposed ADO server). - Attacker sends a crafted unauthenticated (or malformed-auth) request to a specific API endpoint — no brute-force, no phishing, no insider access needed.
- The API responds with a data payload that should have required at minimum
Project Readerpermissions. - Attacker extracts secrets, PATs, pipeline variables, or source code from the response.
- With extracted credentials, attacker pivots to CI/CD pipelines, cloud infrastructure, or downstream systems.
# Example malformed / null-auth request pattern (conceptual — no PoC published):
GET /[org]/[project]/_apis/build/definitions?api-version=7.1 HTTP/1.1
Host: dev.azure.com
Authorization: Bearer <empty or malformed>
Accept: application/json
In a correctly configured system this returns 401 Unauthorized. With CVE-2026-42826 present, the server returns pipeline definitions and potentially embedded variable values.
Real-World Impact
No public proof-of-concept had been released as of May 9, 2026, and Microsoft reports no evidence of in-the-wild exploitation at time of disclosure. However, the combination of zero prerequisites and high data sensitivity in Azure DevOps pipelines makes this a high-priority target. Supply chain attacks — where an adversary compromises a pipeline to inject malicious code into builds or deployments — are a well-documented threat model that this vulnerability directly enables.
2. Who Is Affected?
| Deployment Type | Status |
|---|---|
| Azure DevOps Services (cloud) | Patched automatically by Microsoft (May 7, 2026) |
| Azure DevOps Server 2022.x | Verify patch level; update if not on latest |
| Azure DevOps Server 2020.x | Verify patch level; update if not on latest |
| Azure DevOps Server 2019.x | End-of-support; assume unpatched — upgrade |
High-risk configurations:
- Organizations with publicly exposed Azure DevOps Server instances (internet-facing without VPN/firewall restriction)
- Pipelines storing secrets as plain-text pipeline variables instead of Azure Key Vault references
- Organizations using service principals with broad permissions (
Owner,Contributor) scoped to subscriptions - Multi-tenant development environments where external contributors have partial project access
- Any org that has not rotated credentials since May 7, 2026
3. How to Detect It (Testing)
Manual Testing Steps
Before running any tests, ensure you have written authorization to test the target system. Do not test systems you do not own.
Step 1 — Baseline authentication test
# Test an authenticated request first (use your own valid PAT)
curl -u "":<YOUR_PAT> \
"https://dev.azure.com/{org}/{project}/_apis/build/definitions?api-version=7.1" \
-o auth_response.json -w "%{http_code}"
# Expected: 200 with pipeline data
Step 2 — Unauthenticated probe
# Remove auth entirely
curl -s -o unauth_response.json -w "%{http_code}" \
"https://dev.azure.com/{org}/{project}/_apis/build/definitions?api-version=7.1"
# Patched expected: 401 or 403
# Vulnerable expected: 200 with data
Step 3 — Null token probe
# Send an empty Bearer token
curl -H "Authorization: Bearer " \
-s -o null_token_response.json -w "%{http_code}" \
"https://dev.azure.com/{org}/{project}/_apis/build/definitions?api-version=7.1"
# Patched expected: 401
# Vulnerable expected: 200
Step 4 — Evaluate the response
# Check if sensitive data was returned
cat unauth_response.json | python3 -m json.tool | grep -iE "secret|password|token|key|variable"
If Step 2 or Step 3 returns 200 with pipeline data, the system is vulnerable.
Automated Scanning
Nuclei (Project Discovery)
# nuclei-template: cve-2026-42826.yaml
id: CVE-2026-42826
info:
name: Azure DevOps Unauthenticated Information Disclosure
author: security-team
severity: critical
reference: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-42826
requests:
- method: GET
path:
- "{{BaseURL}}/_apis/build/definitions?api-version=7.1"
- "{{BaseURL}}/_apis/projects?api-version=7.1"
headers:
Authorization: "Bearer "
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
words:
- '"value"'
- '"id"'
condition: and
nuclei -t cve-2026-42826.yaml -u https://devops.yourorg.com -severity critical
Azure Security Center / Defender for DevOps
- Navigate to Microsoft Defender for Cloud → DevOps Security
- Review alerts tagged with
CVE-2026-42826orUnauthorized API Access - Check the Attack path analysis tab for exposure paths
Burp Suite
- Configure Burp as proxy for your ADO browser session
- Use Repeater to replay captured API requests with the
Authorizationheader removed or blanked - Observe HTTP response codes — any
200response without auth is a finding
Code Review Checklist
For teams maintaining custom ADO Server extensions or API integrations:
- Confirm all API calls include a valid, non-empty
Authorizationheader - Verify that PATs used in pipelines are scoped to minimum required permissions
- Check that secret pipeline variables use
isSecret: trueor Key Vault references — not plain text - Review service connections for over-permissioned credentials
- Audit any
AnonymousorAllowAnonymousaccess configurations in IIS (for on-prem servers) - Confirm network-level access controls prevent unauthenticated access from untrusted networks
4. How to Fix It (Mitigation)
Step-by-Step Remediation
For Azure DevOps Services (cloud-hosted):
- Verify Microsoft's patch is active — Log in to your Azure DevOps organization and confirm version in Organization Settings → Overview. The fix was deployed automatically on or after May 7, 2026.
- Audit and rotate exposed credentials — Assume any credentials stored in pipeline variables since before May 7, 2026 may be compromised. Rotate all PATs, service principal secrets, and API keys immediately.
- Review audit logs — In Organization Settings → Policies → Auditing, filter for unauthenticated or anomalous API calls from May 1–9, 2026.
For Azure DevOps Server (on-premises):
- Check your current version:
# On the ADO Server machine: Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Team Foundation Server" | Select-Object -ExpandProperty Version - Download and apply the latest update from the Azure DevOps Server Release Notes.
- Restrict network access immediately — Before patching, restrict inbound access to the ADO server via firewall or network security group:
# Windows Firewall — block all external inbound on port 8080/443 from untrusted IPs New-NetFirewallRule -DisplayName "Block-ADO-External" -Direction Inbound ` -LocalPort 443,8080 -Protocol TCP -Action Block -RemoteAddress Internet - Restart IIS after patching:
iisreset /restart - Re-enable access and validate that authentication is working correctly before returning to normal operations.
Code Fix Example
If you maintain a custom application or integration that calls Azure DevOps APIs, ensure tokens are always validated on the client side before sending:
Before (vulnerable pattern):
import requests
def get_pipelines(org, project, token=""):
url = f"https://dev.azure.com/{org}/{project}/_apis/build/definitions"
headers = {"Authorization": f"Bearer {token}"}
return requests.get(url, headers=headers, params={"api-version": "7.1"})
After (hardened pattern):
import requests
def get_pipelines(org: str, project: str, token: str) -> requests.Response:
if not token or not token.strip():
raise ValueError("A valid authentication token is required.")
url = f"https://dev.azure.com/{org}/{project}/_apis/build/definitions"
headers = {
"Authorization": f"Bearer {token.strip()}",
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers, params={"api-version": "7.1"}, timeout=30)
response.raise_for_status()
return response
Configuration Hardening
Azure DevOps Server — IIS Authentication:
<!-- web.config — ensure Anonymous Authentication is disabled -->
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
Azure Policy — Restrict public access to ADO:
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{ "field": "type", "equals": "Microsoft.DevOps/organizations" },
{ "field": "Microsoft.DevOps/organizations/publicAccessEnabled", "equals": true }
]
},
"then": { "effect": "Deny" }
}
}
Network Security Group (on-prem equivalent — restrict ADO Server access):
# Azure NSG rule — only allow access from known corporate IP ranges
az network nsg rule create \
--resource-group MyRG \
--nsg-name ADO-Server-NSG \
--name AllowCorporateOnly \
--priority 100 \
--direction Inbound \
--protocol Tcp \
--destination-port-ranges 443 8080 \
--source-address-prefixes "203.0.113.0/24" \ # Replace with your corporate IPs
--access Allow
5. How to Test the Fix (Validation)
Regression Test Scenarios
- Scenario A: Unauthenticated request to pipeline API returns
401 Unauthorized— not200 OK. - Scenario B: Empty
Authorization: Bearerheader request is rejected with401— not passed through. - Scenario C: Authenticated request with a valid PAT still returns
200with the correct data — no regression in normal functionality. - Scenario D: Audit log in ADO shows the test probe attempts as failed/unauthorized events (confirming logging is active).
Security Test Cases
Test Case 1: Verify unauthenticated access is blocked
# Precondition: Patch applied, server restarted
# Action: Send unauthenticated GET to pipeline endpoint
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
"https://dev.azure.com/{org}/{project}/_apis/build/definitions?api-version=7.1")
if [ "$RESPONSE" == "401" ] || [ "$RESPONSE" == "403" ]; then
echo "[PASS] Unauthenticated access correctly blocked."
else
echo "[FAIL] Unexpected response code: $RESPONSE — possible vulnerability!"
exit 1
fi
Test Case 2: Verify empty Bearer token is rejected
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer " \
"https://dev.azure.com/{org}/{project}/_apis/projects?api-version=7.1")
if [ "$RESPONSE" == "401" ] || [ "$RESPONSE" == "400" ]; then
echo "[PASS] Empty Bearer token correctly rejected."
else
echo "[FAIL] Empty Bearer token returned: $RESPONSE — investigate immediately!"
exit 1
fi
Test Case 3: Verify authenticated access still works
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
-u "":${ADO_PAT} \
"https://dev.azure.com/{org}/{project}/_apis/build/definitions?api-version=7.1")
if [ "$RESPONSE" == "200" ]; then
echo "[PASS] Authenticated access works correctly."
else
echo "[WARN] Authenticated request returned: $RESPONSE — check token validity."
fi
Automated Test Integration (CI/CD Gate)
Add the following to your security pipeline as a pre-deploy gate:
# azure-pipelines.yml — security gate step
- task: Bash@3
displayName: "Security Gate: Verify CVE-2026-42826 Remediation"
inputs:
targetType: inline
script: |
UNAUTH=$(curl -s -o /dev/null -w "%{http_code}" \
"$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/definitions?api-version=7.1")
if [ "$UNAUTH" == "200" ]; then
echo "##vso[task.logissue type=error]SECURITY GATE FAILED: CVE-2026-42826 — Unauthenticated access returned 200."
exit 1
fi
echo "Security gate passed. Unauthenticated access returned: $UNAUTH"
6. Prevention & Hardening
Best Practices
- Principle of least privilege for service connections: Scope all Azure DevOps service connections and service principals to the minimum required permissions. Use
Readerwhere possible; avoidOwner-scoped credentials in pipelines. - Never store secrets as plain pipeline variables: Migrate all pipeline secrets to Azure Key Vault and reference them using Key Vault task integration. Plain-text variables — even
isSecret: true— are still accessible via the API. - Network restriction by default: Azure DevOps Server instances should never be directly internet-accessible. Place them behind a VPN, WAF, or at minimum an IP allowlist. For cloud, configure IP allowlisting under Organization Settings → Security → Allowed IP addresses.
- Enable Conditional Access for Azure DevOps: Enforce MFA and device compliance for all users via Entra ID Conditional Access policies targeting
dev.azure.com. - Regular credential rotation: Rotate all PATs, service principal secrets, and pipeline credentials on a quarterly schedule minimum — or immediately following any security advisory.
- Monitor for ADO version drift: Establish automated alerting when Azure DevOps Server falls behind the latest patch level. Treat unpatched ADO servers the same as unpatched web servers.
Monitoring & Detection
Key log sources to monitor:
| Log Source | What to Watch For |
|---|---|
ADO Audit Log (Organization Settings → Auditing) |
Spikes in API calls from unknown IPs; calls returning 200 without valid auth context |
| Azure Monitor / Sentinel | Alerts for AzureDevOpsAuditEvent with AuthenticationMechanism = Anonymous |
| IIS Access Logs (on-prem) | 401/403 bursts from external IPs indicating scanning; 200 responses to requests with missing Authorization headers |
| Entra ID Sign-In Logs | Service principal sign-in anomalies — new locations, high frequency |
KQL query for Microsoft Sentinel:
AzureDevOpsAuditEvent
| where TimeGenerated > ago(7d)
| where AuthenticationMechanism == "Anonymous" or isempty(ActorUserId)
| where OperationName has_any ("Build.ReadDefinition", "Code.Read", "VariableGroups.Read")
| summarize Count=count(), IPs=make_set(IpAddress) by OperationName, ActorDisplayName
| where Count > 5
| order by Count desc
Set this as a Scheduled Analytics Rule with a 15-minute query frequency and alert when result count exceeds 0.
References
- CVE Record: NVD — CVE-2026-42826
- MSRC Advisory: Microsoft Security Response Center — CVE-2026-42826
- Patch & Release Notes: Azure DevOps Server Release Notes
- CWE Reference: CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
- TheHackerWire Analysis: Azure DevOps Critical Information Disclosure (CVE-2026-42826)
- Microsoft Defender for DevOps: Secure your DevOps environment
- Azure Key Vault Pipeline Integration: Use Azure Key Vault secrets in pipelines