Unauthorized Cloud & Infrastructure Access
Detects direct cloud service calls, unauthorized infrastructure provisioning, and cloud credential abuse that bypass controlled workflows. Ansible playbooks should use gated APIs and approved IaC pipelines - not raw SDK/CLI calls to cloud services.
144 rules in unauthorized_cloud_access.yml
CRITICAL: 60 | HIGH: 71 | MEDIUM: 13
| Rule ID | Severity | Title | Description | Refs |
|---|---|---|---|---|
ansible_ | CRITICAL | Ansible AWS SQS Module | Using community.aws or amazon.aws SQS modules for direct queue operations | |
aws_ | CRITICAL | AWS AMI / EBS Snapshot / RDS Snapshot Shared Publicly (–launch-permission Group=all) | A task runs aws ec2 modify-image-attribute with --launch-permission 'Add=[{Group=all}]', aws ec2 modify-snapshot-attribute with --create-volume-permission 'Add=[{Group=all}]', aws rds modify-db-snapshot-attribute with --values-to-add '["all"]', sets launch_permission_users: ['all'] / attribute: launchPermission + value: public in amazon.aws.ec2_ami / community.aws.ec2_ami_copy, OR sets public: true on any AMI/snapshot resource. Public AMIs/snapshots are world-readable - any AWS account (including throwaway 4-digit test accounts) can copy them, mount the EBS volumes, and extract EVERYTHING the original instance had on disk: SSH host keys, service credentials, .bash_history, DB files, app source, Ansible Vault files. 2024 Wiz reports: ~50k public AMIs exist across AWS regions; ~15% contain long-lived credentials, RSA private keys, or customer data. Distinct from S3 public-bucket rules (this is EC2/EBS/RDS). | |
aws_ | CRITICAL | AWS CloudTrail Trail Deletion | aws cloudtrail delete-trail is invoked. CloudTrail is the AWS audit log; deleting trails is a textbook anti-forensics step. | |
aws_ | CRITICAL | CloudTrail Audit Logging Disabled | Stops or deletes CloudTrail logging, hiding subsequent API activity from audit | |
aws_ | CRITICAL | AWS Config Recorder Deletion | Deletes or stops the AWS Config configuration recorder to evade compliance monitoring | |
aws_ | CRITICAL | AWS Config Compliance Disabled | Stops AWS Config recorder or deletes rules, removing compliance monitoring | |
aws_ | CRITICAL | AWS Credentials in Playbook | AWS access keys or secret keys referenced directly in playbook variables | |
aws_ | CRITICAL | ECR Repository Policy Grants Principal ‘*’ (Publicly Pullable Image) | A community.aws.ecs_ecr task sets a repository policy: that contains "Principal": "*" (or "Principal": {"AWS": "*"}) with an Allow Effect and any of ecr:BatchGetImage, ecr:GetDownloadUrlForLayer, ecr:DescribeImages, or ecr:*. This publishes the image to the entire internet. Even if the image is “public-facing” by design, a public ECR repo leaks Dockerfiles, layer-hashes (used to identify installed CVE versions), embedded secrets (env-var ARG leaks), and the exact supply-chain of the application - a high-value recon primitive. | |
aws_ | CRITICAL | GuardDuty Threat Detection Disabled | Disables GuardDuty threat detection, removing security monitoring | |
aws_ | CRITICAL | AWS IAM Access Key Creation | Creates IAM access keys, enabling potentially untracked programmatic access | |
aws_ | CRITICAL | AWS IAM User Creation | Creates an IAM user via aws iam create-user, boto3.client(‘iam’).create_user, or iam.create_user. IAM user creation should run via the community.aws.iam_user module so changes are auditable. | |
aws_ | CRITICAL | AWS IAM Destructive Action | Deletes IAM users, roles, or policies which could disrupt access controls | |
aws_ | CRITICAL | IAM policy grants iam:PassRole ‘*’ to EC2/Lambda/ECS/SageMaker (privilege escalation) | A task renders an IAM policy granting iam:PassRole on Resource: '*' to principals that can launch compute (ec2.amazonaws.com, lambda.amazonaws.com, ecs-tasks.amazonaws.com, sagemaker.amazonaws.com, glue.amazonaws.com, cloudformation.amazonaws.com) - the canonical AWS privilege-escalation primitive (documented by Rhino Security Labs as iam_PassExistingRoleToNewLambdaThenInvoke and 20+ variants). Any user with this permission can pass an arbitrary admin role to a new compute resource they control, then assume full admin within seconds. Listed in every major cloud-security benchmark (CIS AWS 1.5 §1.16, AWS IAM Access Analyzer, Wiz CNAPP top findings 2024). | |
aws_ | CRITICAL | IAM Policy Grants iam:PassRole on Wildcard Resource | Policy grants iam:PassRole with Resource="*" (or a broadly-matching wildcard). PassRole lets the holder attach any IAM role to any service resource (EC2, Lambda, ECS, Glue), yielding direct privilege escalation to the powers of the most privileged role in the account. | |
aws_ | CRITICAL | AWS IAM Policy Manipulation | Attaches policies, creates roles, or modifies IAM permissions for privilege escalation | |
aws_ | CRITICAL | IAM Policy Grants Wildcard Action on Wildcard Resource | Inline or managed IAM policy document contains Statement with Effect=Allow and Action="" (or a service-level wildcard like “iam:”) combined with Resource="*". This is effectively a grant of all permissions - any principal holding it becomes an account administrator. | |
aws_ | CRITICAL | AWS IAM role trust policy uses wildcard principal (role assumable by any AWS account) | A task renders an AWS IAM role trust policy (AssumeRolePolicyDocument) with Principal: '*', Principal: AWS: '*', or Principal: { AWS: '*' } and no Condition block narrowing the trust (no aws:PrincipalOrgID, no aws:SourceAccount, no sts:ExternalId). Any AWS account in the world can assume this role with the AssumeRole API. This is the canonical misconfiguration behind dozens of 2023-2024 cross-tenant data-exfiltration incidents (including the December 2023 CodeSpider chain and multiple bug-bounty disclosures against Fortune-500 tenants). | |
aws_ | CRITICAL | IAM Role Trust Policy Open to Public Principal | AssumeRolePolicyDocument / trust policy has Principal="" or Principal={“AWS”:""} without a restrictive Condition block. Any AWS account (including attackers) can assume the role and obtain temporary credentials for whatever it permits. | |
aws_ | CRITICAL | AWS KMS Key Policy Grants kms:* Or Principal * On Resource * | A task creates or updates a KMS key policy with "Principal": "*" (or "AWS": "*") AND either "Action": "kms:*" or "Action": "kms:Decrypt" / "kms:GenerateDataKey" on "Resource": "*". A wildcard-principal KMS key policy is the worst-case cloud-crypto finding: every encrypted-at-rest secret (EBS volumes, RDS snapshots, Secrets Manager, Parameter Store SecureStrings) keyed with that CMK is decryptable by any IAM principal in any account. This is the 2019 Capital One pattern repeated across every 2024 cloud-breach post-mortem. | |
aws_ | CRITICAL | AWS Lambda Function Creation | Creates Lambda functions from Ansible, which could deploy malicious serverless code | |
aws_ | CRITICAL | AWS Lambda Function URL AuthType=NONE (Unauthenticated Public Invoke) | A task creates a Lambda Function URL (aws_lambda_function_url Terraform, aws lambda create-function-url-config, community.aws.lambda_function_url) with AuthType: NONE / authorization_type: NONE. A Function URL with AuthType=NONE is a public HTTPS endpoint - ANY internet client can invoke the Lambda with zero authentication. The function runs with its execution-role permissions, which often include DB access, secrets retrieval, and cross-service invoke. 2024 Wiz + Orca cloud-research reports consistently find unintended public Function URLs in >15% of scanned AWS orgs. Lambda Function URLs were GA in 2022; this misconfig is a post-2022 footgun (there’s no equivalent in API Gateway - AuthType=NONE is Function-URL-specific). | |
aws_ | CRITICAL | AWS CloudWatch Logs Deletion | Deletes CloudWatch log groups or log streams to destroy evidence | |
aws_ | CRITICAL | AWS Organization Manipulation | Leaves an AWS Organization or manipulates organization policies, removing guardrails | |
aws_ | CRITICAL | AWS RDS / Aurora / DocumentDB Instance PubliclyAccessible=true | A task creates/modifies an RDS instance (community.aws.rds_instance, amazon.aws.rds_instance, aws rds create-db-instance, aws_db_instance Terraform) with PubliclyAccessible=true / publicly_accessible: true. This assigns the DB a public IPv4 address and DNS name reachable from the internet - even with security-group restrictions in front of it, the attack-surface becomes every IP on earth for password-spray, CVE-day-0 (like CVE-2024-10976 pg replication RCE), and known-credential replay. The 2024 Mandiant M-Trends shows >20% of initial-access in cloud IR engagements starts with a public RDS instance. AWS Well-Architected Security Pillar explicitly requires private subnets + NAT-egress + PrivateLink for RDS. | |
aws_ | CRITICAL | Route53 DNS Modification | Modifies DNS records directly, enabling DNS hijacking or traffic redirection | |
aws_ | CRITICAL | S3 Block Public Access Disabled or Bucket ACL Public | Creates or updates an S3 bucket with Block Public Access disabled (BlockPublicAcls=false, IgnorePublicAcls=false, BlockPublicPolicy=false, or RestrictPublicBuckets=false), or sets a public bucket/object ACL (public-read, public-read-write, authenticated-read). This re-enables the data-exfiltration path that BPA exists to prevent. | |
aws_ | CRITICAL | S3 Bucket Policy Grants Principal ‘*’ With Write/Delete (Publicly Writable Bucket) | An amazon.aws.s3_bucket / community.aws.s3_bucket_info / amazon.aws.s3_bucket_notification task with policy: or a community.aws.aws_s3_bucket_policy task contains an Allow statement with Principal: '*' (or Principal: {AWS: '*'}) combined with any write-type action: s3:PutObject, s3:PutObjectAcl, s3:DeleteObject, s3:DeleteObjectVersion, s3:PutBucketPolicy, s3:PutBucketAcl, s3:*. This makes the bucket writable by any anonymous internet user - the exact configuration behind the 2017 Accenture, 2017 Verizon, 2019 Capital One (read path) and 2023 MOVEit (exfil path) incidents, and weaponised by ransomware groups that overwrite objects with .encrypted extensions. | |
aws_ | CRITICAL | AWS Secrets Manager Direct Access | Retrieves secrets directly from AWS Secrets Manager, potentially extracting sensitive credentials | |
aws_ | CRITICAL | Security Group Modification | Modifies VPC security group rules, potentially opening unauthorized network access | |
aws_ | CRITICAL | AWS SSM Remote Command Execution | Sends commands to EC2 instances via SSM, enabling remote code execution outside Ansible | |
aws_ | CRITICAL | AWS IAM Identity Center (SSO) Permission Set Grants AdministratorAccess | A task provisions an AWS SSO permission set whose ManagedPolicies include arn:aws:iam::aws:policy/AdministratorAccess or PowerUserAccess and assigns it to a broad group (Everyone, All Users, AWS-Developers). Because SSO assignments propagate to every account in the org, a single over-broad permission set silently grants admin on hundreds of AWS accounts. | |
az_ | CRITICAL | Azure Key Vault Secret Access | az keyvault secret show/set/delete/list is invoked. Reading Key Vault secrets through the CLI surfaces the secret in stdout and Ansible’s logs. | |
az_ | CRITICAL | Azure Monitor/Diagnostics Disabled | az monitor diagnostic-settings delete, activity-log alert delete, or log-analytics delete is invoked. Each call removes telemetry attackers would otherwise leave behind. | |
azure_ | CRITICAL | Azure Credentials in Playbook | AZURE_CLIENT_SECRET / AZURE_TENANT_ID / AZURE_CLIENT_ID is set to a 20+ char literal in a playbook. The shape leaks service-principal credentials that grant Azure API access. | |
azure_ | CRITICAL | Azure NSG Inbound Rule Allows SSH/RDP From 0.0.0.0/0 Or Internet Service Tag | A task creates/updates an Azure Network Security Group rule (azure.azcollection.azure_rm_securitygroup, azurerm_network_security_rule, az network nsg rule create) with direction: Inbound, access: Allow, and source_address_prefix: * / 0.0.0.0/0 / Internet / Any, combined with destination_port_range: 22 / 3389 (or ranges containing them). This exposes Windows RDP or Linux SSH to the entire internet - immediately subject to unauthenticated password-spray from the >10M-IP scanning infrastructure documented by GreyNoise/Shodan. Azure Defender for Cloud’s Just-in-time VM access feature exists specifically to replace this - its absence means 24/7 exposure. Storm-0501, Akira (2024), and Black Basta (2024-2025) consistently cite open RDP as initial-access vector in Mandiant/CrowdStrike quarterly threat reports. | |
azure_ | CRITICAL | Azure RBAC Owner Role Assigned at Subscription or Management Group Scope | Assigns the Owner (or User Access Administrator / Contributor) built-in role at a subscription or management-group scope. Owner has full control over all resources AND the ability to delegate access, making it the Azure equivalent of AWS AdministratorAccess. Assigning it at /subscriptions/ | |
azure_ | CRITICAL | Azure SQL/PostgreSQL Firewall Rule Allows All Public IPs (0.0.0.0 - 255.255.255.255) | An azure.azcollection.azure_rm_sqlfirewallrule / azure.azcollection.azure_rm_postgresqlfirewallrule / azure.azcollection.azure_rm_mysqlfirewallrule / azure.azcollection.azure_rm_mariadbfirewallrule task sets start_ip_address: '0.0.0.0' + end_ip_address: '255.255.255.255' (or the pseudo-range 0.0.0.0 - 0.0.0.0 ‘AllowAllWindowsAzureIps’). The database is then reachable from every IP on the internet - any leaked connection string gives immediate admin access. This is the #1 Azure database exposure. | |
azure_ | CRITICAL | Azure Storage account connection string with embedded AccountKey | A task hard-codes an Azure Storage connection string of the form DefaultEndpointsProtocol=...;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net - this is the full storage-account master key (base64-encoded 64-byte symmetric secret) granting full read/write/delete on every container + file-share + queue + table in the account. Leaked connection strings are the #1 cause of Azure-related breaches in the 2024 Microsoft Digital Defense Report (e.g. T-Mobile API key leak, numerous Shodan-exposed web.config/application.properties). Matches both Ansible ansible.builtin.set_fact/vars and embedded CI/CD snippets. | |
boto3_ | CRITICAL | Boto3 SQS Client | boto3.client(‘sqs’) is constructed inside an Ansible task. Direct SDK use bypasses the community.aws collection’s idempotency, retry, and error-shape contracts. | |
cloudformation_ | CRITICAL | CloudFormation / CDK / Terraform Template Creating IAM User With Access Keys Or Console Login Profile | A task renders a CloudFormation template (or CDK output, or Terraform aws_iam_user resource inside a stack) that creates AWS::IAM::User + AWS::IAM::AccessKey in the same stack AND/OR sets AWS::IAM::User LoginProfile with a Password property OR attaches a managed policy like AdministratorAccess / PowerUserAccess. This is the classic ‘attacker landed with one-time cred, deploys a stack, gets a persistent admin user with programmatic access keys’ persistence technique - a cornerstone of 2021 CodeCov breach, 2022 LastPass breach, and 2023-2024 multiple Scattered Spider campaigns. Legitimate infrastructure-as-code should create IAM roles + instance profiles (short-lived, assumed, auditable), never IAM users with long-lived access keys. Detected by GuardDuty PrivilegeEscalation:IAMUser/AnomalousPermissionChange but often only after the damage is done. | |
direct_ | CRITICAL | Direct SNS Publish | Publishes directly to an SNS topic, bypassing controlled workflows | |
direct_ | CRITICAL | Hardcoded SQS Queue URL | An SQS queue URL (https://sqs. | |
direct_ | CRITICAL | Direct SQS SendMessage Call | Sends messages directly to an SQS queue, bypassing controlled provisioning workflows | |
docker_ | CRITICAL | Docker Host Filesystem Mount | Mounts sensitive host paths into a container, enabling host escape | |
docker_ | CRITICAL | Docker Privileged Mode | Runs a Docker container in privileged mode (docker run --privileged, --privileged=true, or YAML privileged: true/yes/on/1), granting full host access including all capabilities and direct device-node mounts. Container escape becomes trivial (mount /dev/sda, write /etc/cron.d on the host). | |
entra_ | CRITICAL | Entra Conditional Access Policy Excludes All Users Or Broad Non-Breakglass Groups | A task creates/updates an Entra ID Conditional Access policy (New-MgIdentityConditionalAccessPolicy, az ad policy create, or the Graph POST /identity/conditionalAccess/policies) whose conditions.users.excludeUsers contains "All"/"*", OR whose excludeGroups contains more than the documented break-glass / emergency-access groups (Emergency Access Accounts, Break Glass). A CA policy that excludes all users (or an entire large group) renders MFA / risk-based / location-based controls moot for the excluded population - this is the canonical Storm-0558 / Midnight Blizzard 2023-2024 pivot (attacker-created CA exclusion to bypass MFA on the compromised service principal). | |
entra_ | CRITICAL | Microsoft Entra Conditional Access policy excludes all users, guest, or privileged roles | A task creates or updates an Entra ID Conditional Access policy with excludeUsers: 'All', excludeGroups containing All Users, excludeRoles containing Global Administrator, or a massive exclusion list that defeats the policy’s intent (e.g. an MFA-enforcement policy that excludes break-glass + legacy protocols + service accounts + every admin). The 2024 Midnight Blizzard / Storm-0558 + 2024 Microsoft internal breach post-mortems specifically cite over-broad CA exclusions as the root cause - a single break-glass account with no MFA, combined with password-spray, gave tenant-wide access. Matches microsoft.graph.conditional_access_policy, Update-MgIdentityConditionalAccessPolicy, and direct Graph REST POST /identity/conditionalAccess/policies with overly permissive exclusion blocks. | |
gcloud_ | CRITICAL | GCP Audit Logging Modification | Modifies or disables GCP logging sinks, potentially hiding activity from audit | |
gcloud_ | CRITICAL | GCP Secret Manager Access | gcloud secrets versions access (or create/delete) is invoked from a task. Reading Secret Manager values into the playbook exposes them in stdout, no_log defaults, and the controller host. | |
gcp_ | CRITICAL | GCP Compute Firewall Rule Allows SSH/RDP Ingress From 0.0.0.0/0 | A task creates a GCP VPC firewall rule (google_compute_firewall Terraform, google.cloud.gcp_compute_firewall, gcloud compute firewall-rules create) with direction: INGRESS, source_ranges: 0.0.0.0/0, and allowed.ports containing 22 or 3389. Identical internet-exposure risk to the Azure rule. GCP’s own Security Command Center lists Open SSH Port / Open RDP Port as category OPEN_SSH_PORT / OPEN_RDP_PORT findings. Default VPC in new GCP projects ships with a default-allow-ssh rule that allows 0.0.0.0/0 -> 22 - the single most common GCP misconfiguration finding per Google Cloud’s 2024 security-posture report. | |
gcp_ | CRITICAL | GCP IAM Binding to allUsers or allAuthenticatedUsers | Binds a GCP IAM role to allUsers (the entire internet) or allAuthenticatedUsers (any Google account holder). This is the GCP equivalent of a public S3 bucket and grants the bound role’s permissions - often roles/storage.objectViewer, roles/viewer, or worse - to anonymous/any callers. | |
gcp_ | CRITICAL | GCP Service Account Key in Playbook | GCP service account key JSON or GOOGLE_APPLICATION_CREDENTIALS set in playbook | |
gcp_ | CRITICAL | GCP Workload Identity Federation Provider With Empty Or Wildcard attribute_condition | A task creates a Workload Identity Pool Provider (gcloud iam workload-identity-pools providers create-oidc, google_iam_workload_identity_pool_provider) with --attribute-condition empty, missing, or matching .*/true - and no --allowed-audiences narrowing. Without an attribute condition, ANY OIDC token signed by the configured issuer (e.g. https://token.actions.githubusercontent.com) is accepted - meaning every GitHub Actions workflow in every public repo on the internet can impersonate your GCP service account. This is the 2023 token.actions.githubusercontent.com / 2024 GitLab WIF misuse CVE class. | |
gcs_ | CRITICAL | GCS Bucket IAM Grants Storage Admin / Object Admin To allUsers Or allAuthenticatedUsers | A task grants roles/storage.admin, roles/storage.objectAdmin, roles/storage.objectCreator, or roles/storage.legacyBucketOwner to allUsers (fully anonymous world) or allAuthenticatedUsers (any Google account - effectively public). These roles permit OBJECT CREATION and DELETION, not just read - an attacker can overwrite existing objects with malware, pivot the bucket into a drive-by-download hosting service, or delete-and-ransom the bucket. GCS IAM supports Uniform Bucket-Level Access (UBLA) since 2020 but the ACL-compatible role-bindings (storage.legacyBucketOwner) remain a common misconfiguration. Google’s 2024 Security Command Center catches this as a HIGH finding (category: PUBLIC_BUCKET_ACL). | |
inline_ | CRITICAL | Inline Boto3 Script Execution | Runs inline Python boto3 code in a command/shell task, hiding AWS calls from static analysis | |
kubectl_ | CRITICAL | kubectl Run with Overrides | Runs ad-hoc pods with override flags, potentially with escalated privileges | |
s3_ | CRITICAL | S3 Bucket ACL Set To public-read / public-read-write / authenticated-read | A task sets an S3 bucket or object canned-ACL to public-read-write (world-writable - allows attackers to overwrite objects, plant phishing pages, or serve malware from the victim’s domain), public-read (world-readable - direct data-leak primitive), or authenticated-read (any AWS account can read, i.e. effectively public since anyone can create an AWS account in 60s). AWS BlockPublicAccess defaults to ON since 2023 for NEW buckets but does NOT retroactively apply to existing buckets, and can be bypassed by explicit ACL overrides. The 2024 Guardicore / Censys / Wiz public-S3 reports consistently find >50k buckets still exposing customer data this way. | |
snowflake_ | CRITICAL | Snowflake user created with password auth and no MFA / network policy | A task creates a Snowflake user (via CREATE USER, snowflake.snowflake_cli, community.general.snowflake_user, or SQL) with PASSWORD = '...' but WITHOUT a subsequent ALTER USER ... SET MUST_CHANGE_PASSWORD + MFA or RSA_PUBLIC_KEY assignment, and without a NETWORK_POLICY. This is the exact mis-configuration exploited in the June 2024 Snowflake customer campaign (UNC5537, Mandiant) that compromised 165+ Snowflake customers (Ticketmaster, Santander, AT&T, Advance Auto Parts) - attackers used infostealer-harvested credentials because MFA was not enforced at the tenant or user level. Snowflake now requires MFA for all password sign-ins as of Nov 2025 but many deployed Ansible playbooks predate that. | |
vault_ | CRITICAL | Vault Policy Manipulation | Creates or modifies Vault policies from a playbook, potentially granting unauthorized access | |
vault_ | CRITICAL | HashiCorp Vault Token in Playbook | Vault root or service tokens hardcoded in playbook variables | |
aks_ | HIGH | AKS Managed Identity Assigned Broad Subscription-Scope Role | A task assigns a user-assigned managed identity to an AKS pod / node-pool with Contributor, Owner, or User Access Administrator at subscription or resource-group scope via az role assignment create --scope /subscriptions/.... Any pod that federates to that UAMI inherits subscription-level control - the standard 2025 Azure attack-path pattern. | |
aws_ | HIGH | AWS API Gateway Method / Route Authorization Set To NONE (Unauthenticated Endpoint) | A task creates an API Gateway method (REST aws_api_gateway_method / HTTP aws_apigatewayv2_route) with authorization: NONE / authorization_type: NONE / --authorization-type NONE. Distinct from Lambda Function URL (separate service); API Gateway’s NONE means any internet caller can invoke the backend integration - SQS, Lambda, DynamoDB, Step Functions - without authentication. Legitimate use-cases exist (health-check endpoints, OAuth callback routes) but the default should be CUSTOM, AWS_IAM, COGNITO_USER_POOLS, or JWT. The 2024 AWS Security Hub APIGateway.8 finding specifically flags NONE authorizers on non-OPTIONS routes. Many CloudFormation/Terraform templates copy-paste authorization: NONE from tutorials and leave it in production. | |
aws_ | HIGH | API Gateway Method Without Authorization (authorization_type: NONE) | A community.aws.api_gateway / community.aws.aws_api_gateway task (or a Swagger/OpenAPI-imported REST API) defines a method with authorization_type: NONE (or AuthorizationType: NONE). The endpoint is unauthenticated and reachable by any internet caller; combined with any sensitive downstream integration (Lambda, DynamoDB proxy, RDS Data API) this is a direct data-exposure or RCE pivot. | |
aws_ | HIGH | AWS CDK Deploy from Ansible | Deploys CDK stacks directly, bypassing IaC pipeline controls | |
aws_ | HIGH | CloudFormation Deploy from Ansible | Deploys CloudFormation stacks directly, bypassing IaC pipeline controls | |
aws_ | HIGH | CloudWatch Alarm Deletion | Deletes CloudWatch alarms, removing operational and security alerting | |
aws_ | HIGH | Direct DynamoDB Access | aws dynamodb put-item/get-item/scan/query/delete-item or boto3.client(‘dynamodb’) is invoked inside a task. Use the community.aws.dynamodb_* modules so the change appears in Ansible diff output. | |
aws_ | HIGH | AWS EBS Volume Created With encrypted=false (Unencrypted At-Rest) | A task creates an EBS volume (amazon.aws.ec2_vol, community.aws.ec2_vol, aws ec2 create-volume, aws_ebs_volume Terraform) with encrypted: false / --no-encrypted / Encrypted: false. Snapshots of unencrypted volumes are also unencrypted - any cross-account snapshot-sharing, AMI-building, or S3 export retains data in cleartext. Since 2023 AWS supports account-level EnableEbsEncryptionByDefault - bypassing it for specific volumes is the pattern caught here. Unencrypted EBS fails PCI-DSS 3.5.1 + HIPAA §164.312(a)(2)(iv) + SOC 2 CC6.7. Distinct from generic cloud-storage-encryption rules; this catches EBS specifically because block storage often holds DB data, swap, and encryption-key material at rest. | |
aws_ | HIGH | AWS EC2 Reconnaissance or Modification | Describes EC2 instances for recon, creates snapshots for data theft, or modifies instance attributes | |
aws_ | HIGH | Direct EC2 Instance Launch | Launches EC2 instances directly, bypassing provisioning controls | |
aws_ | HIGH | AWS ECR Registry Login | Authenticates to ECR container registry, potentially to push/pull unauthorized images | |
aws_ | HIGH | Direct ECS Task Launch | Launches ECS tasks directly, bypassing deployment pipeline controls | |
aws_ | HIGH | AWS EFS Filesystem Without Encryption at Rest (encrypt: false / kms_key_id missing) | A community.aws.efs task creates an EFS filesystem with encrypt: false (or omits both encrypt: and kms_key_id: - default is false for filesystems created via API/SDK before 2022, and remains overridable via Ansible). EFS volumes often back home-directory data, shared-app state, or ML-training scratch - any of which can contain PII, source-code, SSH private keys, or model weights. An attacker with elasticfilesystem:DescribeMountTargets + a VPC foothold can mount the share and read everything in plaintext; worse, an AWS-side snapshot copy to a rogue account remains readable without any AWS-to-AWS decryption step. | |
aws_ | HIGH | AWS EKS Cluster Public Endpoint Open to 0.0.0.0/0 | A community.aws.eks_cluster task sets endpoint_public_access: true AND public_access_cidrs: to either the default (which is ['0.0.0.0/0']) or explicitly lists 0.0.0.0/0 / ::/0. This exposes the Kubernetes API server - including /api/v1/namespaces/*/secrets reachable with any compromised kubeconfig - to the entire internet. Even with OIDC + IAM authentication enforced, the control-plane surface is attack-probeable 24/7 (think: CVE-2024-3400 style 0-days, upstream kube-apiserver bugs, audit-log-probe DoS). CIS EKS Benchmark 5.4.2. | |
aws_ | HIGH | AWS EKS Token Retrieval | Retrieves EKS authentication tokens, potentially for unauthorized cluster access | |
aws_ | HIGH | IAM Role Trust Policy Allows Cross-Account AssumeRole Without ExternalId | A community.aws.iam_role / amazon.aws.iam_role / community.aws.iam_managed_policy task defines a trust policy (assume_role_policy_document: or similar) that grants sts:AssumeRole to a foreign AWS account principal (Principal: {AWS: 'arn:aws:iam::<different-account-id>:root'} or Principal: {AWS: <12-digit-id>}) without a matching Condition: {StringEquals: {sts:ExternalId: ...}}. This is the classic ‘confused deputy’ pitfall - any customer/vendor/third-party to which the foreign account ID is known can assume the role on your behalf. | |
aws_ | HIGH | EC2 Instance Metadata Service v1 (IMDSv1) Allowed | Creates or modifies an EC2 instance / launch template with HttpTokens=optional (IMDSv1), which permits unauthenticated SSRF-style credential theft against the 169.254.169.254 metadata endpoint. This is the Capital One 2019 breach primitive - any SSRF or file-read bug in a workload running on such an instance yields the instance-profile credentials. | |
aws_ | HIGH | AWS KMS Decrypt Operation | Decrypts data using KMS from a playbook, potentially accessing encrypted secrets | |
aws_ | HIGH | OIDC / Web-Identity Trust Policy Missing Subject Condition | IAM role trust policy federates an OIDC provider (GitHub Actions, Cognito, EKS IRSA, GitLab OIDC) but the Condition block does not pin sub (repository/workflow/namespace) and/or aud. Attackers with any workload using that IdP - including public forks or arbitrary repos - can mint a token and assume this role. | |
aws_ | HIGH | Direct RDS Management | Creates, modifies, or snapshots RDS instances directly from a playbook | |
aws_ | HIGH | Direct S3 Data Access | Copies, syncs, or presigns S3 objects directly, enabling data exfiltration or payload staging | |
aws_ | HIGH | AWS S3 Listing or Bucket Deletion | Lists S3 bucket contents for reconnaissance or deletes entire buckets | |
aws_ | HIGH | AWS Default VPC Security Group Modified to Allow Traffic Instead of Restricting It | An amazon.aws.ec2_security_group task targets the default security group of a VPC (name: default or group_name: default) AND adds explicit rules: / rules_egress: entries - OR fails to set both rules: [] and rules_egress: [] to deny-all. The AWS default SG is attached implicitly to any ENI launched without an explicit SG (common via misconfigured Launch Templates, legacy playbooks, Lambda-in-VPC with missing vpc_subnet_ids wiring). When it carries any allow-rule, those rules silently apply cluster-wide to every default-SG-attached resource. CIS AWS Benchmark 5.4 explicitly states the default SG MUST deny all traffic. | |
aws_ | HIGH | AWS SSM Parameter Store Access | Reads or writes SSM parameters directly, potentially accessing stored secrets | |
aws_ | HIGH | AWS STS AssumeRole | Assumes an IAM role from within a playbook, which could escalate privileges | |
aws_ | HIGH | AWS STS AssumeRole for privileged role without MFA condition (aws:MultiFactorAuthPresent) | A task renders an IAM role trust policy for a privileged role (name matches admin|root|break-glass|superuser|poweruser|poweradmin|billing|audit|iam-admin|security-admin OR attached policies include AdministratorAccess / IAMFullAccess) without a Condition requiring aws:MultiFactorAuthPresent: true or aws:MultiFactorAuthAge. Static long-lived access keys assuming privileged roles without MFA is the top-reported exploitation path in the 2024 IBM X-Force Threat Intelligence Index for cloud breaches - a single leaked developer key can escalate to account-wide admin. | |
aws_ | HIGH | AWS Cross-Account AssumeRole Trust Policy Without sts:ExternalId Condition | A task creates an IAM role with "Action": "sts:AssumeRole" and "Principal": { "AWS": "arn:aws:iam::<different-account>:root" } (or any cross-account ARN) WITHOUT a "Condition": { "StringEquals": { "sts:ExternalId": "..." } } block. Missing sts:ExternalId on a cross-account assume-role is the canonical Confused-Deputy primitive (AWS SRA Pillar 2 finding, 2024 AWS Well-Architected Security Tool default alarm): any third-party SaaS that knows your account ID + role name can assume the role from any of their customers’ tenants, not just yours. | |
az_ | HIGH | Azure Container Registry Access | Accesses Azure Container Registry for push/pull/login operations | |
az_ | HIGH | Direct Azure CLI Command | az vm/aks/storage/keyvault/network/ad/role/group/webapp is invoked from a shell task. Direct az CLI use bypasses the azure.azcollection module surface and its idempotent parameters. | |
az_ | HIGH | Direct Azure SQL Operations | az sql db/server/mi create/delete/update is invoked. Schema and instance changes via shell tasks bypass change tracking available in azure.azcollection modules. | |
azure_ | HIGH | Azure Storage Container Public Access Set To container Or blob (Anonymous Enumeration / Read) | A task sets an Azure Storage container’s publicAccess property to container (anonymous enumeration AND read of every blob - the worst level) or blob (anonymous read of individual blobs if the name is known, no enumeration). The account-level allowBlobPublicAccess must also be true for these to take effect - but this task-level opt-in is the canonical anti-pattern caught by Azure Policy [Preview] Storage accounts should prevent public blob access. The 2023-2024 Microsoft Threat Intelligence reports document Midnight Blizzard (APT29) and LAPSUS$ leveraging exactly this misconfiguration post-exfiltration to stage data outside the victim’s perimeter. | |
azure_ | HIGH | Azure Cosmos DB Account IP Allowlist 0.0.0.0-255.255.255.255 (Publicly Accessible) | An azure.azcollection.azure_rm_cosmosdbaccount task sets ip_range_filter: '' (empty = allow all), ip_range_filter: '0.0.0.0/0', public_network_access: Enabled without any virtual-network rule, or a filter string containing 0.0.0.0 without matching compensating is_virtual_network_filter_enabled: true + a specific VNet ACL. Cosmos DB data-plane is then reachable from any internet IP that possesses a primary/secondary key. Combined with the common mistake of storing Cosmos keys in Git, this is a direct data-exfiltration primitive. | |
azure_ | HIGH | Azure Privileged Role Assigned As Permanent Instead Of PIM-Eligible | A task runs New-AzRoleAssignment, az role assignment create, or azure.azcollection.azure_rm_roleassignment with a privileged role (Owner, Contributor, User Access Administrator, Global Administrator, Privileged Role Administrator, Application Administrator) granted permanently - i.e. without going through Privileged Identity Management (Open-AzureADMSPrivilegedRoleAssignmentRequest / New-AzRoleAssignmentScheduleRequest with RequestType: AdminAssign + ScheduleInfo bounded). Permanent admin roles violate the Zero-Trust just-in-time principle and were the single largest attack-surface finding in the 2024 Microsoft State of Multicloud Risk report. | |
azure_ | HIGH | Azure Storage Account With Default Network Rule Set to Allow | An azure.azcollection.azure_rm_storageaccount task sets network_acls.default_action: Allow (or omits network_acls: entirely - Azure default is Allow). This exposes the storage account (blob, file, queue, table) to the public internet on its *.blob.core.windows.net / *.file.core.windows.net endpoints; any client with a valid SAS token, account key, or anonymous-access-configured container can reach it from anywhere. CIS Azure Benchmark 3.7 mandates default_action: Deny. | |
azure_ | HIGH | Azure Storage SAS token with long expiry or over-privileged permissions | A task generates or embeds an Azure Storage SAS (Shared Access Signature) token with an expiry ≥ 7 days, with write/delete/permanent-delete permissions on an entire account/container, or without IP restriction - the 2023 Microsoft Storm-0558 and 2024 Midnight Blizzard intrusions both leveraged over-scoped SAS tokens for long-term data exfiltration because SAS tokens are bearer credentials that cannot be revoked without rotating the underlying storage account key. Matches azure.azcollection.azure_rm_storageaccount_info/azure_rm_storageblob with sas_token/signed_expiry > 7d, az storage blob generate-sas --expiry more than 7 days out, and signed-permissions strings (sp=) containing racwdxltmeop or rwdlacup on account SAS. | |
boto3_ | HIGH | Boto3 S3 Client | Python boto3 S3 client or resource used in an Ansible task for direct bucket operations | |
cloud_ | HIGH | Cloud Instance Metadata Access | Queries cloud instance metadata endpoints (AWS, GCP, Azure) to extract credentials or config | |
direct_ | HIGH | Direct Lambda Invocation | Invokes a Lambda function directly, bypassing API Gateway controls | |
docker_ | HIGH | Docker Exec into Container | docker exec runs commands inside a running container. The shape sidesteps the container’s declared entrypoint and is rarely how legitimate config-management interacts with containers. | |
docker_ | HIGH | Docker Registry Login | Authenticates to a Docker registry via CLI, potentially exposing credentials in process args | |
docker_ | HIGH | Dangerous docker/podman run Flags - Privileged or Host-Access Container | A shell task launches a container with flags that break the container sandbox: --privileged, --pid=host, --net=host / --network=host, --ipc=host, --userns=host, --cap-add=SYS_ADMIN / SYS_PTRACE / NET_ADMIN / ALL, or a bind-mount of a sensitive host path (-v /:, -v /var/run/docker.sock:, -v /etc:, -v /root:, -v /proc:, -v /sys:, -v /dev:). Each of these flags turns the container into a full-host-compromise primitive (T1611 - Escape to Host) documented in IR write-ups for 2024-2025 TeamTNT, Kinsing, and the actions/upload-artifact supply-chain escape. Plain docker run -d --name foo image:tag without these flags is a normal deployment and is NOT flagged. | |
eks_ | HIGH | EKS / IAM OIDC Provider With Missing or Stale Thumbprint | A task creates an aws_iam_openid_connect_provider (via community.aws.iam_managed_policy or boto3) without setting ThumbprintList, with a placeholder value ('0000000000000000000000000000000000000000'), or with a thumbprint that is not the published EKS root CA thumbprint for the cluster region. With an unverified thumbprint, an attacker who compromises the OIDC issuer’s CA can mint tokens for the IRSA-bound roles - effectively cluster-to-cloud lateral movement. | |
gcloud_ | HIGH | Direct gcloud CLI Command | gcloud compute/iam/pubsub/functions/run/sql/container is invoked from a shell task. Direct CLI use sidesteps the google.cloud collection’s typed parameters and idempotency checks. | |
gcloud_ | HIGH | GCP KMS Operations | gcloud kms decrypt/encrypt or keys create is invoked from a task. KMS material flowing through stdout is a textbook secret-leak shape; use the google.cloud module set instead. | |
gcp_ | HIGH | GCP Compute Instance with Full Cloud-API Scope (https://www.googleapis.com/auth/cloud-platform) | A google.cloud.gcp_compute_instance / google.cloud.gcp_compute_instance_template task sets service_accounts.scopes: to include https://www.googleapis.com/auth/cloud-platform (or the aliases cloud-platform / compute-rw,cloud-platform). This grants the VM’s attached service-account IAM permission to call ANY Google Cloud API the SA is authorized for - in effect making the VM metadata-server token a cluster-wide admin credential. Anyone who exploits the workload (SSRF, RCE, container escape) can curl -s -H 'Metadata-Flavor: Google' http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token and then call gcloud storage cp gs://* / gcloud compute instances list / gcloud iam service-accounts keys create. | |
gcp_ | HIGH | GCP Metadata Server Access | Queries the GCP metadata server, potentially extracting credentials or project info | |
gcp_ | HIGH | GCP user-managed service account key (long-lived JSON key) created | A task creates a user-managed service account key via gcloud iam service-accounts keys create, google.cloud.gcp_iam_service_account_key, or direct REST projects.serviceAccounts.keys.create. User-managed SA keys are long-lived (no expiry by default), rarely rotated, and are the most common root-cause of GCP breaches per Google Cloud Threat Intelligence H2-2024 (33% of incidents). The December 2023 Storm-0558 postmortem + 2024 Volexity reports on GCP-hosted SaaS breaches both traced back to leaked SA key JSON in public git. GCP’s own Organization Policy iam.disableServiceAccountKeyCreation is now enabled by default for new projects since Q2 2024. | |
gcp_ | HIGH | GCP Cloud SQL Instance With Public IP Enabled (ipv4_enabled: true) | A google.cloud.gcp_sql_instance task sets settings.ip_configuration.ipv4_enabled: true (or omits ip_configuration: entirely - Cloud SQL default is ipv4_enabled: true for new instances). The database gets a public IPv4 address on the internet; anyone who discovers the IP can attempt credential-stuffing, log4shell-style injection on the wire protocol, or exploit Cloud-SQL-Proxy impersonation (combined with a leaked service-account key). CIS GCP Benchmark 6.6 + Even authorized_networks: doesn’t help - a forgotten 0.0.0.0/0 entry is the most common CSPM finding on Cloud SQL. | |
gke_ | HIGH | GKE Workload Identity Binds KSA To Broadly-Scoped GSA | A task binds a Kubernetes ServiceAccount to a Google Service Account using roles/iam.workloadIdentityUser where the GSA has roles/owner, roles/editor, or roles/iam.serviceAccountTokenCreator at project/folder/org scope. Any pod that mounts the KSA silently inherits owner-level access to the whole project - a single compromised container becomes a full GCP takeover primitive. | |
gsutil_ | HIGH | gsutil Data Access | gsutil cp/mv/rm/rsync/cat is invoked. Direct gsutil access bypasses the google.cloud.gcp_storage_object module’s idempotent semantics. | |
helm_ | HIGH | Helm Install from External Repo | Installs Helm charts from untrusted or unverified repositories | |
kubectl_ | HIGH | kubectl File Copy | Copies files to/from pods, enabling data exfiltration or payload injection | |
kubectl_ | HIGH | kubectl Secret Creation | Creates Kubernetes secrets directly via kubectl, potentially with plaintext values | |
kubectl_ | HIGH | kubectl Delete Resources | Deletes Kubernetes resources directly, potentially causing service disruption | |
kubectl_ | HIGH | kubectl exec into Running Pod | Executes commands inside a running Kubernetes pod from an Ansible task | |
kubectl_ | HIGH | kubectl Port Forward | Creates network tunnels to pods, potentially bypassing network policy controls | |
mcp_ | HIGH | MCP (Model Context Protocol) Server Exposed Over Network With No Auth (Claude/Cursor Integration RCE) | A task runs an MCP (Model Context Protocol - Anthropic 2024 / OpenAI 2025) server over SSE or HTTP transport, with allow_unauthenticated: true, auth: none, MCP_SERVER_TRANSPORT=sse + MCP_SERVER_HOST=0.0.0.0 and no MCP_AUTH_TOKEN, OR with the stdio transport incorrectly exposed via an inetd / socat wrapper over TCP. MCP servers expose tools (often run_shell, read_file, execute_sql) that the LLM client calls - unauthenticated network-exposed MCP means anyone on the network can invoke those tools with the MCP process’s privileges. The 2024-2025 tool-calling RCE class: an attacker prompts the exposed server with a crafted tool call. Unlike the LangChain ShellTool rule (caught by langchain_shell_tool_unconstrained), this targets the MCP server-config layer which is the 2025 attack surface for Claude Desktop, Cursor, Cline, Continue.dev, and OpenAI Responses integrations. | |
nfs_ | HIGH | NFS Export Grants rw + no_root_squash (Remote Root On Exported Volume) | A task renders /etc/exports (or equivalent nfs-ganesha config) with an export line containing BOTH rw AND no_root_squash. With no_root_squash, remote clients connecting as uid=0 retain UID 0 on the server - directly combined with rw, any NFS client can write files as root into the exported tree, read everyone’s ~/.ssh/id_rsa, modify SUID binaries, and drop shells via echo 'root::0:0:root:/root:/bin/bash' >> /etc/passwd. The canonical lateral-movement primitive in flat-L2 datacenters where the NFS-server-to-client network is trusted but clients are not. Distinct from generic nfs_export_open findings - this specific combo is the direct RCE-as-root primitive. | |
oci_ | HIGH | Oracle Cloud (OCI) CLI Command | Executes Oracle Cloud Infrastructure CLI commands from a playbook | |
oci_ | HIGH | OCI Object Storage Access | Accesses Oracle Cloud object storage for potential data exfiltration | |
okta_ | HIGH | Okta Sign-On Policy Rule With Zero Factor Requirement Or Network Zone = Anywhere For Admin Apps | A task renders an Okta Sign-On policy (okta policies create, okta.okta_api custom module, or the /api/v1/policies/<id>/rules Okta Management API) whose rule has actions.signon.requireFactor: false, actions.signon.factorRequirement: [] (empty), or conditions.network.connection: ANYWHERE - applied to a group with admin privileges or to the Okta Console app itself. Zero-factor sign-on to Okta Admin + ANYWHERE network zone = password-spray-compromised admin account becomes unrestricted Okta tenant takeover (the exact Scattered Spider 2022-2024 attack chain on MGM, Caesars, Clorox). | |
ollama_ | HIGH | Ollama / LM Studio / vLLM Server Bound To 0.0.0.0 With No Auth Proxy | A task runs ollama serve with OLLAMA_HOST=0.0.0.0:11434 (or :11434 which binds to all interfaces in Ollama ≤0.1.34), lms server start --host 0.0.0.0, vllm serve ... --host 0.0.0.0, or renders a systemd unit / Docker compose with --network=host for these local-LLM servers. None of these tools ship with authentication - bind-to-public means any TCP client can invoke inference, list models (model-exfil for LoRA fine-tunes containing private data), push arbitrary models (LOAD a weaponized GGUF that triggers memory-corruption in llama.cpp parser - see 2024 CVE-2024-42478 in llama-cpp parser), and consume GPU quota to $$$ cost in cloud. Shodan / Censys report ~20,000 exposed Ollama instances as of 2025 - typical fingerprint /api/tags returns JSON with no auth. | |
panos_ | HIGH | paloaltonetworks.panos Management Profile Enables Insecure Protocols (HTTP/Telnet) | A paloaltonetworks.panos.panos_management_profile (or deprecated panos_interface) task enables http: true or telnet: true on an interface management profile. HTTP and Telnet transmit the firewall-admin session (including initial login credentials and session cookies) in cleartext over the management plane. Any on-path observer - including a compromised branch-office router between the admin jumpbox and the NGFW - recovers PAN-OS admin credentials and escalates to full rule-base / threat-prevention-bypass control. 2024 Unit42 telemetry found 11% of panos management profiles in IaC repos had this misconfig. | |
panos_ | HIGH | paloaltonetworks.panos Security Rule With source_ip: any AND destination_ip: any | A paloaltonetworks.panos.panos_security_rule (or deprecated panos_security_rule) task declares both source_ip: any (or ['any']) and destination_ip: any. A Palo Alto security rule with any/any/any semantics is effectively a permit-all rule regardless of application/service restrictions applied downstream - and worse, these rules are commonly placed above more-restrictive ones in the rulebase, short-circuiting them. This is the single most-exploited misconfiguration in on-prem -> cloud firewall migrations (cf. Palo Alto PAN-SA-2024-0012 advisory). | |
podman_ | HIGH | Podman Run from Ansible | podman run is invoked from a shell task instead of via the containers.podman.podman_container module. The shell shape loses Ansible’s idempotency, parameter validation, and check mode. | |
pulumi_ | HIGH | Pulumi Deploy from Ansible | Runs Pulumi up/destroy from an Ansible task, bypassing IaC pipeline controls | |
samba_ | HIGH | Samba server min protocol Set To NT1 / CORE / LANMAN (SMBv1 Server Enabled) | A task renders /etc/samba/smb.conf with server min protocol = NT1, CORE, LANMAN1, LANMAN2, or COREPLUS. This makes the Samba server accept SMBv1 connections - the same protocol that Windows hosts have been hardened against since 2017 (EternalBlue / WannaCry). Linux-Samba-hosted file shares running SMB1 are the primary pivot target in mixed Windows+Linux environments where Windows fleets are SMB1-disabled but Linux file servers are not. Modern Samba (4.11+) defaults to SMB2_02 but legacy installs and Docker images (dperson/samba, elswork/samba) often keep SMB1 for ‘compatibility’. | |
serverless_ | HIGH | Serverless Framework Deploy | Deploys serverless applications directly, bypassing pipeline controls | |
terraform_ | HIGH | Terraform Apply from Ansible | Runs terraform apply from an Ansible task, bypassing IaC pipeline controls | |
vault_ | HIGH | Vault CLI Read/Write from Ansible | Reads or writes secrets via the vault CLI, bypassing Ansible Vault integration and audit controls | |
vector_ | HIGH | Vector DB (Weaviate / Qdrant / Milvus / Chroma) Anonymous Access Enabled Or Empty API Key | A task renders a vector-database config with authentication disabled: Weaviate authentication.anonymous_access.enabled: true (or missing authentication.apikey.enabled: true), Qdrant service.api_key: "" / unset with service.http_port: 0.0.0.0, Milvus common.security.authorizationEnabled: false, Chroma CHROMA_SERVER_AUTHN_PROVIDER="" / unset. Vector databases hold embeddings generated from proprietary / PII-laden corpora (customer support transcripts, internal wikis, code bases, medical records) - unauth access allows (1) wholesale vector exfil (then inversion attacks to reconstruct near-original text per 2024 Google Research ‘Stealing Part of a Production Language Model’), (2) collection enumeration for reconnaissance, (3) poisoning via upsert to corrupt RAG retrieval downstream of the DB. Shodan finds >5,000 unauthenticated Weaviate/Qdrant instances as of 2025. | |
ansible_ | MEDIUM | Ansible Kubernetes Module Without securityContext Hardening | Uses Kubernetes Ansible modules for direct cluster operations without a securityContext: hardening block in the task body. Hardened specs (runAsNonRoot, readOnlyRootFilesystem, capabilities drop, automountServiceAccountToken false) are covered by dedicated k8s structural rules; this advisory catches the case where none of that is present. | |
aws_ | MEDIUM | amazon.aws.ec2_instance Explicitly Assigns a Public IPv4 Address | An amazon.aws.ec2_instance (or legacy ec2) task sets assign_public_ip: true (or network.assign_public_ip: true for VPC-launched instances). Per AWS Well-Architected Security Pillar § SEC-01 and CIS AWS 5.2, workload instances should sit in private subnets and egress via a NAT/gateway - public IPv4 exposure shortens time-to-first-scan from hours to ≈90 seconds on common ports (22, 3389, 445) and is the top-of-funnel for mass-exploitation campaigns (e.g. Looney Tunables, CVE-2024-6387 regreSSHion). | |
aws_ | MEDIUM | ECS Service Assigns Public IP (Task Exposed Directly to Internet) | A community.aws.ecs_service task sets network_configuration.assign_public_ip: ENABLED, which attaches a public IPv4 to every task ENI. The task is directly reachable from the internet on whatever ports its security group permits, bypassing the ALB/NLB/private-subnet pattern that makes up the normal AWS ingress perimeter. This exposes container application vulnerabilities, unauthenticated admin endpoints (Prometheus, actuator/*, /debug/pprof), and leaked container secrets to the entire internet. | |
aws_ | MEDIUM | ECS Task Definition Uses Non-Recommended network_mode (host/bridge/none) | A community.aws.ecs_taskdefinition task sets network_mode: host, network_mode: bridge, or network_mode: none. AWS security baseline recommends awsvpc for ECS tasks because it gives each task its own ENI + security-group, enabling task-level network segmentation and IAM-per-task (task roles). host mode shares the EC2 instance’s network namespace (no segmentation, breaks awslogs source-IP attribution), bridge uses the legacy Docker bridge (no SG-per-task), and none breaks service discovery. host mode specifically lets a container SSRF the instance metadata service (169.254.169.254) with IMDSv1 = instance-profile credentials, escalating task-level compromise to instance-level. | |
aws_ | MEDIUM | IAM Account Password Policy Weak or Missing Complexity | A community.aws.iam_password_policy task sets the account-level IAM password policy with any of: minimum_password_length < 14, require_symbols: false, require_numbers: false, require_uppercase: false, require_lowercase: false, password_reuse_prevention < 24, max_password_age > 90, or hard_expiry: false. These settings fall below the CIS AWS Foundations benchmark, PCI-DSS v4.0 and NIST 800-63B requirements. IAM console users (typically operators and emergency break-glass accounts) become brute-force-able, and long max-ages enable stolen-credential replay windows. | |
aws_ | MEDIUM | IAM Policy Attached Directly to User (Group-Based Assignment Bypassed) | A community.aws.iam_user / amazon.aws.iam_user / community.aws.iam_policy task attaches a managed policy or inline policy directly to an IAM user (managed_policy: [...], policy_name: with iam_type: user in the old API). CIS AWS Foundations 1.15 requires that privileges be granted to IAM GROUPS (then users added to groups), not to users directly, because direct attachments (a) bypass group-membership-based auditing, (b) create orphaned permissions when users are deleted piecemeal, and (c) make bulk-permission-changes error-prone. | |
aws_ | MEDIUM | S3 Bucket Created Without Access Logging (requesting_payer/logging Absent) | An amazon.aws.s3_bucket task creates/manages a bucket without a requester_pays: + server access logging: target bucket, and no accompanying community.aws.s3_logging / CloudTrail data-event trail scoped to the bucket. Server access logs (or their modern replacement, CloudTrail S3 data events) are the PRIMARY forensic evidence for investigating object-level reads / writes / deletions after an incident; without them, determining what an attacker exfiltrated is impossible. This is regulatory table-stakes for HIPAA, PCI-DSS req 10, SOC 2 CC7.2,. | |
aws_ | MEDIUM | S3 Bucket Created Without Server-Side Encryption (encryption: none or missing) | An amazon.aws.s3_bucket task creates/manages a bucket with encryption: 'none', or explicitly does not set encryption: while also not configuring default bucket encryption via community.aws.s3_bucket_encryption / amazon.aws.s3_bucket_notification. Without default SSE, objects PUT without an explicit ServerSideEncryption header land unencrypted; a leaked pre-signed URL or IAM compromise exposes cleartext data. AWS enabled default SSE-S3 for new buckets in Jan 2023 but Ansible playbooks that were written before that date (and run against OLD buckets) still toggle it off or leave it implicit. | |
aws_ | MEDIUM | AWS STS Identity Enumeration | Uses STS to enumerate caller identity or generate session tokens for persistence | |
azure_ | MEDIUM | Azure Subnet Created Without Associated Network Security Group | An azure.azcollection.azure_rm_subnet task creates a subnet without a network_security_group: reference (and no task later binds an NSG via azure_rm_networkinterface at the NIC level - which is the inferior alternative). Without an NSG on the subnet, ALL traffic between workloads on the subnet and between peered VNets flows unrestricted, violating zero-trust east-west segmentation. Microsoft Defender for Cloud scores this as a ‘Secure Score’ degrader. | |
azure_ | MEDIUM | Azure Virtual Machine Without OS/Data Disk Encryption (ADE or CMK) | An azure.azcollection.azure_rm_virtualmachine / azure.azcollection.azure_rm_virtualmachinescaleset task creates a VM/VMSS where os_disk.managed_disk_type is set but no os_disk.encryption_settings:/security_profile: block is present AND no companion azure.azcollection.azure_rm_diskencryptionset is referenced via disk_encryption_set on either OS or data disks. The managed disk is then encrypted only with the default platform-managed key (PMK); recovery of the encrypted VHD by a rogue Azure operator or a stolen snapshot (copy to another subscription) would decrypt transparently. Azure Disk Encryption (ADE) with Key Vault customer-managed keys gives the tenant control over key-rotation and revocation. | |
gcp_ | MEDIUM | GCP Compute Disk / Instance Disk Created Without Customer-Managed Encryption Key (CMEK) | A google.cloud.gcp_compute_disk / google.cloud.gcp_compute_instance task creates a persistent disk without disk_encryption_key: referencing a Cloud KMS key (kms_key_name: or kms_key_service_account:) and without source_image_encryption_key:. Data at rest is still encrypted - but only with Google-managed keys (GMEK). The tenant has no ability to rotate the key on demand, revoke access during an incident, prove custody for compliance (PCI, HIPAA, FedRAMP Moderate/High), or cryptographically shred the disk. | |
panos_ | MEDIUM | paloaltonetworks.panos Security Rule With application: any OR service: any | A paloaltonetworks.panos.panos_security_rule task declares application: any or service: any (or ['any']). Palo Alto’s App-ID and Service are the main fine-grained-control axes beyond source/destination IP - an any value on either completely defeats the purpose of migrating from a stateful L3/L4 firewall to a NGFW. Tunnelable apps (e.g. ssh-tunnel, web-browsing carrying exfil-disguised-as-HTTP, dns with DNS-over-HTTPS, msrpc with DCSYNC) become available on any port if service: any. |