Should a coding agent be allowed to read your .env file? Generally, no — and the reason is not that agents are untrustworthy. It is that the agent almost never needs the secret. It needs the capability the secret unlocks, and those are two different things you can separate.
The sentence the page rests on. A leaked function is a disclosure you triage over weeks. A leaked credential is an access-control failure that is live the moment it leaves your boundary, usable by anyone who reads it, with no exploitation step in between.
Plain-English explainer · 2017 TSC with revised 2022 points of focus · OWASP Top 10 for LLM Applications 2026 · Last reviewed August 2026
Restrict by default. Permit narrowly, explicitly and with a time-box. And wherever you can, redesign so the question does not arise — because the agent needs to call the API, not to know the key. That is the whole answer, and everything below is the argument for it. The reason secrets deserve a rule of their own is not that coding agents are careless. It is that an agent moves content into places that source code does not usually reach: a conversation transcript, a provider’s request path, a tool-call payload, a subagent’s context, a commit message, a pull-request description, a bug ticket a human pasted it into. Source code lives in a repository with an access model attached to it. A value that enters an agent’s context inherits that context’s entire surface, and that surface is wider than most teams have mapped. The controls that follow are ordered deliberately: the ones that remove the secret beat the ones that supervise access to it.
Key Takeaways
- A secret is a distinct class of object from source code. Leaked source is a confidentiality problem with a slow blast radius. A leaked credential is an access-control failure that is immediately actionable by anyone who reads it, without an exploit in between.
- The risk is not agent malice. It is reach — agents surface content into transcripts, provider infrastructure, tool payloads, error reports, generated files, commit messages and pull-request descriptions, and repository secret scanning covers only one of the eight common escape paths well and a second partly.
- Deny rules and path exclusions are necessary and insufficient. They protect a path rather than a value, they require you to enumerate every path in advance, and they do nothing about a command whose output happens to contain the credential.
- The structural answer is that the agent never needs the secret — it needs the capability. Short-lived scoped credentials injected into a sandboxed runner, and secret managers that expose an operation rather than a value, remove the question rather than policing it.
- Explicit permission at the moment of access is a real control only while it stays rare enough to be read. A prompt that fires forty times a day is trained away within a week and becomes a log rather than a gate.
- After a suspected exposure, rotate first and investigate second — only rotation changes what an attacker can still do. A credential you cannot rotate inside an hour is a finding in its own right, whether or not anything leaked.
Why secrets are not just more source code
Most AI-tooling policies treat everything in the repository as one asset class, and that is the mistake underneath a lot of otherwise sensible governance. If a function definition leaks, the harm is real but diffuse and slow: an attacker still has to find a weakness, build something against it and reach a system that will accept it. If a credential leaks, there is no exploitation step. There is a login. The value is a working key to a live system, usable from anywhere, by anyone who reads it, for as long as it remains valid — which for a long-lived API key or a service-account token means indefinitely.
The second difference is reach, and it is the one specific to agents. Your repository has an access model: named people, named teams, an audit trail of who cloned it. A value read into an agent’s context does not stay inside that model. It travels with the context — into the transcript the tool retains, along the provider’s request path under whatever retention applies to your plan, into every tool call made after it entered, into any subagent that inherits the conversation, and into the artefacts the agent produces on the way out. None of those destinations has your repository’s access model. Several of them have no access model you control at all.
The third difference is that reproduction is the function, not a defect. A model that has read a value can produce it again later — in a summary of what it changed, in an example configuration, in a generated deployment manifest. It is not leaking. It is doing the thing you asked for with the material it was given. This is why “the agent will not repeat it” is not a control. It is a hope about a system whose job is to reuse what it has read.
None of this is a new weakness class. Hard-coded credentials have a catalogued identifier in CWE-798, and sensitive information written into logs has one in CWE-532. What has changed is the rate and the number of surfaces. The 2026 edition of the OWASP Top 10 for LLM Applications, published in August 2026, keeps Sensitive Information Disclosure at LLM02, moves Excessive Agency up to LLM03 from sixth place in the 2025 list, and broadens the old System Prompt Leakage entry into LLM08 Hidden Context Exposure — covering non-user-facing content assembled into the model’s context window. Those three entries describe this page’s problem almost exactly: material that should not have been in the context, in a system that can act.
So the governance question is not whether the agent is trustworthy. It is: what is the blast radius of a value that has entered a context I do not fully control, and what would shorten the interval between that happening and my knowing about it? For the wider frame around agent permissions, see agent identity and delegated authority and prompt injection once tools are connected.
How a secret actually escapes
None of these require an adversary, a jailbreak or a misbehaving model. Every one is an ordinary sequence of helpful steps. Read the last column first: it is the one that decides how long you spend unaware.
| Escape path | How it actually happens | What is left behind | Whether anything detects it |
|---|---|---|---|
| Read into context, then echoed back | The agent opens a configuration file to compare a value, or a command it ran returned one, and the value is now part of the conversation. It is then quoted in a summary, an explanation or a worked example — often helpfully, because quoting the value is how you show the mismatch. | The transcript held by the tool, whatever the provider retains on its request path, and any local session or history file the client writes to disk. | Almost none by default. Repository secret scanning never sees a transcript, and most teams have no scanner pointed at agent session storage at all. |
| Committed to a branch | The agent writes a working configuration file so a command succeeds, and the file is not covered by the ignore rules. The diff looks like plumbing and is approved quickly. | The commit object, every clone and fork that pulled it, the hosting provider’s caches, and any CI job that checked the branch out. | The best-covered path. Provider push protection and secret scanning catch a great deal here — but scope is a setting: default branch only, all branches, or pre-receive. Confirm which you have. |
| Written into a test fixture or seed script | A test needs a signature, a token or a webhook payload that verifies. The fastest way to make the test deterministic is to paste the real value in, and an agent optimising for a green test will do exactly that. | The fixture file, the CI logs of every run that printed it, and any test-report artefact retained by the pipeline. | Weak. Fixtures are exactly where scanners are most often excluded, on the reasoning that test data is fake. |
| Included in an error report or bug ticket | A human pastes part of the agent transcript into a ticket to explain what went wrong, or the runner posts a failure with the environment attached. The value travels with the context that made it legible. | The ticket, its revision history, the email notification sent to every watcher, and any search index built over the project tool. | Rare. Almost nobody scans the ticketing system, and ticket read access is usually far broader than repository read access. |
| Passed to another tool or subagent | The value is included in an argument to a tool call — a request body, a shell command, a payload handed to a connected server or a delegated subtask that inherits the context. | The tool-call log at both ends, the receiving service’s request log, and the context of every subagent spawned after the value entered. | Poor unless you log tool calls yourself and redact at the boundary. Third-party servers are outside your logging entirely. |
| Printed by a diagnostic command | The agent runs a perfectly reasonable command to understand the environment. Several of them print secrets as a matter of course: the environment dump, a container inspection, a verbose HTTP call, a namespace secret listing, a stack trace from a process holding the value in memory. | Command output in the transcript, the shell history file, and the terminal scrollback that later gets pasted somewhere. | None by default. A file deny rule does not apply, because no denied file was opened. |
| Baked into generated configuration or infrastructure code | The agent generates a deployment manifest, a variables file or a pipeline definition, and inlines the literal because a reference would have required knowing your secret-manager conventions. | The generated file, the state file if it was applied, and the plan output in the pipeline log. | Mixed. Infrastructure state files are a well-known secret sink and are frequently excluded from scanning because they are noisy. |
| Carried into a commit message or pull-request description | The agent writes the summary of what it changed, and the summary explains the change by naming the value it corrected. | The pull-request body, the notification email to reviewers, the release notes generated from commit messages, and any public mirror of the repository. | Partial. Some providers scan pull-request bodies and some do not, and a description edited after the fact leaves the original in the revision history. |
Count the detection column. Repository secret scanning — the control almost every team points at when asked how they would know — covers one path well and a second partially. The other six land outside the repository entirely: in a ticket, a transcript, a third-party request log, a shell history file, an infrastructure state file. That asymmetry is the reason the answer to this problem is not a better scanner. It is a smaller surface.
Deny rules are necessary and insufficient
Current coding-agent tooling generally exposes some form of path-level deny rule and per-tool permission prompt — Claude Code, Cursor and GitHub Copilot each provide mechanisms of this kind, though the syntax, the precedence between project and user settings, and what happens when rules conflict differ by product and change between releases. Confirm the exact behaviour in current vendor documentation for the version you have deployed, and record the date you checked, because this is precisely the sort of detail an assessor will ask you to evidence rather than assert.
Turn them on. A deny rule covering environment files, private keys, credential profiles and cloud configuration directories is cheap, immediate and catches the common case. It is the right first move and the wrong last one, for four reasons that are worth stating plainly rather than discovering later.
It protects a path, not a value. The credential you excluded from one file also exists in the pipeline variable, the cloud secret store, the deployment manifest, the container image layer and — very often — the shell history of the moment somebody exported it. Excluding one file is one door in a corridor.
It requires enumeration, and the list keeps growing. Environment files come in variants. Private keys have half a dozen conventional names. Package managers, container registries, cloud CLIs and Kubernetes clients each keep credentials in their own dotfile. Every new tool in the stack adds a path somebody has to remember to add. A control whose correctness depends on a human maintaining a list will drift, and the drift is silent.
It does not cover indirect reads. The rule stops the agent opening a file. It does not stop a command whose output happens to contain the value: an environment dump, a container inspection, a verbose HTTP request, a namespace secret listing, or a stack trace from a process that holds the credential in memory. No denied path was opened, so no rule applies. This is the gap that surprises people, and it is the reason execution boundaries matter more than read boundaries.
A rule the model is asked to respect is not the same as a rule the harness enforces. If the restriction lives in a prompt or a project instruction file, it is guidance, and guidance under pressure to complete a task is not a control. Prefer restrictions enforced outside the model — by the permission layer, the filesystem, the container, the network — and when you write your system description, describe what is enforced rather than what is requested.
The same reasoning applies to approval prompts, which are the other half of this tier and are genuinely valuable: they are the only control here that produces a decision record an assessor can test. But an approval is a control only while it is rare enough to be read. Fire it forty times a day and it is trained away inside a week, at which point you have a log rather than a gate — and, worse, a log that looks like consent. Design for few approvals, each legible, each carrying the reason and the scope. The same habituation problem in a different guise is covered in tool approval and capability change.
The agent needs the capability, not the credential
Almost every request that appears to require a secret actually requires an outcome: the test passes, the request succeeds, the deployment reconciles. The credential is how that outcome is currently achieved, not what is being asked for. Once you separate the two, the design changes shape — and this is the single highest-leverage move available, because it retires whole rows of the escape-path table rather than watching them.
Inject, do not store. The agent executes inside a runner whose environment is populated at start-up from a secret manager with a short-lived, narrowly scoped token. The repository holds references — names that resolve at run time — and no file in the workspace contains a value. The agent can run the command and read the result, but it never opens anything worth reading twice.
Sandbox the execution, not just the reads. A container or virtual machine that mounts the repository and nothing else — no host keychain, no cloud credential profile, no production kubeconfig — converts the indirect-read problem into a non-problem, because the diagnostic commands find an empty environment. Add a network egress allow-list and you have also bounded where anything the agent obtained could go. Separation of development, test and production environments is a long-standing control for exactly this reason, and ISO/IEC 27001:2022 carries it as Annex A control 8.31.
Expose the operation, not the key. Where a capability is needed repeatedly, put a broker in front of it: an internal service that holds the credential and offers the specific operation — send a test webhook, issue a sandbox charge, read this masked record. The agent calls the operation. The credential never crosses the boundary, and you get a call log for free, which is the artefact you will want when somebody asks what the agent actually did.
Prefer identities that expire over keys that do not. In pipelines, workload identity federation issues a short-lived token to the job rather than storing a long-lived key as a variable, which means an artefact that leaks is not a credential that works. Where long-lived keys are unavoidable, scope them to one service and one operation set, and put a rotation date on them. NIST SP 800-53 treats this as ordinary hygiene under IA-5 for authenticator management and SC-12 for key establishment and management. ISO/IEC 27001:2022 covers the same ground in Annex A controls 5.17 and 8.24.
A useful test when someone asks for broader access: if the justification is “so the command works”, the fix is almost always to change where the command runs, not to widen what the agent can read.
A control hierarchy for agent secrets access
This is a model we use in advisory work, borrowed from the hierarchy-of-controls idea in safety engineering. It is not a standard and no framework mandates it. Its value is the ordering: controls that remove the secret beat controls that supervise access to it, and each tier exists only because the tier above it could not be fully achieved.
| Tier | The control | What it removes | What it leaves open | Where it lands |
|---|---|---|---|---|
| Tier 0 — Eliminate | The secret does not exist in the workspace. The repository holds names and references. Values live only in a secret manager and are resolved by the process at start-up, never by a file the agent can open. | Every escape path that begins with reading a file, and most of the ones that begin with a diagnostic command, because the value is not present to be printed. | A running process still holds the value in memory, and anything that can execute inside that process can reach it. | CC6.1 (managing credentials, protecting keys) · ISO/IEC 27001:2022 A.5.17, A.8.24 |
| Tier 1 — Substitute | Where a credential must be present, it is a short-lived, narrowly scoped, non-production one: a sandbox-tenant token that expires in hours, bound to a single service and a single set of operations. | The consequence rather than the event. The value can still escape, but what it unlocks is bounded in time, in blast radius and in data sensitivity. | A window in which the token is live, and the temptation to reach for the production key the moment the sandbox does not reproduce the bug. | CC6.3 (least privilege) · NIST SP 800-53 IA-5, SC-12 |
| Tier 2 — Isolate | The agent executes inside a container or virtual machine with its own filesystem, its own credentials and a network egress allow-list — not on a developer laptop that already holds the keychain, the cloud profile and the production kubeconfig. | Lateral reach. A command that would have found credentials in a home directory finds an empty one, and traffic to an unexpected destination does not leave. | Whatever you deliberately put inside the sandbox, and the path back out through the artefacts the agent produces. | CC6.1, CC6.6 · ISO/IEC 27001:2022 A.8.31 (separation of environments) |
| Tier 3 — Intercept | Path deny rules, ignore rules, tool allow-lists and redaction applied at the boundary between the agent and anywhere content is written or transmitted. | The obvious and common cases, cheaply. This tier is worth having and is where most estates start. | Everything the rule did not enumerate, every indirect read, and every value the agent obtained without opening a denied path. | CC6.1 · OWASP Top 10 for LLM Applications 2026, LLM02 |
| Tier 4 — Permit explicitly | A human approves the specific access at the moment it is requested, with the reason and the scope shown, and the approval is recorded rather than merely clicked. | Silent access, and it creates the artefact an assessor can test. It is the only tier that produces a decision record. | Habituation. An approval that fires forty times a day is trained away inside a week, and a control nobody reads is a log, not a gate. | CC6.2, CC6.3 · CC5.2 (control activities through technology) |
| Tier 5 — Detect and respond | Secret scanning across the whole surface, provider push protection, alerting on credential use from unexpected origins, and a rotation path that can be executed in under an hour. | Nothing. It shortens the window between exposure and revocation, which is the only variable still available once a value has left. | The interval itself. In the worked example below the interval was nine days, and the nine days were the finding. | CC7.2, CC7.3, CC7.4 · ISO/IEC 27001:2022 A.8.15, A.8.16 |
Most estates we assess operate at tiers 3 to 5 and describe it as a policy. That is not nothing — it is where everyone starts — but it means the entire control set is reactive to a value that is still present and still reachable. Moving one workload up a tier does more than adding a fourth deny rule, and it is usually a week of engineering rather than a programme. If you do only one thing after reading this page, make it the sandbox: tier 2 is where the cost curve and the risk curve cross for most teams.
When the agent genuinely needs it
These are the seven requests that come up most often in practice, and the answer is no in every one of them. That is not obstruction — each row has a substitute that does the same work. Read the third column as the design, not the workaround.
| The request | Needs the value | What to do instead |
|---|---|---|
| “The integration test suite fails and I need you to fix it.” | No | Run the suite in a runner whose environment already carries a scoped test-tenant token. The agent sees the failure output, the request shape and the response — everything it needs to reason with — and never the credential that produced them. |
| “Debug this 401 from the payments API.” | No | What diagnoses a 401 is the request headers, the signature construction, the clock skew and the account the key belongs to. Capture the exchange with the credential redacted, or reproduce it in the sandbox. The literal value is the one part of the problem that is almost never the answer. |
| “Document the environment variables and write the example file.” | No | Variable names, types and whether each is required are not secrets. Give the agent the key list — the output of a command that prints names only — and it can write the example, the schema validation and the onboarding note without a value ever entering context. |
| “Rotate the signing key for me.” | No, and least of all here | Rotation is a privileged change with a blast radius. A human performs it in the provider console, or a pipeline with its own identity performs it. The useful agent contribution is the runbook, the inventory of every place the value is referenced, and the verification step that proves the old one is dead. |
| “Reproduce the bug that only happens with real customer data.” | No — and this is a data question first | A masked or synthetic replica with a read-only scoped credential. If the bug genuinely requires production data, the correct answer is a human working in a controlled session, not a broader grant to an agent. Separation of production from development is a control in its own right. |
| “The application will not start locally.” | Usually no | The diagnostic is which variables are unset or malformed, not what they contain. A start-up check that reports missing and present-but-empty keys by name answers the question completely, and is a better artefact than the agent reading the file anyway. |
| “Add a new secret to the deployment.” | No | The agent edits the manifest to reference a secret by name and opens the change for review. The value is written into the secret manager by a person or a pipeline identity that the agent does not hold. The reference is code. The value is not. |
There is one honest yes, and it is worth naming so the policy does not become a fiction people work around. A freshly issued, short-lived, non-production credential, scoped to a sandbox tenant holding no customer data, inside an isolated runner, is a value you would be willing to see published — and treating it as though it were a production key costs real velocity for no risk reduction. Grade your inventory so that judgement is made once, by name, rather than improvised under deadline. Everything not on that graded list is restricted by default.
Nine days between exposure and detection
An illustrative composite, not a client. A forty-person B2B SaaS company, mid-way through a SOC 2 Type 2 observation period running 1 January to 30 June 2026, Security and Confidentiality categories. One production cloud account, a payments provider, coding agents in daily use by the engineering team. Read the right-hand column first.
| Day 0 | 14 Apr 2026 | An engineer asks the coding agent to fix a failing webhook signature check against the payments provider. The agent opens the local environment file to compare the configured signing secret against the value in the test fixture. The live secret is now in the transcript. |
| Day 0 + 20m | 14 Apr 2026 | The agent makes the test deterministic by writing the real signing secret into the fixture. The diff is eleven lines and looks like plumbing. The engineer approves it without reading the fixture closely. |
| Day 1 | 15 Apr 2026 | The fixture is pushed to a feature branch. Secret scanning is enabled on the default branch only, so nothing fires. Nobody has ever checked which branches the scanner covers. |
| Day 3 | 17 Apr 2026 | To explain the failure, the engineer pastes a section of the agent transcript into a bug ticket. The ticket sits in a project tool where every employee and two contractors hold read access, and the paste includes the value. |
| Day 9 | 23 Apr 2026 | A scheduled scan over an export of the ticketing system flags a high-entropy string matching the provider’s key format. This is the detection — six days after the value left the repository boundary and nine after it left the file. |
| Day 9 + 35m | 23 Apr 2026 | Rotation. A new signing secret is issued, the old one revoked, the deployment updated, and an old signature replayed to confirm the previous value now fails. Only then does anyone open the provider’s audit log. |
| Days 9–12 | 23–26 Apr 2026 | Scoping: provider logs reviewed for 14–23 April for calls from unexpected origins. Branch history rewritten and the branch deleted. The ticket redacted and its revision history purged where the tool allowed. Transcript retention confirmed against the vendor agreement and the date of that check recorded. |
| Day 20 | 4 May 2026 | Design change: the agent moves into a container populated at start-up from the secret manager with a twelve-hour sandbox token. The repository environment file becomes references rather than values. Scanning is extended to all branches and to push. A redaction step is added to the transcript-to-ticket path. |
Notice what did not go wrong. The model did not misbehave. Nobody was negligent in a way that would show up in a performance review. The agent read a file it was permitted to read, wrote a fixture that made a test deterministic, and summarised its work accurately. A human then did the most natural thing available and pasted the explanation into a ticket. Four ordinary, defensible steps produced a live production credential sitting in a system with far broader read access than the repository it came from.
Notice, too, where the nine days came from. Two configuration facts nobody had checked: secret scanning covered the default branch only, and no scanner was pointed at the ticketing system at all. Neither is exotic. Both are the kind of scope setting that is chosen once at enablement and never revisited, and both would have been surfaced by a single question — which of our surfaces does this control actually cover?
At fieldwork the service auditor does not ask whether an exposure occurred. Exposures occur. What is tested is whether the described process did what the description says it does: was the event evaluated against the incident criteria, was the evaluation timely against your own stated window, was containment evidenced with times, and was the design change implemented and tested. The exception risk in this scenario is not the leak. It is the nine-day interval measured against a control description that promised detection of credential exposure — and a management response that explains the scope gap, names the fix and dates it will generally read better than one that emphasises that no misuse was found.
The control that failed here was never the agent’s permission model. It was the scope of the detection, and nobody had read it since the day it was switched on.
Rotate first, investigate second
The instinct after a suspected exposure is to establish what happened before doing anything irreversible. It is a good instinct in most incident types and the wrong one here. Investigation tells you what has already occurred, but only rotation changes what can still occur. While you are reading logs, the credential is live. The sequence below is short because it needs to be executable by whoever is on call at the time, not by the person who wrote it.
One: revoke or rotate. Issue the replacement, update the consumers, revoke the old value. If the system supports overlapping validity, use it — but set and keep a short overlap, because an overlap nobody closes is a rotation nobody completed. Two: verify the old value is dead. Attempt an operation with it and confirm the failure. An unverified rotation is a belief, and beliefs have a way of surviving into the management response. Three: scope it. What did the credential permit, over what window, and does the provider’s audit log show use you cannot attribute? Four: preserve before you clean. Capture the transcript, the diff, the ticket and the log extracts before rewriting branch history or purging revisions — remediation that destroys the record makes the next four questions unanswerable. Five: decide notification against your contracts and applicable law, on the facts, not on comfort.
Two mistakes recur often enough to name. The first is treating deletion as rotation: a force-push, a deleted branch or an edited ticket removes the visible artefact and does nothing whatsoever to the credential, which remains valid. Assume that anything which reached a hosted provider is retrievable, and let rotation — not deletion — be the thing you rely on. The second is waiting for certainty before rotating. Rotation is cheap and reversible in effect. A live credential in an unknown number of hands is neither.
Which produces a design requirement rather than a response one: a credential you cannot rotate inside an hour is a finding whether or not anything has leaked. If rotation requires a person who is asleep, a vendor ticket, a coordinated deployment and a change-advisory slot, then your effective exposure window is measured in days regardless of how quickly you detect. Rotation drills belong in the same category as restore tests: rehearsed, timed, and evidenced. Pre-agree who may rotate each class of credential out of hours, and write the runbook before you need it.
For how an event like this is handled when it lands inside an examination window — and why a well-documented incident is not automatically an exception — see a security incident during the observation period, and for the configuration change that follows, mid-period changes.
What the CPA firm actually requests
The request that surprises teams is not for a screenshot of the deny rules. It is the population question — and the honest answer is that the model transcript is not the population and cannot be made into one. The population comes from the systems that hold the secrets and the systems that run the agents.
| The request | What satisfies it | What gets rejected |
|---|---|---|
| Define the population of agents and the runners they execute in | A system-generated inventory: which coding-agent tools are in use, on which repositories, executing in which environments, under which identities, with the date each was approved. Reconciled to licence or seat assignments from the vendor and to the identity provider, with counts stated. | A hand-typed list of tools somebody remembered. A seat count that does not reconcile to the roster. Any inventory that omits agents running in CI, which is where the highest-privilege identities usually live. |
| Show the deny-rule and permission configuration held for the whole period | The configuration file or policy captured at two or more in-period dates, held in version control so the history is the evidence, plus the platform log showing it was not relaxed between those points and who could have relaxed it. | A screenshot of today’s settings offered as evidence about a period that closed months ago. A configuration stored only on individual laptops, where there is no way to establish what any given machine actually enforced. |
| Produce the secret inventory | Every credential in scope with an owner, the system it authenticates to, where the authoritative copy lives, its scope, its expiry or rotation cadence, and the date it was last rotated. Exported from the secret manager rather than maintained by hand. | An inventory that lists only the secrets in the secret manager while the pipeline variables, the third-party webhook signing keys and the two long-lived tokens in a founder’s password manager sit outside it. Completeness is the whole test. |
| Show that scanning covered the whole surface | Scanner configuration showing branch scope, push protection state and the exclusion list, with a stated justification for each exclusion — plus the finding history for the period, including findings closed as false positives. | Scanning enabled on the default branch only, presented as scanning enabled. An exclusion list containing the fixture directories, with nobody able to say when or why they were excluded. |
| Show the approval where a human granted an agent access to a secret | A record naming the requester, the approver as a different person, the specific secret or scope, the time-box, the business reason, and evidence the access ended when the time-box did. | A blanket approval covering all secrets for all time. An approval trail where requester and approver are the same account. A grant with no expiry and no revocation record. |
| Show that rotation was performed and the old value is dead | The provider’s key-management log showing the new credential issued and the old one revoked, with timestamps. The deployment change that took the new value. And a positive test proving the old credential now fails. | A ticket saying rotated with no system record behind it. A rewritten branch offered as remediation — deleting the artefact is not revoking the credential, and the two are frequently confused in management responses. |
| Show the exposure was evaluated as a security event | The event record with detection time, the evaluation of whether it rose to an incident, containment and remediation steps with times, the communication decision and its basis, and the design change that followed. | A remediation with no evaluation step in front of it. A record created after the period closed for an event that occurred inside it. Anything that documents the fix but not the decision. |
Two practical notes that decide how painful fieldwork is. The first is retention. Every row above leans on a log, and a log relied on as evidence has to retain for longer than the observation period plus the lag before anyone asks for it. Agent-tool audit logs, transcript storage and secret-manager access logs are frequently plan-tier settings with windows shorter than a six-month period. List every log you cite in a control description on day one of readiness, write its retention window beside it, and schedule an export wherever the window is short. This is the same discipline covered in what auditors actually accept as evidence.
The second is the failure mode we see most often, and it is self-inflicted. A policy states that AI tools must not access production secrets. Nothing enforces it, nothing evidences it, and no system could produce a population that would demonstrate it either way. Your own documents are the standard you are tested against, so a sentence like that creates the exception rather than preventing it. Write what is enforced. If the enforcement is a sandbox with no production identity inside it, say that — it is both stronger and testable.
Where this lands across the frameworks
There is no criterion called AI, and looking for one is the wrong search. A SOC 2 examination is performed under AT-C 205 by a licensed CPA firm, and it tests the controls you described against the trust services criteria you claimed. Agent secrets access lands squarely inside criteria that already exist. CC6.1 is the anchor: two of its points of focus speak directly to this, one on managing credentials for infrastructure and software, the other requiring processes to protect encryption keys during generation, storage, use and destruction. CC6.3 asks that access be authorised, modified and removed based on roles and responsibilities, giving consideration to least privilege and segregation of duties — which is where the scoping of an agent’s identity is argued. CC7.2 covers monitoring for anomalies indicative of malicious acts. CC7.3 and CC7.4 cover evaluating a security event and responding under a defined incident-response programme, which is the worked example above. And where the agent tooling is a vendor holding or processing your material, CC9.2 applies like any other third party.
On the ISO side, ISO/IEC 27001:2022 carries the same substance in Annex A: control 5.17 on the management of authentication information, 8.24 on the use of cryptography including key management, and 8.31 on separating development, test and production environments. ISO/IEC 42001:2023 is a different instrument — an AI management system standard, certifiable by an accredited certification body — and it governs how you decide, document and review AI use rather than prescribing a secrets control. In practice the two work together: the AI management system is where the decision to permit coding agents is recorded, scoped and reviewed, and the information security controls are where the boundary is actually enforced. That relationship is set out in integrating ISO 42001 with ISO 27001.
One boundary worth restating, because it comes up in every one of these engagements. TCSA advises, implements and coordinates: we help design the control, write the description, build the evidence routine and run the readiness assessment. SOC 2 reports are issued by licensed CPA firms. ISO 42001 and ISO 27001 certificates are issued by accredited certification bodies. Keeping those roles separate is not a formality — a firm that designs or operates your controls cannot then examine them.
The edge cases that generate the questions
The rule is easy. These eight are where it gets argued about, and where a policy written without them gets quietly ignored within a month.
The sandbox will not reproduce the bug
This is the honest hard case, and it is where good policies get quietly abandoned. A signature mismatch, a provider-side rate limiter or a data-shape difference can be genuinely invisible outside production. The workable answer is a controlled session rather than a broader standing grant: a human drives, the agent is given the redacted request and response rather than the credential, and if a credential must be present it is a freshly issued short-lived one revoked at the end of the session. What fails is the version where the exception becomes the working pattern and nobody records that it happened.
The .env file is not where your secrets are
Teams deny-list the file they can name, then leave the rest of the corridor open. The same class of value sits in cloud credential profiles in the home directory, private keys and known-hosts files, container registry configuration, package-manager credential files, machine-level network credentials, kubeconfigs, pipeline variables, and the shell history that recorded the moment somebody exported one. If the agent has a shell on a machine that holds any of these, the file exclusion is decorative. This is the single strongest argument for the sandbox: it is easier to control what is inside a clean environment than to enumerate what is inside a developer laptop.
The development credential is a production credential
In a surprising number of estates the local environment file points at production, because that is what worked on day one and nobody revisited it. Before you can reason about what an agent may read, you have to know what each value actually unlocks. Grade the inventory: which credentials touch customer data, which touch a sandbox tenant, which touch nothing that matters. Separation of development, test and production environments is where this control properly sits, and it is a prerequisite rather than a refinement.
The agent runs on the developer’s own machine
Most coding agents run locally by design, which means the agent inherits everything the human has. You are then relying on tiers 3 to 5 for a workload that would be far better served by tier 2. There is a reasonable middle: run the agent in a devcontainer or a virtual machine that mounts only the repository, holds only sandbox credentials and has no access to the host keychain. It costs some convenience. It converts the entire question from a policy problem into a boundary problem, which is the only version of it that is testable.
A credential arrives through a connected tool rather than a file
An agent with connected tooling — a database client, a cloud console integration, a server exposed over the Model Context Protocol — can receive credentials in a response body without ever reading a denied path. Treat the tool surface as part of the secret surface: enumerate what each connected tool can return, restrict the identity it runs under, and log its calls on your side of the boundary. This is closer to a vendor-management problem than a file-permissions one.
The agent proposes a fix that hard-codes the value, and a human approves it
Reviewer fatigue is the failure mode, not agent behaviour. Volume goes up, diffs get larger, and the reviewer skims a fixture file that looks like plumbing. Two controls carry most of the weight here: pre-receive or push-time secret detection, so approval is not the last line, and a diff-size or generated-code convention that makes machine-authored changes legible as such. Hard-coded credentials are an old weakness with a catalogued identifier, CWE-798, and the agent has not created a new category — it has raised the rate.
You cannot see what the model provider retains
Once a value has entered a request to a third party, your incident timeline depends partly on somebody else’s retention behaviour, and that is a contractual question rather than a technical one. Before deployment, confirm in current vendor documentation and in your agreement what is retained, for how long, under which plan tier, whether inputs may be used for training, where the data is processed, and what deletion you can actually request. Consumer and enterprise tiers generally differ materially on exactly these points. Record the answers with the date you obtained them, because these terms change and an assessor will ask what you relied on.
The secret was exposed but nothing was used
A provider audit log showing no unexpected use is genuinely reassuring, and it is not the same as proof. Log coverage may not extend to every operation the credential permitted, attribution by source address is weak, and absence of evidence over a nine-day window is a weaker claim than it feels. Rotate anyway, say plainly in the record what the log did and did not cover, and resist the pull towards a management response that reads as certainty. Assessors and enterprise buyers both read overstatement as a control weakness of its own.
What buyers push back on and the answer
These seven now appear in enterprise security questionnaires and vendor reviews with some regularity. The difference between a good answer and a defensive one is whether it describes architecture or asserts intent.
“Your engineers use AI coding agents. How do we know our keys are not sitting in a model provider’s logs?”
The defensible answer is structural rather than reassuring. Describe where agents execute, what credentials exist inside that boundary, what the values reach, and what enforces the boundary — then describe the detection and rotation path for the case where all of that fails. If your production credentials are never present in an agent-accessible environment, that is a statement about your architecture that survives scrutiny. A promise about model behaviour is not, because it is unfalsifiable in exactly the direction the buyer cares about.
“Do you send our source code to a third party?”
Usually yes in some form, and the honest answer is more persuasive than a hedge. Name the tools, the plan tier, the processing location, the retention position and the contractual terms as documented at the time you last verified them, and say when that was. Then draw the distinction the buyer is really reaching for: source code disclosure is a confidentiality matter with a slow blast radius, whereas credential disclosure is an access-control failure that is live immediately. The controls you describe for the second should be visibly stronger than for the first.
“You cannot prove an agent never read a secret.”
Correct, and the useful reply is to move the claim to ground you can evidence. You cannot prove a negative about a model’s context. You can show that production credentials were not present in the environment the agent executed in, that the identity available to the runner was scoped to a sandbox tenant, that egress was restricted, and that scanning and rotation exist for the residual case. Design evidence beats behavioural assurance, and an assessor will treat it the same way.
“We require AI tools to be disabled on any project touching our data.”
That is a procurement policy, not a control requirement from any framework, and it is worth naming the difference politely before deciding whether to fight it. Ask which risk the clause is aimed at: retention, training use, or credential exposure. Each has a specific answer, and buyers frequently accept a scoped commitment — no production credentials in agent environments, enterprise tier with the retention terms in writing, named repositories excluded — where a blanket ban was the opening position. Find out early whether it is a hard gate or a scoring factor.
“What is your rotation SLA if a key is exposed?”
Answer with a number you can hold every time, not the best case. State the target measured from detection rather than from exposure, name who is authorised to rotate each class of credential including out of hours, and confirm that you rehearse it. A team that says two hours and can evidence two hours reads far better than a team that says immediately. If you cannot answer the question at all, that is the finding — and it exists whether or not an agent is involved.
“Is any of this actually covered by your SOC 2?”
It is, but not as a line item called AI. A SOC 2 examination under AT-C 205 tests the controls you described against the criteria you claimed. Credential management and key protection sit under CC6.1, least-privilege access decisions under CC6.3, monitoring under CC7.2, and evaluating and responding to a security event under CC7.3 and CC7.4. Where agent tooling is a vendor holding or processing your material, CC9.2 applies. If your description says agents may not reach production secrets, that sentence becomes testable — which is a reason to write it carefully rather than aspirationally.
“Shouldn’t you just ban agents from running shell commands?”
It removes a real class of exposure and a great deal of the value at the same time, and in practice it tends to be reversed within a quarter rather than held. The more durable trade is to keep execution and bound it: a sandboxed runner, an egress allow-list, no production identity inside the boundary, and command logging on your side. Bans that are quietly abandoned are worse than bounded permissions that are enforced, because the first leaves you with no record of what actually happened.
For how to structure the whole answer when a questionnaire arrives, see SOC 2 and security questionnaires, and for the governance layer above the individual tool decision, shadow AI governance.
Frequently Asked Questions
Should a coding agent be allowed to read .env files?
Is a deny rule on .env enough on its own?
What is the difference between an agent reading a secret and a developer reading it?
If a secret ended up in an agent transcript, is that a reportable incident?
What should we do first if we think a key was exposed to an agent?
Does SOC 2 say anything about AI coding agents?
How do we give an agent access to a system without giving it the credential?
Do we have to ban coding agents to pass a security review?
Are enterprise plans of coding-agent tools safer than consumer ones?
What evidence should we keep so this is testable later?
Related Reading
Governing Coding Agents
Claude Code, Cursor and Copilot assessed by capability graph rather than product label.
Read moreReviewing AI-Generated Code
Same security outcome, different failure modes — and the review gate that has to stay meaningful at volume.
Read moreShould a Coding Agent Deploy to Production?
Separating code-generation rights from deployment authority, even when one human holds both.
Read moreThe Ten Questions That Govern Any AI Agent
Scope, ownership, data, capability, identity, oversight, failure detection, evidence, reassessment and how to stop it.
Read moreISO 42001 Knowledge Hub
AIMS controls, EU AI Act mapping, risk assessment and guides.
Read moreISO 42001 (AI Management)
The world's first AI management system standard, for AI builders.
Read more