The app started with three roles. When I audited it, there were 94 permissions, 17 roles, and a function called checkAccess that was 400 lines of nested conditionals.
A client's AI coding agent had contents:write on every repo in the org. When I asked who approved that, the answer was "the setup wizard." The defaults are the danger zone.
A client connected 11 MCP servers to their development environment in three months. When I reviewed the OAuth scopes, two of them had write access to production infrastructure. Nobody had checked.
A client's multi-tenant SaaS had menus, routes, and role checks — all in the browser. The API behind it would happily serve any tenant's data to anyone with a valid session token. It took eight months for someone to notice.
A client's API had been running Node 16 for two years past end-of-life. When a critical OpenSSL vulnerability dropped, the "we'll upgrade next quarter" plan collapsed into a three-week fire drill. The upgrade itself wasn't hard. Undoing two years of drift was.
A client found one of their API keys in a public error log. Tracing where that key actually lived took longer than fixing the leak — and revealed a secrets management problem nobody wanted to own.
The Axios supply chain attack reminded me of a dependency audit I ran at a client last year. What I found was worse than any vulnerability scanner could flag.