Complete output examples for CleanCloud across AWS, Azure, and GCP — doctor validation, human-readable scan results, JSON output for CI/CD integration, and markdown for sharing in GitHub PRs or Slack.
- Doctor — AWS
- Doctor — Azure
- Doctor — GCP
- Doctor — Multi-Account
- Doctor — Azure Multi-Subscription
- Scan — AWS (Human-Readable)
- Scan — AWS Multi-Account
- Scan — Azure (Human-Readable)
- Scan — GCP (Human-Readable)
- Scan — AWS (JSON)
- Scan — Azure (JSON)
- Scan — GCP (JSON)
- Scan — AWS (Markdown)
- Scan — Azure (Markdown)
- Scan — GCP (Markdown)
- JSON Schema Reference
cleancloud doctor --provider aws
Validates IAM credentials, authentication method, security grade, and all read-only permissions required for scanning.
Running CleanCloud doctor
======================================================================
CLEANCLOUD ENVIRONMENT DIAGNOSTICS
======================================================================
Providers to check: AWS
======================================================================
AWS ENVIRONMENT VALIDATION
======================================================================
Step 1: AWS Credential Resolution
----------------------------------------------------------------------
[OK] AWS session created successfully
Step 2: Authentication Method Detection
----------------------------------------------------------------------
Authentication Method: AWS CLI Profile (default)
Boto3 Provider: shared-credentials-file
Credential Type: Long-lived
Lifetime: long-lived (access keys)
Rotation Required: Yes (every 90 days)
[!] Security Grade: ACCEPTABLE
[!] - Long-lived credentials
[!] - Manual rotation required
Recommendation for local development:
Current setup is acceptable
CI/CD Ready: NO (Local development only)
AWS CLI profiles are not available in CI/CD
Compliance: Acceptable for development environments
Step 3: Identity Verification
----------------------------------------------------------------------
[OK] Account ID: 123456789012
[OK] User ID: AIDAURVBTGFZCW6JGFCG2
[OK] ARN: arn:aws:iam::123456789012:user/cleanclouduser
IAM User: cleanclouduser
Region Scope
----------------------------------------------------------------------
Active Region: us-east-1
Doctor validates permissions for the active region only
Use 'cleancloud scan --provider aws --all-regions' to scan all active regions
Step 4: Read-Only Permission Validation
----------------------------------------------------------------------
[OK] ec2:DescribeVolumes
[OK] ec2:DescribeSnapshots
[OK] ec2:DescribeRegions
[OK] ec2:DescribeAddresses
[OK] ec2:DescribeNetworkInterfaces
[OK] ec2:DescribeImages
[OK] ec2:DescribeNatGateways
[OK] ec2:DescribeInstances
[OK] ec2:DescribeSecurityGroups
[OK] rds:DescribeDBInstances
[OK] rds:DescribeDBSnapshots
[OK] elasticloadbalancing:DescribeLoadBalancers
[OK] elasticloadbalancing:DescribeTargetGroups
[OK] logs:DescribeLogGroups
[OK] cloudwatch:GetMetricStatistics
[OK] s3:ListAllMyBuckets
[OK] s3:GetBucketTagging
======================================================================
VALIDATION SUMMARY
======================================================================
Authentication: AWS CLI Profile (default)
Security Grade: ACCEPTABLE
Permissions Tested: 19/19 passed
[OK] AWS ENVIRONMENT READY FOR CLEANCLOUD
======================================================================
When running with OIDC authentication (e.g., GitHub Actions), the security grade upgrades to EXCELLENT:
Step 2: Authentication Method Detection
----------------------------------------------------------------------
Authentication Method: OIDC (AssumeRoleWithWebIdentity)
Boto3 Provider: assume-role-with-web-identity
Credential Type: Temporary
Lifetime: 1 hour (temporary)
Rotation Required: No (auto-rotated)
[OK] Security Grade: EXCELLENT
[OK] - Temporary credentials
[OK] - Auto-rotated
[OK] - No secret storage required
[OK] CI/CD Ready: YES
cleancloud doctor --provider azure
Validates Azure credentials, subscription access, and Reader role permissions across all accessible subscriptions.
Running CleanCloud doctor
======================================================================
CLEANCLOUD ENVIRONMENT DIAGNOSTICS
======================================================================
Providers to check: AZURE
======================================================================
AZURE ENVIRONMENT VALIDATION
======================================================================
Step 1: Azure Credential Resolution
----------------------------------------------------------------------
Authentication Method: Service Principal (Client Secret)
Lifetime: long-lived (client secret)
Rotation Required: Yes (every 90 days or per policy)
[!] Uses Secret: Yes (stored credential)
[!] Security Grade: POOR
[!] - Long-lived client secret
[!] - Requires manual rotation
[!] - High blast radius if compromised
Recommendation for CI/CD:
Switch to OIDC (Workload Identity Federation)
See: https://docs.cleancloud.io/azure#oidc
[!] CI/CD Ready: NO
[!] Client secrets not recommended for automated pipelines
[!] Compliance: May not meet enterprise security requirements
Client ID: d7b1a453-4182-41f1-aa1f-2b9c99956981
Tenant ID: a8d6813d-de25-4473-bf18-94658b348c7d
Subscription Filter: 29d91ee0-922f-483a-a81f-1a5eff4ecfa2
Step 2: Credential Acquisition
----------------------------------------------------------------------
[OK] Azure credentials acquired successfully
Token expires in: ~59 minutes
Step 3: Subscription Access Validation
----------------------------------------------------------------------
[OK] Accessible subscriptions: 1
• Azure subscription 1 (29d91ee0-922f-483a-a81f-1a5eff4ecfa2)
[OK] Subscription filter matched: Azure subscription 1
Step 4: Permission Validation
----------------------------------------------------------------------
[OK] Subscription read access confirmed
Reader role provides all required permissions:
- Microsoft.Compute/disks/read
- Microsoft.Compute/snapshots/read
- Microsoft.Compute/virtualMachines/read
- Microsoft.Network/publicIPAddresses/read
- Microsoft.Network/loadBalancers/read
- Microsoft.Network/applicationGateways/read
- Microsoft.Network/virtualNetworkGateways/read
- Microsoft.Network/connections/read
- Microsoft.Web/serverfarms/read
- Microsoft.Web/serverfarms/sites/read
- Microsoft.Web/sites/read
- Microsoft.ContainerRegistry/registries/read
- Microsoft.Sql/servers/read
- Microsoft.Sql/servers/databases/read
- Microsoft.Insights/metrics/read
- Microsoft.Resources/subscriptions/read
- Microsoft.Resources/resources/read
======================================================================
VALIDATION SUMMARY
======================================================================
Authentication: Service Principal (Client Secret)
Security Grade: POOR
Subscriptions: 1 accessible
Filtered to: 29d91ee0-922f-483a-a81f-1a5eff4ecfa2
[OK] AZURE ENVIRONMENT READY FOR CLEANCLOUD
======================================================================
When running with Workload Identity Federation, the security grade upgrades to EXCELLENT:
Step 1: Azure Credential Resolution
----------------------------------------------------------------------
Authentication Method: OIDC (Workload Identity Federation)
Lifetime: 1 hour (temporary)
Rotation Required: No
[OK] Uses Secret: No (secretless)
[OK] Security Grade: EXCELLENT
[OK] - No client secrets stored
[OK] - Temporary credentials
[OK] - Auto-rotated
[OK] CI/CD Ready: YES
[OK] Suitable for production CI/CD pipelines
[OK] Compliance: SOC2/ISO27001 Compatible
cleancloud doctor --provider aws --multi-account accounts.yaml
Validates cross-account role access for every account in the config before committing to a full scan.
Running CleanCloud doctor
======================================================================
MULTI-ACCOUNT VALIDATION
======================================================================
Role name : CleanCloudReadOnlyRole
External ID : (none)
Accounts : 3
Step 1: Hub Account Credentials
----------------------------------------------------------------------
[OK] Hub account: 000000000000 (arn:aws:sts::000000000000:assumed-role/CleanCloudCIReadOnly/github-actions)
Step 2: Hub Role Permissions
----------------------------------------------------------------------
[OK] organizations:ListAccounts ✅ (--org flag will work)
Step 3: Cross-Account Role Validation
----------------------------------------------------------------------
[OK] production (111111111111) → arn:aws:sts::111111111111:assumed-role/CleanCloudReadOnlyRole/cleancloud-111111111111
[OK] staging (222222222222) → arn:aws:sts::222222222222:assumed-role/CleanCloudReadOnlyRole/cleancloud-222222222222
[!] dev (333333333333) → AccessDenied: role not found
======================================================================
MULTI-ACCOUNT SUMMARY
======================================================================
Accounts passed : 2/3
Accounts failed : 1
dev (333333333333): AccessDenied: role not found
Expected role ARN format: arn:aws:iam::<ACCOUNT_ID>:role/CleanCloudReadOnlyRole
See docs/aws.md for cross-account IAM setup instructions
======================================================================
cleancloud doctor --provider azure
When the service principal has Reader on multiple subscriptions, the doctor validates all of them automatically.
Running CleanCloud doctor
======================================================================
AZURE ENVIRONMENT VALIDATION
======================================================================
Step 1: Azure Credential Resolution
----------------------------------------------------------------------
Authentication Method: OIDC (Workload Identity Federation)
Lifetime: 1 hour (temporary)
Rotation Required: No
[OK] Uses Secret: No (secretless)
[OK] Security Grade: EXCELLENT
[OK] - No client secrets stored
[OK] - Temporary credentials
[OK] - Auto-rotated
[OK] CI/CD Ready: YES
[OK] Suitable for production CI/CD pipelines
[OK] Compliance: SOC2/ISO27001 Compatible
Client ID: d7b1a453-4182-41f1-aa1f-2b9c99956981
Tenant ID: a8d6813d-de25-4473-bf18-94658b348c7d
Step 2: Credential Acquisition
----------------------------------------------------------------------
[OK] Azure credentials acquired successfully
Token expires in: ~59 minutes
Step 3: Subscription Access Validation
----------------------------------------------------------------------
[OK] Accessible subscriptions: 3
• Production (a1b2c3d4-e5f6-7890-abcd-ef1234567890)
• Staging (f9e8d7c6-b5a4-3210-fedc-ba0987654321)
• Dev (c3d4e5f6-a7b8-9012-cdef-345678901234)
Step 4: Permission Validation
----------------------------------------------------------------------
[OK] Subscription read access confirmed
Reader role provides all required permissions:
- Microsoft.Compute/disks/read
- Microsoft.Compute/snapshots/read
- Microsoft.Compute/virtualMachines/read
- Microsoft.Network/publicIPAddresses/read
- Microsoft.Network/loadBalancers/read
- Microsoft.Network/applicationGateways/read
- Microsoft.Network/virtualNetworkGateways/read
- Microsoft.Network/connections/read
- Microsoft.Web/serverfarms/read
- Microsoft.Web/serverfarms/sites/read
- Microsoft.Web/sites/read
- Microsoft.ContainerRegistry/registries/read
- Microsoft.Sql/servers/read
- Microsoft.Sql/servers/databases/read
- Microsoft.Insights/metrics/read
- Microsoft.Resources/subscriptions/read
- Microsoft.Resources/resources/read
======================================================================
VALIDATION SUMMARY
======================================================================
Authentication: OIDC (Workload Identity Federation)
Security Grade: EXCELLENT
Subscriptions: 3 accessible
[OK] AZURE ENVIRONMENT READY FOR CLEANCLOUD
======================================================================
Assign Reader at the Management Group level to cover all subscriptions with a single role assignment — see docs/azure.md.
cleancloud doctor --provider gcp --project my-project-123
Validates Application Default Credentials, project access, and all required IAM roles for scanning.
Running CleanCloud doctor
======================================================================
CLEANCLOUD ENVIRONMENT DIAGNOSTICS
======================================================================
Providers to check: GCP
======================================================================
GCP ENVIRONMENT VALIDATION
======================================================================
Step 1: GCP Credential Resolution
----------------------------------------------------------------------
Authentication Method: Application Default Credentials (gcloud)
Credential Type: Temporary (OAuth2)
Source: ~/.config/gcloud/application_default_credentials.json
[OK] Security Grade: EXCELLENT
[OK] - Short-lived OAuth2 token
[OK] - Auto-refreshed by gcloud
CI/CD Ready: NO (Local development only)
Use Workload Identity Federation for CI/CD pipelines
Step 2: Project Access Validation
----------------------------------------------------------------------
[OK] Project accessible: my-project-123 (My Project)
Step 3: Read-Only Permission Validation
----------------------------------------------------------------------
[OK] compute.disks.list (roles/compute.viewer)
[OK] compute.instances.list (roles/compute.viewer)
[OK] compute.addresses.list (roles/compute.viewer)
[OK] compute.snapshots.list (roles/compute.viewer)
[OK] cloudsql.instances.list (roles/cloudsql.viewer)
[OK] monitoring.timeSeries.list (roles/monitoring.viewer)
[OK] resourcemanager.projects.get (roles/browser)
======================================================================
VALIDATION SUMMARY
======================================================================
Authentication: Application Default Credentials (gcloud)
Security Grade: EXCELLENT
Permissions Tested: 7/7 passed
[OK] GCP ENVIRONMENT READY FOR CLEANCLOUD
======================================================================
When running with Workload Identity Federation (e.g., GitHub Actions), there are no stored credentials:
Step 1: GCP Credential Resolution
----------------------------------------------------------------------
Authentication Method: Workload Identity Federation (OIDC)
Credential Type: Temporary (exchanged from GitHub OIDC token)
Lifetime: 1 hour (temporary)
Rotation Required: No (auto-rotated)
[OK] Security Grade: EXCELLENT
[OK] - No service account key stored
[OK] - Temporary credentials
[OK] - Auto-rotated
[OK] CI/CD Ready: YES
[OK] Suitable for production CI/CD pipelines
cleancloud scan --provider aws --multi-account accounts.yaml --all-regions
Scans 3 accounts in parallel, aggregates findings, and shows a per-account breakdown.
Starting CleanCloud scan...
Provider: aws
Scanning 3 accounts (role: CleanCloudReadOnlyRole)...
[INFO] Scanning production (111111111111)...
[INFO] Scanning staging (222222222222)...
[INFO] Scanning dev (333333333333)...
[INFO] Completed dev in 14.2s — 8 findings ~$420
[INFO] Completed staging in 18.7s — 31 findings ~$4,200
[INFO] Completed production in 22.1s — 45 findings ~$12,000
Found 84 hygiene issues:
1. [AWS] Unattached EBS Volume
Account : production (111111111111)
Risk : Low
Confidence : High
Resource : aws.ebs.volume → vol-0a1b2c3d4e5f67890
Region : us-east-1
Rule : aws.ebs.unattached
Reason : Volume has been unattached for 47 days
...
--- Scan Summary ---
Total findings: 84
By risk:
low: 61
medium: 23
By confidence:
high: 38
medium: 46
Minimum estimated waste: ~$18,200/month
(71 of 84 findings costed)
Regions scanned: eu-west-1, us-east-1, us-west-2 (explicit)
Scanned at: 2026-03-17T08:00:00+00:00
Accounts scanned: 3 ✅
Per-account breakdown:
dev (333333333333): 8 findings ~$420/month
production (111111111111): 45 findings ~$12,000/month
staging (222222222222): 31 findings ~$4,200/month
JSON output includes accounts_scanned, per_account breakdown, and account_id/account_name on every finding — ideal for downstream processing in CI/CD pipelines.
cleancloud scan --provider aws --all-regions
Found 9 hygiene issues:
1. [AWS] Stopped EC2 Instance (30+ Days)
Risk : Medium
Confidence : High
Resource : aws.ec2.instance → i-0abc1234567890def
Region : us-east-1
Rule : aws.ec2.instance.stopped
Reason : Instance has been stopped for 45 days (EBS charges continue)
Detected : 2026-02-08T14:32:01+00:00
Details:
- instance_type: t3.large
- stopped_days: 45
- ebs_volume_count: 2
- ebs_total_gb: 120
- estimated_monthly_cost_usd: 12.00
- tags: {"Environment": "staging", "Owner": "backend-team"}
2. [AWS] Unattached EBS Volume
Risk : Low
Confidence : High
Resource : aws.ebs.volume → vol-0a1b2c3d4e5f67890
Region : us-east-1
Rule : aws.ebs.unattached
Reason : Volume has been unattached for 47 days
Detected : 2026-02-08T14:32:02+00:00
Details:
- size_gb: 500
- availability_zone: us-east-1a
- state: available
- tags: {"Project": "legacy-api", "Owner": "platform"}
3. [AWS] Old RDS Snapshot
Risk : Low
Confidence : High
Resource : aws.rds.snapshot → rds:db-prod-2025-08-01-00-00
Region : us-east-1
Rule : aws.rds.snapshot.old
Reason : Manual RDS snapshot is 191 days old
Detected : 2026-02-08T14:32:03+00:00
Details:
- db_instance_identifier: db-prod
- age_days: 191
- allocated_storage_gb: 100
- engine: postgres
- estimated_monthly_cost_usd: 9.50
4. [AWS] Idle NAT Gateway
Risk : Medium
Confidence : Medium
Resource : aws.ec2.nat_gateway → nat-0abcdef1234567890
Region : us-west-2
Rule : aws.ec2.nat_gateway.idle
Reason : No traffic detected for 21 days
Detected : 2026-02-08T14:32:04+00:00
Details:
- name: staging-nat
- state: available
- vpc_id: vpc-0abc123
- total_bytes_out: 0
- total_bytes_in: 0
- estimated_monthly_cost_usd: 32.40
- idle_threshold_days: 14
5. [AWS] Old AMI
Risk : Low
Confidence : Medium
Resource : aws.ec2.ami → ami-0fedcba9876543210
Region : us-east-1
Rule : aws.ec2.ami.old
Reason : AMI is 243 days old with 3 associated snapshots (85.0 GB)
Detected : 2026-02-08T14:32:05+00:00
Details:
- ami_name: backend-v2.3.1-2025-06-10
- age_days: 243
- snapshot_count: 3
- total_size_gb: 85.0
- estimated_monthly_cost_usd: 4.25
6. [AWS] Unattached Elastic IP
Risk : Low
Confidence : High
Resource : aws.ec2.elastic_ip → eipalloc-0a1b2c3d4e5f6
Region : eu-west-1
Rule : aws.ec2.elastic_ip.unattached
Reason : Elastic IP not associated with any instance or ENI (age: 92 days)
Detected : 2026-02-08T14:32:06+00:00
Details:
- public_ip: 52.18.xxx.xxx
- domain: vpc
- age_days: 92
7. [AWS] Unused Security Group
Risk : Low
Confidence : High
Resource : aws.ec2.security_group → sg-0abc123def456789
Region : us-east-1
Rule : aws.ec2.security_group.unused
Reason : Security group has no ENI associations
Detected : 2026-02-08T14:32:07+00:00
Details:
- group_name: legacy-api-sg
- vpc_id: vpc-0abc123
- tags: {"Project": "legacy-api"}
8. [AWS] CloudWatch Log Group with Infinite Retention
Risk : Low
Confidence : Medium
Resource : aws.cloudwatch.log_group → /aws/lambda/legacy-processor
Region : us-east-1
Rule : aws.cloudwatch.logs.infinite_retention
Reason : Log group has no retention policy (never expires)
Detected : 2026-02-08T14:32:08+00:00
Details:
- stored_bytes: 8745213952
- retention_days: Never expires
9. [AWS] Untagged Resource
Risk : Low
Confidence : Medium
Resource : aws.s3.bucket → company-temp-uploads-2024
Region : global
Rule : aws.resource.untagged
Reason : S3 bucket has no tags
Detected : 2026-02-08T14:32:09+00:00
--- Scan Summary ---
Total findings: 9
By risk:
low: 7
medium: 2
By confidence:
high: 5
medium: 4
Minimum estimated waste: ~$206/month
(6 of 9 findings costed)
Regions scanned: us-east-1, us-west-2, eu-west-1 (auto-detected)
Scanned at: 2026-02-08T14:32:09+00:00
cleancloud scan --provider azure
Found 7 hygiene issues:
1. [AZURE] Unattached Managed Disk
Risk : Low
Confidence : Medium
Resource : azure.compute.disk → data-disk-legacy-api
Region : eastus
Rule : azure.unattached_disk
Reason : Managed disk not attached to any VM (age: 34 days)
Detected : 2026-02-08T14:45:12+00:00
Details:
- size_gb: 256
- disk_state: Unattached
- subscription: Production
2. [AZURE] Unused Public IP
Risk : Low
Confidence : High
Resource : azure.network.public_ip → pip-old-gateway
Region : westeurope
Rule : azure.network.public_ip.unused
Reason : Public IP not associated with any resource
Detected : 2026-02-08T14:45:13+00:00
Details:
- ip_address: 20.82.xxx.xxx
- allocation_method: Static
- subscription: Staging
3. [AZURE] Load Balancer with No Backends
Risk : Medium
Confidence : High
Resource : azure.network.load_balancer → lb-deprecated-service
Region : eastus
Rule : azure.lb_no_backends
Reason : Load balancer has no backend pools configured
Detected : 2026-02-08T14:45:14+00:00
Details:
- sku: Standard
- subscription: Production
4. [AZURE] Empty App Service Plan
Risk : Low
Confidence : High
Resource : azure.web.app_service_plan → plan-old-staging
Region : eastus2
Rule : azure.app_service_plan_empty
Reason : App Service Plan has no associated web apps
Detected : 2026-02-08T14:45:15+00:00
Details:
- sku: P1v3
- subscription: Staging
5. [AZURE] Idle App Service (No Requests for 14+ Days)
Risk : Medium
Confidence : High
Resource : azure.app_service → /subscriptions/.../sites/api-legacy-v1
Region : uksouth
Rule : azure.app_service.idle
Reason : App Service has zero HTTP requests for 14+ days
Detected : 2026-02-08T14:45:17+00:00
Details:
- app_name: api-legacy-v1
- kind: app
- sku_tier: Standard
- days_idle_threshold: 14
- subscription: Production
6. [AZURE] Unused Container Registry (90+ Days No Pulls)
Risk : Low
Confidence : High
Resource : azure.container_registry → /subscriptions/.../registries/acr-old-project
Region : eastus
Rule : azure.container_registry.unused
Reason : Container registry has zero pull activity for 90+ days
Detected : 2026-02-08T14:45:18+00:00
Details:
- registry_name: acr-old-project
- sku: Standard
- days_unused_threshold: 90
- subscription: Staging
7. [AZURE] Untagged Resource
Risk : Low
Confidence : Medium
Resource : azure.compute.disk → temp-migration-disk
Region : eastus
Rule : azure.resource.untagged
Reason : Resource has no tags
Detected : 2026-02-08T14:45:19+00:00
--- Scan Summary ---
Total findings: 7
By risk:
low: 5
medium: 2
By confidence:
high: 5
medium: 2
Minimum estimated waste: ~$165/month
(5 of 7 findings costed)
Subscriptions scanned: Production, Staging (all accessible)
Scanned at: 2026-02-08T14:45:19+00:00
cleancloud scan --provider aws --all-regions --output json --output-file results.json
{
"schema_version": "1.3.0",
"summary": {
"total_findings": 9,
"by_provider": { "aws": 9 },
"by_risk": { "low": 7, "medium": 2 },
"by_confidence": { "high": 5, "medium": 4 },
"minimum_estimated_monthly_waste_usd": 206.15,
"findings_with_cost_estimate": 6,
"highest_confidence": "high",
"high_conf_findings": 5,
"regions_scanned": ["us-east-1", "us-west-2", "eu-west-1"],
"region_selection_mode": "all-regions",
"provider": "aws",
"scanned_at": "2026-02-08T14:32:09+00:00"
},
"findings": [
{
"provider": "aws",
"rule_id": "aws.ec2.instance.stopped",
"resource_type": "aws.ec2.instance",
"resource_id": "i-0abc1234567890def",
"region": "us-east-1",
"title": "Stopped EC2 Instance (30+ Days)",
"summary": "EC2 instance has been stopped for 45 days — EBS charges continue accruing",
"reason": "Instance has been stopped for 45 days (EBS charges continue)",
"risk": "medium",
"confidence": "high",
"detected_at": "2026-02-08T14:32:01+00:00",
"details": {
"instance_type": "t3.large",
"stopped_days": 45,
"ebs_volume_count": 2,
"ebs_total_gb": 120,
"tags": { "Environment": "staging", "Owner": "backend-team" }
},
"estimated_monthly_cost_usd": 12.00,
"evidence": {
"signals_used": [
"Instance state is 'stopped' for 45 days",
"EBS volumes attached — storage charges continue",
"2 attached EBS volumes totalling 120 GB"
],
"signals_not_checked": [
"Intentional pause for cost-saving during off-hours",
"IaC-managed lifecycle",
"Pending reactivation"
],
"time_window": "30 days"
}
},
{
"provider": "aws",
"rule_id": "aws.ebs.unattached",
"resource_type": "aws.ebs.volume",
"resource_id": "vol-0a1b2c3d4e5f67890",
"region": "us-east-1",
"title": "Unattached EBS Volume",
"summary": "EBS volume has been unattached for 47 days",
"reason": "Volume has been unattached for 47 days",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:32:01+00:00",
"details": {
"size_gb": 500,
"availability_zone": "us-east-1a",
"state": "available",
"tags": { "Project": "legacy-api", "Owner": "platform" }
},
"evidence": {
"signals_used": [
"Volume state is 'available' (not attached to any instance)",
"Volume has been unattached for 47 days"
],
"signals_not_checked": [
"Application-level usage intent",
"IaC-managed lifecycle",
"Disaster recovery purpose"
],
"time_window": "30 days"
}
},
{
"provider": "aws",
"rule_id": "aws.ec2.nat_gateway.idle",
"resource_type": "aws.ec2.nat_gateway",
"resource_id": "nat-0abcdef1234567890",
"region": "us-west-2",
"title": "Idle NAT Gateway",
"summary": "NAT Gateway with zero traffic for 21 days",
"reason": "No traffic detected for 21 days",
"risk": "medium",
"confidence": "medium",
"detected_at": "2026-02-08T14:32:04+00:00",
"details": {
"name": "staging-nat",
"state": "available",
"vpc_id": "vpc-0abc123",
"total_bytes_out": 0,
"total_bytes_in": 0,
"estimated_monthly_cost_usd": 32.40,
"idle_threshold_days": 14
},
"evidence": {
"signals_used": [
"Zero bytes transferred (in and out) over 14-day CloudWatch window",
"NAT Gateway has been idle for 21 days"
],
"signals_not_checked": [
"Future provisioning intent",
"IaC-managed lifecycle"
],
"time_window": "14 days"
}
},
{
"provider": "aws",
"rule_id": "aws.ec2.ami.old",
"resource_type": "aws.ec2.ami",
"resource_id": "ami-0fedcba9876543210",
"region": "us-east-1",
"title": "Old AMI",
"summary": "AMI is 243 days old with 3 associated snapshots (85.0 GB)",
"reason": "AMI is 243 days old with 3 associated snapshots (85.0 GB)",
"risk": "low",
"confidence": "medium",
"detected_at": "2026-02-08T14:32:05+00:00",
"details": {
"ami_name": "backend-v2.3.1-2025-06-10",
"age_days": 243,
"snapshot_count": 3,
"total_size_gb": 85.0,
"estimated_monthly_cost_usd": 4.25
},
"evidence": {
"signals_used": [
"AMI age exceeds 180-day threshold",
"AMI has associated snapshots incurring storage costs"
],
"signals_not_checked": [
"Whether AMI is referenced in launch templates",
"IaC-managed lifecycle",
"Disaster recovery or compliance retention"
],
"time_window": "180 days"
}
},
{
"provider": "aws",
"rule_id": "aws.ec2.elastic_ip.unattached",
"resource_type": "aws.ec2.elastic_ip",
"resource_id": "eipalloc-0a1b2c3d4e5f6",
"region": "eu-west-1",
"title": "Unattached Elastic IP",
"summary": "Elastic IP not associated with any instance or ENI",
"reason": "Elastic IP not associated with any instance or ENI (age: 92 days)",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:32:06+00:00",
"details": {
"public_ip": "52.18.xxx.xxx",
"domain": "vpc",
"age_days": 92
},
"evidence": {
"signals_used": [
"Elastic IP has no association (no instance or ENI)",
"EIP has been unattached for 92 days"
],
"signals_not_checked": [
"DNS records pointing to this IP",
"IaC-managed lifecycle"
],
"time_window": "30 days"
}
},
{
"provider": "aws",
"rule_id": "aws.rds.snapshot.old",
"resource_type": "aws.rds.snapshot",
"resource_id": "rds:db-prod-2025-08-01-00-00",
"region": "us-east-1",
"title": "Old RDS Snapshot",
"summary": "Manual RDS snapshot is 191 days old — no longer needed for point-in-time recovery",
"reason": "Manual RDS snapshot is 191 days old",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:32:07+00:00",
"details": {
"db_instance_identifier": "db-prod",
"age_days": 191,
"allocated_storage_gb": 100,
"engine": "postgres"
},
"estimated_monthly_cost_usd": 9.50,
"evidence": {
"signals_used": [
"Snapshot age (191 days) exceeds 90-day threshold",
"Manual snapshot — not managed by automated backup retention",
"Allocated storage: 100 GB (ceiling estimate; incremental snapshots may be smaller)"
],
"signals_not_checked": [
"Compliance or audit retention requirements",
"Whether snapshot is referenced by a restore procedure"
],
"time_window": "90 days"
}
},
{
"provider": "aws",
"rule_id": "aws.ec2.security_group.unused",
"resource_type": "aws.ec2.security_group",
"resource_id": "sg-0abc123def456789",
"region": "us-east-1",
"title": "Unused Security Group",
"summary": "Security group has no ENI associations",
"reason": "Security group has no ENI associations",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:32:08+00:00",
"details": {
"group_name": "legacy-api-sg",
"vpc_id": "vpc-0abc123",
"tags": { "Project": "legacy-api" }
},
"evidence": {
"signals_used": [
"Security group has zero network interface associations"
],
"signals_not_checked": [
"Referenced in launch templates or IaC",
"Intentional placeholder for future use"
],
"time_window": null
}
},
{
"provider": "aws",
"rule_id": "aws.cloudwatch.logs.infinite_retention",
"resource_type": "aws.cloudwatch.log_group",
"resource_id": "/aws/lambda/legacy-processor",
"region": "us-east-1",
"title": "CloudWatch Log Group with Infinite Retention",
"summary": "Log group has no retention policy (never expires)",
"reason": "Log group has no retention policy (never expires)",
"risk": "low",
"confidence": "medium",
"detected_at": "2026-02-08T14:32:07+00:00",
"details": {
"stored_bytes": 8745213952,
"retention_days": null
},
"evidence": {
"signals_used": [
"Log group retention is set to 'Never expire'",
"Log group has significant stored data (8.1 GB)"
],
"signals_not_checked": [
"Compliance or audit retention requirements",
"Active log ingestion rate"
],
"time_window": null
}
},
{
"provider": "aws",
"rule_id": "aws.resource.untagged",
"resource_type": "aws.s3.bucket",
"resource_id": "company-temp-uploads-2024",
"region": null,
"title": "Untagged Resource",
"summary": "S3 bucket has no tags",
"reason": "S3 bucket has no tags",
"risk": "low",
"confidence": "medium",
"detected_at": "2026-02-08T14:32:08+00:00",
"details": {},
"evidence": {
"signals_used": [
"Resource has zero tags attached"
],
"signals_not_checked": [
"Whether resource is managed by IaC with tags defined elsewhere",
"Organizational tagging policy exceptions"
],
"time_window": null
}
}
]
}cleancloud scan --provider azure --output json --output-file results.json
{
"schema_version": "1.3.0",
"summary": {
"total_findings": 7,
"by_provider": { "azure": 7 },
"by_risk": { "low": 5, "medium": 2 },
"by_confidence": { "high": 5, "medium": 2 },
"minimum_estimated_monthly_waste_usd": 165.00,
"findings_with_cost_estimate": 5,
"highest_confidence": "high",
"high_conf_findings": 5,
"regions_scanned": ["eastus", "eastus2", "uksouth", "westeurope"],
"subscriptions_scanned": [
"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"f9e8d7c6-b5a4-3210-fedc-ba0987654321"
],
"subscription_selection_mode": "all",
"provider": "azure",
"scanned_at": "2026-02-08T14:45:19+00:00"
},
"findings": [
{
"provider": "azure",
"rule_id": "azure.unattached_disk",
"resource_type": "azure.compute.disk",
"resource_id": "/subscriptions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resourceGroups/rg-legacy/providers/Microsoft.Compute/disks/data-disk-legacy-api",
"region": "eastus",
"title": "Unattached Managed Disk",
"summary": "Managed disk not attached to any VM",
"reason": "Managed disk not attached to any VM (age: 34 days)",
"risk": "low",
"confidence": "medium",
"detected_at": "2026-02-08T14:45:12+00:00",
"details": {
"size_gb": 256,
"disk_state": "Unattached",
"subscription": "Production"
},
"evidence": {
"signals_used": [
"Disk state is 'Unattached'",
"Disk has been unattached for 34 days"
],
"signals_not_checked": [
"Application-level usage intent",
"IaC-managed lifecycle",
"Disaster recovery purpose"
],
"time_window": "30 days"
}
},
{
"provider": "azure",
"rule_id": "azure.network.public_ip.unused",
"resource_type": "azure.network.public_ip",
"resource_id": "/subscriptions/f9e8d7c6-b5a4-3210-fedc-ba0987654321/resourceGroups/rg-staging/providers/Microsoft.Network/publicIPAddresses/pip-old-gateway",
"region": "westeurope",
"title": "Unused Public IP",
"summary": "Public IP not associated with any resource",
"reason": "Public IP not associated with any resource",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:45:13+00:00",
"details": {
"ip_address": "20.82.xxx.xxx",
"allocation_method": "Static",
"subscription": "Staging"
},
"evidence": {
"signals_used": [
"Public IP has no ip_configuration (not attached to any resource)"
],
"signals_not_checked": [
"DNS records pointing to this IP",
"IaC-managed lifecycle"
],
"time_window": null
}
},
{
"provider": "azure",
"rule_id": "azure.lb_no_backends",
"resource_type": "azure.network.load_balancer",
"resource_id": "/subscriptions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resourceGroups/rg-prod/providers/Microsoft.Network/loadBalancers/lb-deprecated-service",
"region": "eastus",
"title": "Load Balancer with No Backends",
"summary": "Load balancer has no backend pools configured",
"reason": "Load balancer has no backend pools configured",
"risk": "medium",
"confidence": "high",
"detected_at": "2026-02-08T14:45:14+00:00",
"details": {
"sku": "Standard",
"subscription": "Production"
},
"evidence": {
"signals_used": [
"Load balancer has zero backend pools configured"
],
"signals_not_checked": [
"Whether backend pools are being provisioned",
"IaC-managed lifecycle"
],
"time_window": null
}
},
{
"provider": "azure",
"rule_id": "azure.app_service_plan_empty",
"resource_type": "azure.web.app_service_plan",
"resource_id": "/subscriptions/f9e8d7c6-b5a4-3210-fedc-ba0987654321/resourceGroups/rg-staging/providers/Microsoft.Web/serverfarms/plan-old-staging",
"region": "eastus2",
"title": "Empty App Service Plan",
"summary": "App Service Plan has no associated web apps",
"reason": "App Service Plan has no associated web apps",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:45:15+00:00",
"details": {
"sku": "P1v3",
"subscription": "Staging"
},
"evidence": {
"signals_used": [
"App Service Plan has zero web apps associated"
],
"signals_not_checked": [
"Whether apps are being deployed to this plan",
"IaC-managed lifecycle"
],
"time_window": null
}
},
{
"provider": "azure",
"rule_id": "azure.app_service.idle",
"resource_type": "azure.app_service",
"resource_id": "/subscriptions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resourceGroups/rg-prod/providers/Microsoft.Web/sites/api-legacy-v1",
"region": "uksouth",
"title": "Idle App Service (No Requests for 14+ Days)",
"summary": "App Service 'api-legacy-v1' (Standard) has received zero HTTP requests for 14+ days but continues to accrue compute charges.",
"reason": "App Service has zero HTTP requests for 14+ days",
"risk": "medium",
"confidence": "high",
"detected_at": "2026-02-08T14:45:17+00:00",
"details": {
"app_name": "api-legacy-v1",
"kind": "app",
"sku_tier": "Standard",
"location": "uksouth",
"days_idle_threshold": 14
},
"estimated_monthly_cost_usd": 73.0,
"evidence": {
"signals_used": [
"Zero HTTP requests for 14 days (Azure Monitor: Requests metric)",
"App state: Running",
"App Service Plan tier: Standard",
"App Service Plan tier 'Standard' costs ~$73/month per instance"
],
"signals_not_checked": [
"Non-HTTP workloads (WebJobs, background services)",
"Planned reactivation or seasonal use",
"IaC-managed placeholder deployment",
"Blue/green deployment staging slot"
],
"time_window": "14 days"
}
},
{
"provider": "azure",
"rule_id": "azure.container_registry.unused",
"resource_type": "azure.container_registry",
"resource_id": "/subscriptions/f9e8d7c6-b5a4-3210-fedc-ba0987654321/resourceGroups/rg-staging/providers/Microsoft.ContainerRegistry/registries/acr-old-project",
"region": "eastus",
"title": "Unused Container Registry (90+ Days No Pulls)",
"summary": "Container Registry 'acr-old-project' (Standard) has had no image pulls for 90+ days.",
"reason": "Container registry has zero pull activity for 90+ days",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T14:45:18+00:00",
"details": {
"registry_name": "acr-old-project",
"sku": "Standard",
"location": "eastus",
"days_unused_threshold": 90
},
"estimated_monthly_cost_usd": 20.0,
"evidence": {
"signals_used": [
"Zero successful image pulls for 90 days (Azure Monitor: SuccessfulPullCount)",
"Zero successful image pushes for 90 days (Azure Monitor: SuccessfulPushCount)",
"No push or pull activity detected across the entire 90-day window",
"Registry SKU: Standard",
"ACR Standard tier costs ~$20/month plus storage"
],
"signals_not_checked": [
"Geo-replication pull activity in other regions",
"Planned reactivation or migration",
"Images referenced by stopped but not deleted workloads"
],
"time_window": "90 days"
}
},
{
"provider": "azure",
"rule_id": "azure.resource.untagged",
"resource_type": "azure.compute.disk",
"resource_id": "/subscriptions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resourceGroups/rg-legacy/providers/Microsoft.Compute/disks/temp-migration-disk",
"region": "eastus",
"title": "Untagged Resource",
"summary": "Resource has no tags",
"reason": "Resource has no tags",
"risk": "low",
"confidence": "medium",
"detected_at": "2026-02-08T14:45:19+00:00",
"details": {},
"evidence": {
"signals_used": [
"Resource has zero tags attached"
],
"signals_not_checked": [
"Whether resource is managed by IaC with tags defined elsewhere",
"Organizational tagging policy exceptions"
],
"time_window": null
}
}
]
}cleancloud scan --provider aws --all-regions --output markdown
Produces a grouped, cost-sorted summary you can paste directly into a GitHub PR comment, Slack message, or issue. Use --output-file results.md to save to a file instead.
## CleanCloud Scan Results
**Provider:** AWS
**Regions:** us-east-1, us-west-2, eu-west-1
**Scanned:** 2026-02-08
**Estimated monthly waste:** ~$206
**Total findings:** 9
| Finding | Count | Est. Monthly Cost |
|---------|------:|------------------:|
| Idle NAT Gateway | 1 | ~$32 |
| Unattached EBS Volume | 2 | ~$115 |
| Old RDS Snapshot | 1 | ~$10 |
| Stopped EC2 Instance | 1 | ~$12 |
| Old AMI | 1 | ~$4 |
| Unattached Elastic IP | 1 | ~$0 |
| Unused Security Group | 1 | — |
| CloudWatch Log Group: Infinite Retention | 1 | — |
| Untagged Resource | 1 | — |
**Confidence:** high: 5 · medium: 4
> Generated by [CleanCloud](https://github.com/cleancloud-io/cleancloud) — read-only cloud hygiene scanner for AWS, Azure, and GCP.Findings are grouped by title (multiple instances of the same finding type are collapsed into one row with a count) and sorted by estimated cost descending.
cleancloud scan --provider azure --output markdown
## CleanCloud Scan Results
**Provider:** AZURE
**Subscriptions:** Production, Staging
**Scanned:** 2026-02-08
**Estimated monthly waste:** ~$165
**Total findings:** 7
| Finding | Count | Est. Monthly Cost |
|---------|------:|------------------:|
| Empty App Service Plan | 1 | ~$146 |
| Idle App Service | 1 | ~$73 |
| Load Balancer with No Backends | 1 | ~$18 |
| Unused Container Registry | 1 | ~$20 |
| Unused Public IP | 1 | ~$4 |
| Unattached Managed Disk | 1 | — |
| Untagged Resource | 1 | — |
**Confidence:** high: 5 · medium: 2
> Generated by [CleanCloud](https://github.com/cleancloud-io/cleancloud) — read-only cloud hygiene scanner for AWS, Azure, and GCP.For Azure, the Subscriptions field is shown instead of Regions, reflecting how Azure scans are scoped.
cleancloud scan --provider gcp --all-projects
Found 5 hygiene issues:
1. [GCP] Stopped VM Instance (30+ Days)
Risk : Medium
Confidence : High
Resource : gcp.compute.instance → projects/my-project/zones/us-central1-a/instances/old-worker-1
Region : us-central1-a
Rule : gcp.compute.vm.stopped
Reason : VM instance has been stopped for 52 days (disk charges continue)
Detected : 2026-02-08T15:00:01+00:00
Details:
- machine_type: n1-standard-4
- stopped_days: 52
- disk_count: 2
- total_disk_gb: 200
- estimated_monthly_cost_usd: 16.00
- labels: {"env": "staging", "team": "data"}
2. [GCP] Unattached Persistent Disk
Risk : Low
Confidence : High
Resource : gcp.compute.disk → projects/my-project/zones/us-central1-b/disks/data-disk-old
Region : us-central1-b
Rule : gcp.compute.disk.unattached
Reason : Persistent disk has been unattached for 38 days
Detected : 2026-02-08T15:00:02+00:00
Details:
- size_gb: 500
- type: pd-ssd
- status: READY
- estimated_monthly_cost_usd: 85.00
- labels: {"project": "legacy-pipeline"}
3. [GCP] Unused Reserved Static IP
Risk : Low
Confidence : High
Resource : gcp.compute.address → projects/my-project/regions/us-central1/addresses/old-loadbalancer-ip
Region : us-central1
Rule : gcp.compute.ip.unused
Reason : Static IP is reserved but not attached to any resource
Detected : 2026-02-08T15:00:03+00:00
Details:
- address: 34.123.xxx.xxx
- address_type: EXTERNAL
- status: RESERVED
- labels: {}
4. [GCP] Old Disk Snapshot
Risk : Low
Confidence : High
Resource : gcp.compute.snapshot → projects/my-project/global/snapshots/disk-backup-2025-08-01
Region : global
Rule : gcp.compute.snapshot.old
Reason : Disk snapshot is 191 days old
Detected : 2026-02-08T15:00:04+00:00
Details:
- source_disk: projects/my-project/zones/us-central1-a/disks/app-disk
- age_days: 191
- storage_bytes: 53687091200
- estimated_monthly_cost_usd: 2.15
- labels: {}
5. [GCP] Idle Cloud SQL Instance
Risk : Medium
Confidence : High
Resource : gcp.sql.instance → projects/my-project/instances/db-staging
Region : us-central1
Rule : gcp.sql.instance.idle
Reason : Cloud SQL instance has zero connections for 14+ days
Detected : 2026-02-08T15:00:05+00:00
Details:
- database_version: POSTGRES_14
- tier: db-n1-standard-2
- estimated_monthly_cost_usd: 100.00
- labels: {"env": "staging"}
--- Scan Summary ---
Rules executed: 5/5
Total findings: 5
By risk:
low: 3
medium: 2
By confidence:
high: 5
Minimum estimated waste: ~$203/month
(4 of 5 findings costed)
Projects scanned: my-project (all accessible)
Scanned at: 2026-02-08T15:00:05+00:00
For GCP, the Projects scanned field is shown instead of Regions, and findings use labels instead of tags in details.
cleancloud scan --provider gcp --all-projects --output json --output-file results.json
{
"schema_version": "1.3.0",
"summary": {
"total_findings": 5,
"by_provider": { "gcp": 5 },
"by_risk": { "low": 3, "medium": 2 },
"by_confidence": { "high": 5 },
"minimum_estimated_monthly_waste_usd": 203.15,
"findings_with_cost_estimate": 4,
"highest_confidence": "high",
"high_conf_findings": 5,
"projects_scanned": ["my-project"],
"project_selection_mode": "all",
"total_rules": 5,
"provider": "gcp",
"scanned_at": "2026-02-08T15:00:05+00:00"
},
"findings": [
{
"provider": "gcp",
"rule_id": "gcp.compute.disk.unattached",
"resource_type": "gcp.compute.disk",
"resource_id": "projects/my-project/zones/us-central1-b/disks/data-disk-old",
"region": "us-central1-b",
"title": "Unattached Persistent Disk",
"summary": "Persistent disk has been unattached for 38 days",
"reason": "Persistent disk has been unattached for 38 days",
"risk": "low",
"confidence": "high",
"detected_at": "2026-02-08T15:00:02+00:00",
"details": {
"size_gb": 500,
"type": "pd-ssd",
"status": "READY",
"labels": { "project": "legacy-pipeline" }
},
"estimated_monthly_cost_usd": 85.00,
"evidence": {
"signals_used": [
"Disk status is READY with no users (not attached to any instance)",
"Disk has been unattached for 38 days"
],
"signals_not_checked": [
"Application-level usage intent",
"IaC-managed lifecycle",
"Disaster recovery purpose"
],
"time_window": "30 days"
}
},
{
"provider": "gcp",
"rule_id": "gcp.sql.instance.idle",
"resource_type": "gcp.sql.instance",
"resource_id": "projects/my-project/instances/db-staging",
"region": "us-central1",
"title": "Idle Cloud SQL Instance",
"summary": "Cloud SQL instance has zero connections for 14+ days",
"reason": "Cloud SQL instance has zero connections for 14+ days",
"risk": "medium",
"confidence": "high",
"detected_at": "2026-02-08T15:00:05+00:00",
"details": {
"database_version": "POSTGRES_14",
"tier": "db-n1-standard-2",
"labels": { "env": "staging" }
},
"estimated_monthly_cost_usd": 100.00,
"evidence": {
"signals_used": [
"Zero database connections over 14-day Cloud Monitoring window",
"Instance state: RUNNABLE"
],
"signals_not_checked": [
"Application-level connection poolers that may suppress direct connections",
"Planned reactivation or seasonal workload"
],
"time_window": "14 days"
}
}
]
}cleancloud scan --provider gcp --all-projects --output markdown
## CleanCloud Scan Results
**Provider:** GCP
**Projects:** my-project
**Scanned:** 2026-02-08
**Estimated monthly waste:** ~$203
**Total findings:** 5
| Finding | Count | Est. Monthly Cost |
|---------|------:|------------------:|
| Unattached Persistent Disk | 1 | ~$85 |
| Idle Cloud SQL Instance | 1 | ~$100 |
| Old Disk Snapshot | 1 | ~$2 |
| Stopped VM Instance | 1 | ~$16 |
| Unused Reserved Static IP | 1 | ~$0 |
**Confidence:** high: 5
> Generated by [CleanCloud](https://github.com/cleancloud-io/cleancloud) — read-only cloud hygiene scanner for AWS, Azure, and GCP.For GCP, the Projects field is shown instead of Regions or Subscriptions.
CleanCloud uses a versioned JSON schema (current: 1.3.0). All JSON output includes a schema_version field for backward compatibility.
- Schema definition:
schemas/output-v1.3.0.json - CI/CD integration guide:
docs/ci.md
Key differences between AWS, Azure, and GCP JSON output:
| Field | AWS | Azure | GCP |
|---|---|---|---|
region_selection_mode |
"explicit" or "all-regions" |
Not present | Not present |
regions_scanned |
Array of region strings | Array of region strings | Not present |
subscription_selection_mode |
Not present | "explicit", "all", or "management-group" |
Not present |
subscriptions_scanned |
Not present | Array of subscription IDs | Not present |
project_selection_mode |
Not present | Not present | "explicit" or "all" |
projects_scanned |
Not present | Not present | Array of project IDs |
resource_id |
Short ID (e.g., vol-0abc123) |
Full ARM resource ID | Full resource path (e.g., projects/p/zones/z/disks/d) |
details.tags |
Present | Present | Not present |
details.labels |
Not present | Not present | Present |