AI-generated code security review

Most of what is written about AI and code is about the code: is it insecure, does it hallucinate a package, does it reproduce a vulnerable pattern. That is one of the two risks, and increasingly it is the smaller one. The other is that the assistant is no longer a text box. It has a token, a checkout and a pipeline.

Risk one: the code, and the controls it stresses

Generated code does not introduce a new vulnerability class. It changes the rate and the shape of the old ones, and it does that faster than the controls around it were tuned for. Four controls take the strain first:

  • Human review depth. Reviewers read a large, fluent, plausible diff differently from a small handwritten one. Review that was calibrated on the second does not transfer to the first, and approval rates rise while attention falls.
  • Test adequacy. Tests generated alongside the code tend to assert the behaviour that was written rather than the behaviour that was required, so coverage rises without confidence rising with it.
  • Dependency introduction. A suggested import is a supply chain decision made silently. The review looks at whether a new dependency can reach a merge without anyone deciding to take it on, and whether a package that does not exist can be installed on a typo.
  • Secrets in generated code. Assistants produce plausible configuration, and plausible configuration contains plausible credentials. Real ones arrive when context includes them.

The practice set for this is NIST SP 800-218A, Secure Software Development Practices for Generative AI and Dual-Use Foundation Models, which extends the Secure Software Development Framework to generative AI, and the relevant failure category when generated output is consumed without validation is OWASP LLM05 Improper Output Handling.

Risk two: the agent is a privileged actor

A coding assistant that can check out a repository, run a build, open a pull request and trigger a pipeline is an identity in your software supply chain. It reads issues, web pages, documentation and test output — all untrusted content — and it acts on what it reads. That is OWASP LLM06 Excessive Agency with commit rights, and it belongs in the same permission model as every other agent you run: see agentic AI and MCP security, where the boundary testing and confused-deputy analysis for agents is set out in full. The coding agent is not an exception to that model. It is usually the most privileged member of it.

The specific questions: which repositories is it scoped to, and is that scope enumerated or inherited from a human account? What credentials does its pipeline hold, and can a build it triggers read them? Can it merge, or approve its own pull request? Does branch protection distinguish it from a person? What does a malicious issue comment, fetched as context, let it do?

Hardening the agent

  • Repository scope. An explicit allowlist, not organization-wide access, and a separate machine identity rather than a developer’s personal token.
  • CI credentials. Workflows triggered by agent-authored branches run with the least privilege available and no access to deployment secrets; secrets are exposed only to workflows that a human approval has released.
  • Merge rights. None. Branch protection requires review by an identity that is not the author, and the agent is an author like any other.
  • Branch protection. Enforced for administrators too, since the exception that exists for emergencies is the one an agent inherits when it runs under an administrator’s token.

A coding agent should hold the permissions of a new contractor on their first day: read and write on a working branch in the repositories it was scoped to, no merge rights, no production credentials, and no access to the secrets its own pipeline uses. The test of the model is simple: if the agent were fully compromised tomorrow, what would it reach, and which of that would anybody notice?

Gates worth adding, and where they belong

Controls are cheapest where the feedback is fastest, so the recommendation places them across three points rather than piling them at the pull request:

  • At the developer. Secret scanning before commit, and dependency resolution that fails on a package that does not exist rather than installing whatever does.
  • At the pull request. Static analysis tuned to fail the build rather than decorate the diff; a dependency policy gate; and a required reviewer who is not the author.
  • Before release. Provenance for what is being shipped, and verification that what is deployed is what was reviewed.

A gate that reports without blocking is documentation. The review says which of yours are which, which is frequently the most uncomfortable page of it.

What reviewers should look for

Reviewer guidance is part of the deliverable because the reviewers are the control that is actually under load. The patterns worth naming: authorization checks that are present on the endpoint but not on the object; input validation that checks shape but not authority; error handling that swallows the failure path the test never exercises; a plausible-looking dependency nobody chose; configuration defaults that are convenient rather than safe; and code that consumes model output or external data and treats it as trusted.

An optional sample review grounds all of this in your actual output: we read a set of recent merged changes you select and report what the patterns are in your codebase rather than in general. That is a review of source you supply, read-only, and it is not testing of a running system — a distinction that matters for how it is scoped and what it can claim.

What you receive

  • A control review of the four pressure points, with what each currently catches and what it does not.
  • An agent permission model: the target state for repository scope, credentials, merge rights and branch protection, with the changes to get there.
  • Recommended gates, placed at developer, pull request and release, marked blocking or advisory.
  • Reviewer guidance your team can put in a pull request template, drawn from your own code where a sample review is in scope.

Where the concern extends to the models and artifacts themselves, see AI supply chain and model integrity; for the underlying development practice, secure development.

How the work is bounded

The scope is agreed in writing before work starts, and the engagement is quoted in writing with it.

SecHB does not issue certifications, attestations or audit opinions: those come from accredited certification bodies, CPA firms and QSAs. The work here is what an organization does to be ready for them.

Nothing here is legal advice. Where a question turns on the law, the work is done alongside the client’s counsel, not instead of them.

Questions we are asked

Should we stop using coding assistants?

Stopping is not the recommendation and would not hold anyway. The recommendation is to treat the assistant as what it is — a very fast contributor with no accountability — and to make the controls that catch a fast contributor’s mistakes strong enough to matter.

Does this replace a secure code review?

This is a review of the controls around generated code, not a line-by-line review of your application. A secure code review of a specific service is a separate engagement, and the two answer different questions.

What permissions should a coding agent actually have?

A coding agent should hold the permissions of a new contractor on their first day: read and write on a working branch in the repositories it was scoped to, no merge rights, no production credentials, and no access to the secrets its own pipeline uses.

Do you need repository access?

Repository access is not required for the control review, which runs on configuration, policy and pipeline definitions. It is required only for the optional sample review, and then read-only, on repositories you name.

Review the controls, not the anecdotes

Describe which assistants your developers use, what the agent can reach, and how a change gets merged. The reply says what the review would cover.

Discuss a scope