Findings
After every sync, 141 audit rules check your assets for what's exposed, unencrypted, unused or misconfigured.
Once a sync has collected an asset source, AssetHermit runs its cloud's audit rules over every asset it found. A finding is one rule matching one asset. It opens on the sync that first matches it and stays open, keeping the time it opened, until a sync no longer matches it, when it resolves. A finding whose asset was deleted resolves the same way.
Each rule is a query in the query language, such as $type:storage.disk -encrypted:true, with a severity (critical, high, medium, low and info) and a category (security, cost, configuration and usage). So a rule's findings are one click from the inventory, where you can narrow them further.
Where findings show
- Findings shows the counts by severity, each rule with what it found, the rules that found nothing, and what opened and resolved recently. Filter by severity, category, asset source or asset group.
- A rule's page lists its assets, what resolved, its query and its guide.
- Each asset's page has a Findings tab, and the dashboard shows the counts and the five worst rules.
- Notifications tell you when a sync opens findings, from the severity you choose.
Guides
Every rule has a guide: what a finding means, why it matters, when it's fine and how to tell, the steps to fix it with a CLI command for one asset, and links to the cloud's own documentation.
Findings that save money
Cost rules, such as unused volumes and Elastic IPs, show up in Costs as savings, priced from what each asset costs you.
Not yet
Findings can't be muted yet, and you can't add rules of your own.
Amazon Web Services rules (89)
| Rule | Severity | Category |
|---|---|---|
Bucket policy allows public accessaws.s3.bucket.public-policy | Critical | Security |
All traffic and ports are open to 0.0.0.0/0aws.ec2.securitygroup.all-traffic-open-to-world | High | Security |
Bucket does not fully block public accessaws.s3.bucket.public-access-block-disabled | High | Security |
Cluster is publicly accessibleaws.redshift.cluster.publicly-accessible | High | Security |
DB cluster is publicly accessibleaws.rds.dbcluster.publicly-accessible | High | Security |
DB instance is publicly accessibleaws.rds.dbinstance.publicly-accessible | High | Security |
GuardDuty detector is disabledaws.guardduty.detector.disabled | High | Security |
KMS key is scheduled for deletionaws.kms.key.pending-deletion | High | Configuration |
Public API endpoint is open to the whole internetaws.eks.cluster.public-endpoint-open | High | Security |
RDP (port 3389) is open to the whole internetaws.ec2.securitygroup.rdp-open-to-world | High | Security |
SSH (port 22) is open to the whole internetaws.ec2.securitygroup.ssh-open-to-world | High | Security |
Trail logging is stoppedaws.cloudtrail.trail.logging-stopped | High | Security |
Access key is older than 90 days and unused for 90 daysaws.iam.accesskey.old-unused | Medium | Security |
At-rest encryption is disabledaws.elasticache.cachecluster.at-rest-encryption-disabled | Medium | Security |
At-rest encryption is disabledaws.opensearchservice.domain.at-rest-encryption-disabled | Medium | Security |
Automated backups are disabledaws.rds.dbinstance.backups-disabled | Medium | Configuration |
Bucket has no default encryption configuredaws.s3.bucket.no-encryption | Medium | Security |
Certificate expires within 30 daysaws.acm.certificate.expiring-soon | Medium | Security |
Certificate is in expired stateaws.acm.certificate.expired | Medium | Security |
Certificate is in revoked stateaws.acm.certificate.revoked | Medium | Security |
Classic Load Balancer has no requestsaws.elb.loadbalancer.idle | Medium | Cost |
Cluster storage is not encryptedaws.redshift.cluster.unencrypted | Medium | Security |
Custom NACL allows all inbound traffic from 0.0.0.0/0aws.ec2.networkacl.all-traffic-allowed | Medium | Security |
DB cluster storage is not encryptedaws.docdb.dbcluster.unencrypted | Medium | Security |
DB cluster storage is not encryptedaws.rds.dbcluster.unencrypted | Medium | Security |
DB instance storage is not encryptedaws.rds.dbinstance.unencrypted | Medium | Security |
Default cache behavior allows plain HTTPaws.cloudfront.distribution.insecure-viewer-protocol | Medium | Security |
Deliver logs status is FAILEDaws.ec2.flowlog.failed | Medium | Configuration |
Distribution has no WAF web ACL attachedaws.cloudfront.distribution.no-waf | Medium | Security |
Domain does not enforce HTTPSaws.opensearchservice.domain.https-not-enforced | Medium | Security |
EBS volume isn't encryptedaws.ec2.volume.unencrypted | Medium | Security |
EC2 instance is idleaws.ec2.instance.idle | Medium | Cost |
Elastic IP address is unusedaws.ec2.eip.unused | Medium | Cost |
ElastiCache cluster has no connectionsaws.elasticache.cachecluster.idle | Medium | Cost |
File system is not encryptedaws.efs.filesystem.unencrypted | Medium | Security |
Image in 'error' stateaws.ec2.image.error-state | Medium | Configuration |
Image in 'invalid' stateaws.ec2.image.invalid-state | Medium | Configuration |
In-transit encryption is disabledaws.elasticache.cachecluster.transit-encryption-disabled | Medium | Security |
Instance metadata service allows IMDSv1 (HttpTokens is not required)aws.ec2.instance.imdsv1-allowed | Medium | Security |
Lambda runtime is deprecatedaws.lambda.function.deprecated | Medium | Security |
Load balancer has no trafficaws.elbv2.loadbalancer.idle | Medium | Cost |
MFA is not enabled for the user poolaws.cognito.userpool.mfa-disabled | Medium | Security |
NAT gateway carries almost no trafficaws.ec2.natgateway.idle | Medium | Cost |
NAT Gateway is in failed stateaws.ec2.natgateway.failed | Medium | Cost |
No WAF web ACL is associated with this stageaws.apigateway.stage.no-waf | Medium | Security |
Node-to-node encryption is disabledaws.opensearchservice.domain.node-to-node-encryption-disabled | Medium | Security |
OpenSearch domain is neither searched nor written toaws.opensearch.domain.idle | Medium | Cost |
Peering connection status is expiredaws.ec2.vpcpeeringconnection.expired | Medium | Configuration |
Peering connection status is failedaws.ec2.vpcpeeringconnection.failed | Medium | Configuration |
Peering connection status is rejectedaws.ec2.vpcpeeringconnection.rejected | Medium | Configuration |
Queue has no server-side encryptionaws.sqs.queue.unencrypted | Medium | Security |
RDS instance has no connectionsaws.rds.dbinstance.idle | Medium | Cost |
Secret rotation is disabled or exceeds 90 daysaws.secretsmanager.secret.rotation-disabled | Medium | Security |
Security group opens a port to the whole internetaws.ec2.securitygroup.port-open-to-world | Medium | Security |
Snapshot is not encryptedaws.ec2.snapshot.unencrypted | Medium | Security |
Transfer server failed to startaws.transfer.server.start-failed | Medium | Configuration |
Transfer server failed to stopaws.transfer.server.stop-failed | Medium | Configuration |
Transfer server is offlineaws.transfer.server.offline | Medium | Configuration |
Volume is unusedaws.ec2.volume.unused | Medium | Cost |
Access logging is not configured for this stageaws.apigateway.stage.access-logging-disabled | Low | Configuration |
Alarm actions are disabledaws.cloudwatch.alarm.actions-disabled | Low | Configuration |
Alarm has had insufficient data for over a dayaws.cloudwatch.alarm.insufficient-data | Low | Configuration |
Application Load Balancer access logging is disabledaws.elasticloadbalancingv2.loadbalancer.access-logs-disabled | Low | Configuration |
Bucket versioning is not enabledaws.s3.bucket.versioning-disabled | Low | Configuration |
Certificate is in failed stateaws.acm.certificate.failed | Low | Configuration |
Certificate is in inactive stateaws.acm.certificate.inactive | Low | Configuration |
CloudWatch Container Insights is disabled for this clusteraws.ecs.cluster.container-insights-disabled | Low | Configuration |
Deletion protection is disabledaws.docdb.dbcluster.deletion-protection-disabled | Low | Configuration |
Deletion protection is disabledaws.dynamodb.table.deletion-protection-disabled | Low | Configuration |
Deletion protection is disabledaws.elasticloadbalancingv2.loadbalancer.deletion-protection-disabled | Low | Configuration |
Deletion protection is disabledaws.networkfirewall.firewall.deletion-protection-disabled | Low | Configuration |
Deletion protection is disabledaws.rds.dbcluster.deletion-protection-disabled | Low | Configuration |
Deletion protection is disabledaws.rds.dbinstance.deletion-protection-disabled | Low | Configuration |
EBS volume is attached but never read or writtenaws.ec2.volume.idle | Low | Cost |
ECS service uses under a third of its CPU and memoryaws.ecs.service.oversized | Low | Cost |
Group uses a launch configuration instead of a launch templateaws.autoscaling.autoscalinggroup.legacy-launch-configuration | Low | Configuration |
Image tags are mutableaws.ecr.repository.mutable-tags | Low | Security |
Instance uses a previous generation typeaws.ec2.instance.previous-generation-type | Low | Configuration |
Kinesis stream gets no recordsaws.kinesis.stream.idle | Low | Cost |
KMS key is disabled — data encrypted with it is inaccessible until it is re-enabledaws.kms.key.disabled | Low | Configuration |
Lambda function hasn't been invoked in 90 daysaws.lambda.function.unused | Low | Usage |
Load balancer has a plain-HTTP listeneraws.elasticloadbalancing.loadbalancer.insecure-listener | Low | Security |
Log file integrity validation is disabledaws.cloudtrail.trail.log-validation-disabled | Low | Security |
Log retention is missing or exceeds 365 daysaws.logs.loggroup.no-retention | Low | Cost |
Point-in-time recovery is disabledaws.dynamodb.table.pitr-disabled | Low | Configuration |
Queue has no dead-letter queue configuredaws.sqs.queue.no-dlq | Low | Configuration |
Snapshot is older than 80 daysaws.ec2.snapshot.stale | Low | Cost |
Topic has no subscribersaws.sns.topic.no-subscribers | Low | Configuration |
Trail is not multi-regionaws.cloudtrail.trail.not-multi-region | Low | Configuration |
Google Cloud rules (23)
| Rule | Severity | Category |
|---|---|---|
BigQuery dataset is publicgcp.bigquery.dataset.public | Critical | Security |
Cloud SQL instance accepts connections from anywheregcp.sqladmin.instance.open-to-world | Critical | Security |
Firewall rule opens SSH or RDP to the internetgcp.compute.firewall.admin-ports-open | Critical | Security |
Firewall rule allows ingress from anywheregcp.compute.firewall.open-to-world | High | Security |
GKE cluster uses legacy ABACgcp.container.cluster.legacy-abac | High | Security |
GKE control plane is reachable from any addressgcp.container.cluster.open-control-plane | High | Security |
VM runs as the default service account with full API accessgcp.compute.instance.default-service-account-full-access | High | Security |
Bucket doesn't enforce public access preventiongcp.storage.bucket.public-access-prevention-off | Medium | Security |
Bucket uses fine-grained ACLsgcp.storage.bucket.uniform-access-disabled | Medium | Security |
Cloud SQL instance allows unencrypted connectionsgcp.sqladmin.instance.unencrypted-connections | Medium | Security |
Cloud SQL instance has a public IP addressgcp.sqladmin.instance.public-ip | Medium | Security |
Cloud SQL instance has automated backups offgcp.sqladmin.instance.backups-disabled | Medium | Configuration |
Cloud SQL instance has no connectionsgcp.sqladmin.instance.idle | Medium | Cost |
Compute Engine instance is idlegcp.compute.instance.idle | Medium | Cost |
KMS key has no automatic rotationgcp.cloudkms.crypto-key.rotation-disabled | Medium | Security |
Public DNS zone doesn't use DNSSECgcp.dns.managed-zone.dnssec-off | Medium | Security |
Service account key is older than 90 daysgcp.iam.service-account-key.user-managed-old | Medium | Security |
VM allows interactive serial console accessgcp.compute.instance.serial-port-enabled | Medium | Security |
VM has an external IP addressgcp.compute.instance.public-ip | Medium | Security |
Bucket versioning is not enabledgcp.storage.bucket.versioning-disabled | Low | Configuration |
Cloud SQL instance uses little of its CPU and memorygcp.sqladmin.instance.oversized | Low | Cost |
Subnet has no VPC flow logsgcp.compute.subnetwork.flow-logs-disabled | Low | Configuration |
VM doesn't use Shielded VM integrity checksgcp.compute.instance.shielded-vm-off | Low | Security |
Microsoft Azure rules (29)
| Rule | Severity | Category |
|---|---|---|
Network security group opens SSH or RDP to the internetazure.network.network-security-group.admin-ports-open | Critical | Security |
AKS API server is reachable from any addressazure.containerservice.managed-cluster.open-api-server | High | Security |
AKS cluster has Kubernetes RBAC offazure.containerservice.managed-cluster.rbac-disabled | High | Security |
Container registry allows anonymous pullazure.containerregistry.registry.anonymous-pull | High | Security |
Cosmos DB account accepts traffic from any networkazure.documentdb.database-account.open-network | High | Security |
Network security group allows inbound traffic from anywhereazure.network.network-security-group.open-to-internet | High | Security |
AKS cluster allows local accountsazure.containerservice.managed-cluster.local-accounts | Medium | Security |
App Service app accepts unencrypted HTTPazure.web.site.https-only-off | Medium | Security |
Azure SQL server accepts public network accessazure.sql.server.public-network | Medium | Security |
Azure SQL server accepts TLS older than 1.2azure.sql.server.old-tls | Medium | Security |
Container registry has its admin user onazure.containerregistry.registry.admin-user | Medium | Security |
Cosmos DB account gets no requestsazure.documentdb.database-account.idle | Medium | Cost |
Key vault accepts traffic from any networkazure.keyvault.vault.open-network | Medium | Security |
Key vault has purge protection offazure.keyvault.vault.purge-protection-off | Medium | Security |
Linux VM allows password sign-inazure.compute.virtual-machine.password-authentication | Medium | Security |
MySQL flexible server has no connectionsazure.dbformysql.flexible-server.idle | Medium | Cost |
MySQL server accepts public network accessazure.dbformysql.flexible-server.public-network | Medium | Security |
PostgreSQL flexible server has no connectionsazure.dbforpostgresql.flexible-server.idle | Medium | Cost |
PostgreSQL server accepts public network accessazure.dbforpostgresql.flexible-server.public-network | Medium | Security |
Redis cache accepts unencrypted connectionsazure.cache.redis.non-ssl-port | Medium | Security |
Storage account accepts TLS older than 1.2azure.storage.storage-account.old-tls | Medium | Security |
Storage account accepts traffic from any networkazure.storage.storage-account.open-network | Medium | Security |
Storage account accepts unencrypted HTTPazure.storage.storage-account.https-not-required | Medium | Security |
Storage account allows public blob accessazure.storage.storage-account.blob-public-access | Medium | Security |
VM is idleazure.compute.virtual-machine.idle | Medium | Cost |
Managed disk isn't attached to any VMazure.compute.disk.unattached | Low | Cost |
MySQL flexible server uses little of its CPU and memoryazure.dbformysql.flexible-server.oversized | Low | Cost |
PostgreSQL flexible server uses little of its CPU and memoryazure.dbforpostgresql.flexible-server.oversized | Low | Cost |
Storage account allows shared key accessazure.storage.storage-account.shared-key-access | Low | Security |