Scattered findings
Security problems turned up by accident, as a side effect of other work: a token found here, an outdated database there, an exposed tool somewhere else. There was no single view of the attack surface, and each finding was left with no owner, no severity and no plan.
I proposed a methodical sweep, with one rule I wouldn't break: touch nothing.
Looking without touching
I reviewed the production Kubernetes clusters on seven fronts: versions against end-of-support dates, network exposure, permissions, secrets, workload configuration, database access and exposed admin dashboards.
Everything was done read-only. No credential found was used, and nothing was changed during the review. To say something was "open to the internet", I tested from an ordinary connection, without VPN, so as not to confuse it with "open to whoever is on the internal network". When I found the same password serving several systems, I proved the reuse by comparing hashes, without the report containing a single secret. And every finding was recorded with the command and the observed value.
On a second product, I extended the review with a static review of 14 repositories against the 2025 OWASP Top 10 and a passive external check of the public hosts.
What turned up
The first sweep produced 13 findings: two critical, four high, five medium and two low. There were plain-text credentials in ConfigMaps, with the same password reused across several databases, so a single leak would open production and the backup at the same time. There were Git access tokens in plain text in the GitOps configuration, also present in the repository history. There were databases and dashboards reachable from the internet with no source restriction, unsupported Kubernetes and operating system versions, overly broad permissions, and a critical CVE, CVSS 9.8, in an edge component its own project had already discontinued. In CI, third-party actions were referenced by branch and ran with production credentials in the environment.
In the second product's report, I split out 16 actions for the DevOps team and 12 suggestions for the development team, so each side knew exactly what was theirs.
Order matters
Every critical finding became its own card, with actions in order of risk, acceptance criteria and a rollback plan. Often, the right order was the most important part. Rotating a credential has to come before cleaning the Git history, because rewriting history without revoking the key is useless: the value has already leaked. On the Kubernetes API, the VPN and internal network IPs go into the rule first, and only then does the open rule come out, with a heads-up to the team that uses kubectl. And pod security policies start in warn and audit mode before blocking anything.
The first fixes
I removed the cluster admin binding tied to an individual user on two clusters, after confirming the person kept access through the IAM group and saving a copy of the object. I started moving credentials from ConfigMap to Secret, reducing the copies of the master password, with no impact on production: no container restarted and no error event. And I designed the mitigation for the ingress's critical CVE, with an immediate, reversible step and a migration to another controller, host by host.
What changed
Infrastructure security went from scattered findings to a single inventory, with severity, evidence and an owner. The critical items became cards with an execution and rollback plan, and the first fixes went in with no impact on production.
What I take from it
A security review is only useful if it is safe and actionable. Safe: read-only, without using credentials found and with no secret in the report. Actionable: every finding with evidence, severity, owner and the right order of correction. In security, doing the right thing in the wrong order causes the very problem you wanted to avoid.