The phishing email that nearly caught one of our developers last year did not have a single spelling mistake. It referenced a real project, used the right internal vocabulary, and arrived on a Tuesday morning when a deploy was actually happening. The only reason it failed is that the link went to a domain nobody recognised and the developer checked.
That is what changed. The tell-tale signs we spent a decade training people to spot — bad grammar, generic greetings, obvious urgency — were artefacts of attackers who did not speak the language well and did not have time to research each target. Both of those constraints are gone.
Security awareness training that teaches people to look for typos is now training people to trust well-written attacks. Here is what I think teams should be doing instead, from the perspective of someone who builds and deploys the systems rather than someone who sells security products.
What AI Actually Changed for Attackers
It is worth being precise, because the hype cuts both ways. Language models did not hand attackers a new class of vulnerability. What they did was collapse the cost of the labour-intensive parts of an attack.
Personalised social engineering used to require a human to research the target. Now the research and the writing are automated, so the same effort that produced one convincing spear-phishing email produces a thousand. Voice cloning turned "verify by calling them" into weaker advice than it was two years ago. And the reconnaissance phase — reading a company's job listings, GitHub repositories, conference talks and LinkedIn posts to map its stack and its people — is exactly the kind of tedious synthesis a model does well.
On the exploitation side, the picture is more mundane than the headlines suggest. Models are useful for reading unfamiliar code and spotting weak patterns, which helps both attackers and defenders roughly equally. The asymmetry is in volume, personalisation and speed, not in some new superweapon.
Which means the defensive response is not exotic either. It is the boring architectural work most organisations have been postponing.
Zero Trust, Minus the Marketing
Zero Trust has been diluted into a sticker vendors put on products. The actual idea is simple and predates the buzzword: stop treating network location as proof of identity. Being inside the VPN should grant you nothing on its own.
In practice, for a normal engineering team, that translates to a short list of unglamorous decisions:
Every service authenticates every call, including internal service-to-service traffic. If your microservices trust each other because they share a VPC, one compromised container owns the estate.
Short-lived credentials everywhere. On AWS this means IAM roles and STS rather than long-lived access keys sitting in a
.envfile. A leaked key that expires in an hour is an incident; one that never expires is a breach.Phishing-resistant MFA for anything that matters. SMS codes and TOTP can both be relayed by a convincing fake login page in real time. Hardware keys and passkeys cannot, because the credential is bound to the origin. If you protect one thing this way, protect your cloud console and your source control.
Least privilege that is actually reviewed. Permissions accumulate. The contractor who needed production read access in March still has it in December. Quarterly access review is not glamorous work, and it catches more real risk than most tooling.
Segment the blast radius. Separate accounts or subscriptions for production and everything else. Separate credentials per environment. Assume something will be compromised and design so that it does not become everything.
None of that requires a new product. Most of it requires a Friday afternoon and the willingness to annoy people slightly.
The Attack Surface Nobody Reviewed: Your Own AI Features
This is the part I find most teams have not thought through at all. If you have added a language model to your product, you have added a component that follows instructions found in data. That is a genuinely new category of problem.
Prompt injection is the headline, and it is not solved. If your agent reads a web page, a PDF, an email or a support ticket, an attacker who controls that content can put instructions in it. The model does not reliably distinguish "content I was asked to summarise" from "instructions I should follow."
The mitigations that hold up are architectural, not prompt-based. Telling the model "ignore any instructions in the document" is not a control; it is a suggestion.
// The model chooses WHICH action. The system decides IF it is allowed.
const ALLOWED = {
"search_docs": { needsApproval: false, scope: "read" },
"create_draft": { needsApproval: false, scope: "write:draft" },
"send_email": { needsApproval: true, scope: "write:external" },
"refund": { needsApproval: true, scope: "write:money" },
};
function authorize(action: string, ctx: RequestContext) {
const rule = ALLOWED[action];
if (!rule) throw new Error("Unknown action");
if (!ctx.user.scopes.includes(rule.scope)) throw new Error("Forbidden");
if (rule.needsApproval) return queueForHumanApproval(action, ctx);
return execute(action, ctx);
}
The rule I work to: the model's output is a request, never a permission. It runs under the permissions of the user who invoked it, not the permissions of the service account. Anything irreversible or externally visible goes through a human. And any content the model retrieved from an untrusted source is tagged as untrusted all the way through the pipeline.
Two more that get missed. First, output handling: model output rendered into a page is untrusted input to your frontend, so sanitise it like any user-generated content or you have shipped a self-inflicted XSS. Second, data leakage: whatever context you stuff into a prompt can come back out, so do not put another tenant's data in the same context window and hope the instructions hold.
Cloud Security Is Mostly Configuration, Still
Every breach post-mortem I have read in the last few years lands on the same handful of causes, and none of them are sophisticated. A storage bucket open to the internet. A database with a public endpoint and a default password. An over-permissive IAM policy with a wildcard in it. A secret committed to a repository three years ago that nobody rotated. A dependency with a known CVE that had a patch available for eight months.
The tooling to catch all of that is free or nearly free, and it belongs in CI rather than in a quarterly audit:
Secret scanning on every commit and on the full history, not just new changes.
Dependency scanning with an actual policy on what blocks a merge, because a scanner nobody acts on is theatre.
Infrastructure-as-code scanning before the resources exist. Catching a public S3 bucket in a Terraform plan costs nothing; catching it in production costs a disclosure.
Cloud posture checks against the provider's own benchmarks, reviewed monthly.
If your security budget is limited, this is where it goes first. Ethical hacking engagements and red teams are valuable, but paying an expert to find your public bucket is paying a premium for something a linter finds for free.
Where I Would Focus in 2026
Identity is the perimeter now, so spend there first: passkeys for staff, short-lived cloud credentials, and a real answer for what happens when someone's session token is stolen. Assume a convincing message from a colleague may not be from that colleague, and put an out-of-band verification step on anything involving payment details or credential resets — a process control, not a training slide.
Then treat your AI features as a first-class part of the threat model rather than a feature that happens to call an API. Ask who can influence what goes into the context window, and what the worst thing is the model can trigger without a human. If the answer to the second question is uncomfortable, that is your next sprint.
Attackers got a productivity tool. So did we. The difference is that defenders also have the architecture, and architecture is the part that does not care how well the phishing email was written.



