A build pipeline needs to read one private repository, so somebody creates a token and puts it in the CI secret store. It works, the pipeline goes green, and everybody moves on. Nine months later an agent is added to the same pipeline to triage failing tests, and it inherits the environment it runs in, including that token.

Nobody made a decision at that point. There was no review, no ticket, and nothing to approve. The agent simply started up inside a process that already had credentials, which is how almost every agent gets its access.

When somebody finally reads the token's scope, it turns out to be organisation-wide rather than repository-scoped, because that was the quickest option on the afternoon it was created and it worked first time. It has never expired. It is now held by something that reads text from tickets and decides what to do next.

Think about how your agent authenticates. Somewhere there is a token. It might be in an environment variable, a config file, a keychain entry, or a secrets manager the agent can read from. It was put there deliberately, by somebody sensible, so the agent could do its job.

Now ask a different question about it. Not who issued it, but what it permits, and for how long

For most teams the honest answers are: more than the agent has ever needed, and for ever. Neither is negligence. Both are the path of least resistance, and together they define the worst day you can have.

Blast radius is a property of the token

There is a comforting way to think about an agent, which is that its risk is proportional to what you ask it to do. Ask it to fix a failing test and the risk is roughly test-shaped.

That is not how it works. The risk is the full set of actions its credentials permit, because anything that can influence the agent's input can spend those credentials. What it was asked to do determines what usually happens. What it is permitted to do determines what can happen.

This is why the interesting attacks against agents are so boring at the technical level. There is no exploit and no privilege escalation, because none is required. The privilege is already sitting in the process, and the attacker's only job is to get a sentence in front of the model.

The read-only credential that reads everything

A specific case, because it comes up constantly and it sounds safe. A team gives their agent a read-only database user, reasoning that a read-only credential cannot break anything.

It cannot break anything. It can read the customer table.

Read-only is a control on integrity. Nothing about it addresses confidentiality, and for an agent that summarises what it reads into tickets, pull requests and chat messages, confidentiality is usually the exposure that matters. The agent debugging a slow query does not know that the forty sample rows it pasted into the ticket are real people, and the ticket system does not know it should not show them to a contractor.

Read versus write is the wrong axis. The question is which rows, which columns, and where the answer is allowed to end up.

The tokens you have forgotten

There is a second-order version of this that is worse, and almost every organisation has it.

Credentials issued to agents are rarely tied to a person, a project or a lifecycle. When an engineer leaves, there is a process: accounts are disabled, laptops come back, access reviews catch what the process missed. When an experiment with an agent is quietly abandoned, there is no process at all. The repository goes stale, the pipeline stops running, and the credential stays valid indefinitely.

These are the most dangerous credentials you hold, for a simple reason: nobody is watching the systems they belong to. An alert on unusual activity assumes somebody would notice the alert. For an abandoned project, nobody is subscribed.

The credential nobody remembers issuing is the one nobody will notice being used.

The fix is unglamorous and it works: every credential gets an owner and an expiry at the moment it is created, and expiry is the default rather than something you opt into. If renewing takes a deliberate act, abandoned access removes itself, which is the only cleanup process that has ever reliably run.

Four changes

None of these require a new product. They are the same access control practice you already apply to people, applied to an actor that does not get tired.

1. Make the credential short-lived

A token that expires in an hour is a fundamentally different object from one that expires never. It changes theft from a permanent compromise into a race, it forces the issuing path to exist and be automated, and it means a token found in a log or a container image next year is worthless. If your agent holds anything that has been valid since it was set up, that is the first thing to change.

2. Scope it to the work, not to the system

Grant on views rather than tables, on one queue rather than the service desk, on one repository rather than the organisation. The test is whether somebody can state the permission set in a sentence. If describing what the agent may do requires the word "everything" or a shrug, it is not scoped, it is inherited.

3. Separate the identity from the human

An agent should not use a person's credentials, and it should not share an identity with other automations. The first destroys the meaning of that person's access reviews. The second destroys attribution, which quietly removes your ability to investigate anything later. One identity per agent is not bureaucracy, it is the thing that makes every other control legible.

4. Treat the output destination as part of the permission

This is the one that gets missed. You scoped what the agent may read and then let it write wherever it likes. A credential that can read customer records and an integration that can post to a public channel are, combined, an exfiltration path that neither one looks like on its own. Permissions compose, and nobody reviews the composition.


Where to look this afternoon

You do not need a project to find out where you stand. You need thirty minutes and a willingness to be unimpressed.

  1. List every credential your agents currently hold. If that list does not exist, the fact that it does not exist is the finding.
  2. For each one, write down its expiry. Count how many say never.
  3. For the broadest one, write down in a single sentence what it permits. Notice how hard that is.
  4. Ask who else can influence what that agent reads. Wikis, tickets, repositories, email, shared drives, anything indexed.
  5. Multiply the last two together. That number is your actual exposure, and it is almost never the number people expect.

Check your AI risk exposure