Security, secrets and dependencies

The specific security mistakes agents make, why credentials must never enter a prompt, and how to review an added package.

Credentials

  1. Never paste a key, token or password into a prompt. Transcripts are files on disk and are sometimes shared.
  2. Point the agent at .env.example, never .env, and refer to variables by name.
  3. Use environment variables at runtime so no secret is ever written into source.
  4. Keep secrets out of client-side code - anything in a browser bundle is public, however it was written.
  5. If a value did reach a transcript or a commit, rotate it. Removing the text does not undo the exposure.
Bad prompt:
"Connect to postgres://admin:hunter2@db.internal:5432/prod and add the index"

Better:
"Add a migration for an index on orders.created_at.
Use the connection from DATABASE_URL, which is already in the environment.
Do not print or log the connection string."
⚠️
The dangerous instruction is 'get it working'. An agent asked to make something connect will reach for whatever credential is reachable on the machine. What fixed the problem locally can be a production credential in a config file in a diff. Name the variable and forbid the rest.

The mistakes agents actually make

MistakeWhere it appearsFix
SQL built by string concatenationRepository and migration codeParameterised queries, always
Authorisation checked in the UIRoute handlersCheck on the server, per request
Missing ownership checkFetch-by-id endpointsScope the query to the current user
Verbose errors returned to clientsError handlersLog detail, return a code
Secret in a client bundleFront-end configMove to a server route
CORS set to wildcard with credentialsServer configAllow only known origins
Password compared with ==Auth codeA constant-time comparison
No rate limit on loginAuth routesRate limit and lockout
// generated, and wrong: authorisation is implied by the route name
app.get("/orders/:id", async (req, res) => {
  res.json(await db.order.findUnique({ where: { id: req.params.id } }));
});

// correct: the query itself is scoped to the caller
app.get("/orders/:id", async (req, res) => {
  const order = await db.order.findFirst({
    where: { id: req.params.id, userId: req.user.id },
  });
  if (!order) return res.status(404).json({ error: { code: "NOT_FOUND" } });
  res.json(order);
});

The pattern to check in every generated handler: does the query constrain the row to the current user, or does it fetch by identifier and trust that only the right people call it?

Added dependencies

git diff package.json package-lock.json

# is this package real, and is it the one you meant?
npm view <package> repository homepage maintainers time.modified

# what will it pull in?
npm ls --all | wc -l
npm audit --omit=dev
  • Check the name character by character against the real package. A one-letter difference is the whole attack.
  • Look at who publishes it, when it was last updated, and how many maintainers there are.
  • Prefer a package with few transitive dependencies; each one is code you now depend on.
  • Ask whether the dependency is needed at all - a date formatter is usually twenty lines.
  • Pin versions and commit the lockfile, so the code that runs today is the code that runs tomorrow.
"Before adding any dependency, tell me what it is for and what it pulls
in. If it can be done in twenty lines of code we already have, do that
instead."

That instruction alone removes a large share of generated package additions, because most of them exist to avoid writing code the agent could easily have written.

FAQ

Why are agents so prone to authorisation bugs?
Authorisation is a property of the whole request path, and it is invisible in the local view of one function. Generated code reproduces the common shape of a fetch-by-id endpoint, which is exactly the shape that omits the ownership check. Review it explicitly in every handler.
Is it safe to let an agent run my test suite?
Generally yes, if the tests are yours and the environment is not production. Be careful with anything that runs migrations, seeds data or calls a real external service - a test run should not be able to reach production credentials or a production database.

Reviewing generated code like an owner Shipping, documenting and maintaining an agent-built project

Last refreshed 2026-09-18.