Why We Built a Free Scanner
The Azure teams we speak to tell the same story: they know secrets are expiring somewhere, but they don’t have visibility across all their subscriptions and Key Vaults. They’ve cobbled together PowerShell scripts, Azure Policy assignments, and calendar reminders, but nothing gives them a single, clear picture.
So we built one. cc-scan is a free command-line tool that audits every Key Vault you have access to and tells you what’s expiring and what’s misconfigured. It runs on your own machine with your existing az login session, and it costs nothing.
What It Does
cc-scan performs a read-only audit of your Azure Key Vaults. It inventories secrets, certificates, and cryptographic keys across all accessible subscriptions, then evaluates them against 14 security checks covering expiry, network security, access control, and data protection.
This is real scanner output from a demo subscription, trimmed for length, with the names changed:
Scanning Azure subscriptions...
contoso-demo (00000000-0000-0000-0000-000000000000)
├── kv-contoso-prod (uksouth): 22 secrets, 9 certificates, 13 keys
├── kv-contoso-staging (uksouth): 9 secrets, 4 certificates, 8 keys
├── kv-contoso-dev (uksouth): 29 secrets, 18 certificates, 20 keys
└── kv-contoso-dr (uksouth): 40 secrets, 10 certificates, 11 keys
─────────────────────────────── SUMMARY ───────────────────────────────
Subscriptions: 1 Vaults: 7 Total assets: 206
Secrets: 107 Certificates: 43 Keys: 56
EXPIRY WARNINGS
EXPIRED 19 secrets, 3 certificates, 6 keys
< 30 days 4 certificates, 4 keys
< 90 days 4 secrets, 1 key
SECURITY FINDINGS
CRITICAL: 28 MEDIUM: 45 INFO: 8
Severity Finding Resource
CRITICAL Expired secret still enabled kv-contoso-prod/GitHub-PAT-CI
CRITICAL Expired secret still enabled kv-contoso-prod/Twilio-Auth-Token
CRITICAL Expired key still enabled kv-contoso-prod/PII-Encryption-Key
... and 66 more findings
That demo subscription is seeded with problems on purpose. Your numbers will be different, but the layout is the same.
No secret values are ever read. The scanner accesses metadata only: names, expiry dates, enabled status, vault configuration. Your credentials stay where they are.
The 14 Security Checks
Each finding has a severity so you know what to fix first:
| Severity | Rule | What It Catches |
|---|---|---|
| CRITICAL | SEC-001, SEC-002, SEC-012 | Expired secrets (SEC-001), certificates (SEC-002) and keys (SEC-012) that are still enabled. Anything still using them is about to fail, or already has |
| HIGH | SEC-003 | Key Vaults with public network access enabled |
| HIGH | SEC-004, SEC-005 | Missing soft-delete or purge protection, meaning an accidental or malicious delete is permanent |
| MEDIUM | SEC-006, SEC-007, SEC-013 | Secrets (SEC-006), certificates (SEC-007) and keys (SEC-013) with no expiry date set, invisible to any expiry-based alerting |
| MEDIUM | SEC-008 | RBAC not enforced, relying on legacy access policies instead of Azure’s recommended model |
| LOW | SEC-009 | Standard SKU vaults without HSM backing for key operations |
| INFO | SEC-010, SEC-011, SEC-014 | Secrets (SEC-010), certificates (SEC-011) and keys (SEC-014) expiring within 30 days |
The checks cover the same ground as the Key Vault section of the CIS Microsoft Azure Foundations Benchmark: expiry dates set, soft-delete and purge protection on, public access restricted, RBAC in use. If an auditor asks how you manage key material, a dated cc-scan report is a concrete answer.
Install cc-scan
pip (Python 3.11+):
pip install certifyclouds
Homebrew (macOS/Linux):
brew tap certifyclouds/certifyclouds
brew install certifyclouds
First run asks for your email once and gives you a free API key (no expiry), saved to ~/.certifyclouds/config.json. After that:
az login
cc-scan
That’s it. The scanner discovers all subscriptions your account can access and scans every Key Vault within them.
Output Formats
The default output is a rich terminal table, but cc-scan supports multiple formats for different workflows:
--format jsonfor piping into jq, scripts, or SIEM ingestion--format csvfor spreadsheet analysis and sharing with non-technical stakeholders--format htmlfor a standalone report with charts that you can open in any browser or attach to an email
# Generate an HTML report
cc-scan --format html -o audit-report.html
# JSON for automation
cc-scan --format json -o results.json
# Scan specific subscriptions only
cc-scan --subscription "sub-id-1" --subscription "sub-id-2"
CI/CD Integration
cc-scan is built for pipelines. When several exit codes apply, the first one listed wins:
- Exit 2: The scan could not run or read nothing, including a sign-in error or timeout
- Exit 3: No key and no terminal to register in, or registration failed
- Exit 1: A finding at or above
--fail-on(default:high) - Exit 4: The scan finished with coverage gaps, such as unreadable vaults or item types
- Exit 0: None of the above
A pipeline has no one to answer the email prompt, so set CC_SCAN_KEY as a secret. For GitHub Actions, sign in with OIDC through azure/login, then use the Azure CLI session with --auth cli. Give the pipeline identity Reader on each subscription and the vault permissions listed on the scanner page.
# GitHub Actions job: grant id-token: write in the workflow permissions
- name: Sign in to Azure
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Audit Key Vaults
env:
CC_SCAN_KEY: ${{ secrets.CC_SCAN_KEY }}
run: |
pip install certifyclouds
cc-scan --auth cli --format json -o scan-results.json
# Azure DevOps (variables come from a variable group)
- script: |
pip install certifyclouds
cc-scan --auth default --format json -o scan-results.json
displayName: 'Key Vault Security Audit'
env:
AZURE_CLIENT_ID: $(AZURE_CLIENT_ID)
AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET)
AZURE_TENANT_ID: $(AZURE_TENANT_ID)
CC_SCAN_KEY: $(CC_SCAN_KEY)
The CI/CD guide has the full workflows, the service principal setup and a GitLab example.
A failed gate means someone created a Key Vault without purge protection, or a secret expired and nobody rotated it. You want to hear about either before it reaches production.
Privacy and Offline Mode
We designed cc-scan with a minimal data footprint. After registration it sends counts only: how many subscriptions, vaults, secrets, certificates and keys were scanned, and how many were expired or expiring soon. It never sends names, values or subscription IDs.
If even that is too much for your environment, use --offline so nothing is sent to CertifyClouds after the initial registration:
cc-scan --offline
With --offline nothing is sent to CertifyClouds. The scan still talks to the Azure APIs, because that is where your vaults are.
From Scanner to Platform
cc-scan gives you a point-in-time snapshot, which is enough for an ad-hoc audit, a CI/CD gate or a first inventory. Credentials keep expiring after the scan finishes, though, and new ones appear every week.
When you’re ready to move from periodic scans to continuous lifecycle management, CertifyClouds picks up where cc-scan leaves off:
- Continuous discovery with scheduled scans and real-time alerting
- Certificates outside Key Vault, the ones your App Services, Application Gateways, API Management, Container Apps and Front Door serve on their custom domains, which a Key Vault scan never sees
- Automated rotation of App Registration secrets and certificates with zero-downtime overlap windows
- Dependency mapping showing which App Services, Functions, and Container Apps consume each secret
- Multi-cloud sync to keep credentials consistent across Azure, AWS, and GCP
- Compliance scoring against the CIS Microsoft Azure Foundations Benchmark, SOC 2, ISO 27001, NIST 800-53, the Microsoft cloud security benchmark, HIPAA and PCI DSS
Try CertifyClouds free with a 30-day trial. Starter or Pro depending on what you need. Starter includes discovery, compliance scoring, alerts, and 3 manual rotations per month.
Get Started
Install cc-scan, sign in to Azure and run your first scan:
pip install certifyclouds
az login
cc-scan
Full documentation: docs.certifyclouds.com/scanner
If the first scan turns up expired items you didn’t know about, start with the CRITICAL rows. Finding them now beats finding them at 3 AM, when a production integration fails because a certificate expired three weeks ago.
Further Reading
- How to Find All Expiring Secrets and Certificates Across Azure Subscriptions: the manual methods cc-scan replaces.
- Azure Key Vault Secret Rotation: Best Practices for 2026: what to do after you’ve found the problems.
- The True Cost of an Expired Azure Certificate in Production: why this matters in real money.