external/anthropic-cybersecurity-skills/skills/detecting-misconfigured-azure-storage/SKILL.md
Detecting misconfigured Azure Storage accounts including publicly accessible blob containers, missing encryption settings, overly permissive SAS tokens, disabled logging, and network access violations using Azure CLI, PowerShell, and Microsoft Defender for Storage.
npx skillsauth add seikaikyo/dash-skills detecting-misconfigured-azure-storageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Do not use for Azure SQL or Cosmos DB security auditing (use dedicated database security tools), for real-time threat detection on storage operations (use Defender for Storage), or for Azure Files or Data Lake Gen2 specific auditing without adapting the checks.
az login) with Reader and Storage Account Contributor rolesInstall-Module Az.Storage)List all storage accounts across subscriptions and assess their baseline security settings.
# List all storage accounts across all subscriptions
az storage account list \
--query "[].{Name:name, ResourceGroup:resourceGroup, Location:location, Kind:kind, Sku:sku.name, HttpsOnly:enableHttpsTrafficOnly, MinTLS:minimumTlsVersion, PublicAccess:allowBlobPublicAccess}" \
-o table
# Use Resource Graph for cross-subscription enumeration
az graph query -q "
Resources
| where type == 'microsoft.storage/storageaccounts'
| project name, resourceGroup, subscriptionId, location,
properties.allowBlobPublicAccess,
properties.enableHttpsTrafficOnly,
properties.minimumTlsVersion,
properties.networkAcls.defaultAction
" -o table
Identify storage accounts and containers allowing anonymous public access to blob data.
# Check each storage account for public blob access setting
for account in $(az storage account list --query "[].name" -o tsv); do
public=$(az storage account show --name "$account" --query "allowBlobPublicAccess" -o tsv)
echo "$account: allowBlobPublicAccess=$public"
done
# List containers with public access level set
for account in $(az storage account list --query "[?allowBlobPublicAccess==true].name" -o tsv); do
key=$(az storage account keys list --account-name "$account" --query "[0].value" -o tsv)
echo "=== $account ==="
az storage container list \
--account-name "$account" \
--account-key "$key" \
--query "[?properties.publicAccess!='off' && properties.publicAccess!=null].{Container:name, PublicAccess:properties.publicAccess}" \
-o table 2>/dev/null
done
# Test anonymous access to discovered public containers
curl -s "https://ACCOUNT.blob.core.windows.net/CONTAINER?restype=container&comp=list" | head -50
Check for storage accounts accessible from all networks versus those restricted to specific VNets or IP ranges.
# Find storage accounts with default network action set to Allow (open to all networks)
az storage account list \
--query "[?networkRuleSet.defaultAction=='Allow'].{Name:name, DefaultAction:networkRuleSet.defaultAction, VNetRules:networkRuleSet.virtualNetworkRules}" \
-o table
# Detailed network rule audit
for account in $(az storage account list --query "[].name" -o tsv); do
echo "=== $account ==="
az storage account show --name "$account" \
--query "{DefaultAction:networkRuleSet.defaultAction, IPRules:networkRuleSet.ipRules[*].ipAddressOrRange, VNetRules:networkRuleSet.virtualNetworkRules[*].virtualNetworkResourceId, Bypass:networkRuleSet.bypass}" \
-o json
done
# Find storage accounts with private endpoints
az network private-endpoint list \
--query "[?privateLinkServiceConnections[0].groupIds[0]=='blob'].{Name:name, Storage:privateLinkServiceConnections[0].privateLinkServiceId}" \
-o table
Ensure all storage accounts use encryption at rest with appropriate key management (Microsoft-managed or customer-managed keys).
# Check encryption configuration for all storage accounts
for account in $(az storage account list --query "[].name" -o tsv); do
echo "=== $account ==="
az storage account show --name "$account" \
--query "{Encryption:encryption.services, KeySource:encryption.keySource, KeyVaultUri:encryption.keyVaultProperties.keyVaultUri, InfraEncryption:encryption.requireInfrastructureEncryption}" \
-o json
done
# Find accounts without infrastructure encryption (double encryption)
az storage account list \
--query "[?encryption.requireInfrastructureEncryption!=true].{Name:name, KeySource:encryption.keySource}" \
-o table
# Check for accounts using TLS version below 1.2
az storage account list \
--query "[?minimumTlsVersion!='TLS1_2'].{Name:name, TLS:minimumTlsVersion}" \
-o table
Identify overly permissive SAS tokens and check for access key usage patterns.
# Check when storage account keys were last rotated
for account in $(az storage account list --query "[].name" -o tsv); do
echo "=== $account ==="
az storage account keys list \
--account-name "$account" \
--query "[].{KeyName:keyName, CreationTime:creationTime}" \
-o table
done
# Check if storage account allows shared key access (should be disabled for AAD-only)
az storage account list \
--query "[].{Name:name, AllowSharedKeyAccess:allowSharedKeyAccess}" \
-o table
# Review stored access policies on containers (SAS governance)
for account in $(az storage account list --query "[].name" -o tsv); do
key=$(az storage account keys list --account-name "$account" --query "[0].value" -o tsv 2>/dev/null)
for container in $(az storage container list --account-name "$account" --account-key "$key" --query "[].name" -o tsv 2>/dev/null); do
policies=$(az storage container policy list --container-name "$container" --account-name "$account" --account-key "$key" 2>/dev/null)
[ -n "$policies" ] && echo "$account/$container: $policies"
done
done
Verify that storage analytics logging and Azure Monitor diagnostic settings are enabled.
# Check diagnostic settings for storage accounts
for account in $(az storage account list --query "[].name" -o tsv); do
rg=$(az storage account show --name "$account" --query "resourceGroup" -o tsv)
echo "=== $account ==="
az monitor diagnostic-settings list \
--resource "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/$rg/providers/Microsoft.Storage/storageAccounts/$account" \
--query "[].{Name:name, Logs:logs[*].category, Metrics:metrics[*].category}" \
-o json 2>/dev/null || echo " No diagnostic settings configured"
done
# Check blob service logging properties
for account in $(az storage account list --query "[].name" -o tsv); do
key=$(az storage account keys list --account-name "$account" --query "[0].value" -o tsv 2>/dev/null)
az storage logging show \
--account-name "$account" \
--account-key "$key" \
--services b 2>/dev/null
done
| Term | Definition | |------|------------| | Blob Public Access | Storage account setting that allows anonymous read access to blob containers and their contents without authentication | | Shared Access Signature | Time-limited URI with embedded authentication tokens granting delegated access to Azure Storage resources with specific permissions | | Network ACL Default Action | Storage firewall setting that determines whether traffic is allowed or denied by default, with exceptions for specified IPs and VNets | | Customer-Managed Key | Encryption key stored in Azure Key Vault that the customer controls for storage encryption instead of Microsoft-managed keys | | Stored Access Policy | Named policy on a container that defines SAS permissions, start/expiry times, and can be revoked independently of individual SAS tokens | | Defender for Storage | Microsoft Defender plan providing threat detection for anomalous storage access patterns, malware uploads, and data exfiltration |
Context: A developer creates a storage account for a web application and enables blob public access to serve static files. They accidentally store API keys and database connection strings in a publicly accessible container.
Approach:
az storage account list filtering for allowBlobPublicAccess=trueblob or containerallowBlobPublicAccess to false on the storage accountPitfalls: Disabling blob public access immediately breaks applications serving content publicly. Coordinate with the development team and implement Azure CDN before disabling public access. SAS tokens generated before a key rotation remain valid until expiry unless the underlying storage key is regenerated.
Azure Storage Security Audit Report
======================================
Subscription: Production (SUB-ID)
Assessment Date: 2026-02-23
Storage Accounts Audited: 24
CRITICAL FINDINGS:
[STOR-001] Public Blob Access Enabled
Account: webapp-static-prod
Container: uploads (PublicAccess: blob)
Risk: Anonymous users can read all blobs in the container
Contents: 1,247 files including .env and config.json
Remediation: Disable allowBlobPublicAccess, use Azure CDN with SAS
[STOR-002] Storage Account Open to All Networks
Account: data-lake-analytics
Default Action: Allow (no network restrictions)
Risk: Accessible from any network including the internet
Remediation: Set default action to Deny, add VNet rules
SUMMARY:
Public blob access enabled: 3 / 24
Open to all networks: 8 / 24
Missing infrastructure encryption: 12 / 24
TLS version below 1.2: 2 / 24
No diagnostic logging: 10 / 24
Shared key access enabled: 18 / 24
Keys not rotated in 90+ days: 14 / 24
development
拋棄式 HTML mockup 比稿:產出 2 到 3 個設計立場不同的變體(密度 / 版式 / 強調軸,不是換色),各附取捨說明,最後給有立場的對比結論。適用:「畫個草圖」「比較 A 版 B 版」「先看方向再做」「給我看幾種做法」。要 production 元件或設計已定案時不適用。
tools
需求不明時的意圖萃取訪談:一次一題、每題附上自己的猜測、聽出「真正想要 vs 覺得應該要」,直到能預測使用者反應(約 95% 信心)才動工。適用:需求缺少對象 / 動機 / 成功標準 / 約束,或使用者點名「訪談我」「先確認一下」「我們確定嗎」。明確自足的指示、純資訊查詢、機械性操作不適用。
development
對非平凡決策啟動新鮮 context 對抗審查(找碴不背書),在修正還便宜的時候抓出錯誤方向。適用:高風險改動(production、資安敏感邏輯、不可逆操作)、不熟的程式碼、要宣稱「這樣是安全的 / 可行的」之前。機械性操作與一行修改不適用。
testing
Reference for writing and editing agent skills well — the vocabulary and principles that make a skill predictable. Consult when authoring, reviewing, or pruning a SKILL.md.