The 5 Security Misconfigurations Found in Every IR & SOC Report
It’s 2026. We have AI agents writing our Terraform, Quantum-safe cryptography is rolling out, and we are on the verge of AGI.
It’s 2026. We have AI agents writing our Terraform, Quantum-safe cryptography is rolling out, and we are on the verge of AGI.
And yet, I am still reading Incident Response (IR) reports that look exactly like they did in 2021.
Let’s be real: sophisticated zero-days are rare. Most cloud breaches aren’t caused by a genius hacker bypassing your firewall with a custom exploit. They are caused by your junior dev taking a shortcut on a Friday afternoon, or your senior architect forgetting to clean up a POC.
Based on the IR trends we’re seeing, here are the 5 repeat offenders the zombie misconfigurations that are fueling the major breaches of 2025 and maybe in 2026.
1. Identity Federation
In 2026, nobody uses long-lived access keys anymore (hopefully). We use OIDC and Identity Federation. The problem? We are too generous with who we trust.
You set up a Trust Relationship allowing a 3rd party vendor (like a cloud monitoring tool or a CI/CD SaaS) to assume a role in your account. But you messed up the Condition block.
An attacker compromises the vendor. Because your trust policy doesn’t enforce an ExternalId or specific sub (subject) filtering, the attacker uses the vendor’s legitimate access to pivot into your environment. This is the “confused deputy” problem on steroids.
The Bad Policy (Don’t do this)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:root" }, // The Vendor's Account
"Action": "sts:AssumeRole"
// MISSING: Condition block for ExternalId!
}
]
}The Fix
Always require a unique sts:ExternalId or strictly filter the OIDC subject.
"Condition": {
"StringEquals": {
"sts:ExternalId": "Your-Unique-Secret-ID",
"token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main"
}
}Public S3/Blob Buckets
You’d think we solved this. But with the rise of AI, data scientists are spinning up massive data lakes to train models. Often, these are outside the purview of the central platform team.
A data team needs to share a 5TB dataset with an external AI auditing firm. Permissions are hard, so they just toggle the Public Access switch to On for just 5 minutes. They forget. 48 hours later, a scanner finds it.
The Command to Find Them
Don’t click through the console. Script it. Here is a quick AWS CLI loop to find buckets where public access block is disabled:
# Check for buckets that DO NOT have Public Access Block enabled
for bucket in $(aws s3api list-buckets --query "Buckets[].Name" --output text); do
status=$(aws s3api get-public-access-block --bucket $bucket 2>&1)
if [[ $status == *"NoSuchPublicAccessBlockConfiguration"* ]]; then
echo " DANGER: Bucket $bucket has NO public access block!"
fi
doneThe Fix
Move enforcement up a level. Use Service Control Policies (SCPs) at the AWS Organization level (or Azure Policy) to mathematically forbid the creation of public buckets. Make it impossible for the root user of a child account to even try to make a bucket public.
Privileged Service Accounts
We put MFA on humans. We don’t put MFA on the build-bot service account.
Your Jenkins or GitHub Actions runner needs to deploy to production. To save time, someone attached the AdministratorAccess policy to the IAM role used by the runner. An attacker compromises the repo, modifies the build script (CI/CD poisoning), and simply runs: aws iam create-user --user-name BackdoorUser because the build bot had permission to do anything.
The Fix
Least Privilege is mandatory. If a bot only needs to update an ECS service, do not give it CreateRole. Use Attribute-Based Access Control (ABAC).
"Condition": {
"StringEquals": {
"aws:PrincipalTag/Department": "DevOps",
"aws:PrincipalTag/Project": "PaymentGateway"
}
}Make the bot prove it belongs to the project before it touches the project’s resources.
Cyber Security Notes and Cheat Sheets
Abandoned Dev Environments
Cloud sprawl is real. In 2026, companies have thousands of “Test-Env-2” and “POC-Llama-Migration” resource groups rotting in the corner.
An EC2 instance from 2024 is still running a legacy version of a web server. It’s not monitored by the SOC because it was tagged Env: Dev. Attackers breach it, establish persistence, and use it as a jump box to scan your internal production VPCs.
The Investigation Command
Use tools like Steampipe or CloudQuery to query your infrastructure like a database. Find instances older than 90 days.
select
instance_id,
launch_time,
tags ->> 'Owner' as owner
from
aws_ec2_instance
where
launch_time < now() - interval '90 days'
and state_name = 'running';The Fix
Implement TTL (Time To Live) tagging. Every non-prod resource must have a terminate_after tag. Run a “Janitor Monkey” script nightly that ruthlessly deletes anything past its expiry date.
K8s RBAC Hell
Kubernetes is the operating system of the cloud, and its Role-Based Access Control (RBAC) is a nightmare to manage manually.
Developers complain that their kubectl commands are failing. The admin gets tired of debugging and creates a ClusterRoleBinding that binds the developer’s group to cluster-admin. Congratulations, that developer’s laptop credential is now a root key for the entire cluster.
The Technical Trap
The difference between RoleBinding (namespace specific) and ClusterRoleBinding (entire cluster) is massive.
The Lazy Admin Manifest:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: developers-are-gods
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin # <--- The fatal flaw
apiGroup: rbac.authorization.k8s.ioThe Fix
- Never use
cluster-adminfor users. - Use tools like Kubiscan or Krane to visualize your RBAC graph.
- Command to audit who has cluster-admin:Bash
kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'
Conclusion
We can buy all the AI-driven security tools in the world, but if we leave an S3 bucket open or give a build-bot admin rights, we are just automating our own demise. The fix isn’t a new product; it’s better hygiene.