
AI agents keep gaining new capabilities. They read files, run shell commands, access Git repositories, talk to databases, call APIs, or use tools connected through MCP.
That is exactly where a significant security risk lies.
A classic program might receive one API key and use it for a single, tightly defined purpose. An autonomously operating AI agent, on the other hand, may simultaneously have access to the file system, the shell, network services, and other tools.
If a file like this happens to be lying around:
OPENAI_API_KEY=sk-xxxxxxxx
GITHUB_TOKEN=github_pat_xxxxxxxx
DATABASE_PASSWORD=SuperSecret123
AWS_SECRET_ACCESS_KEY=xxxxxxxx
a small configuration mistake can suddenly turn into a serious security incident.
That's why the most important rule is:
An AI agent should never be able to see or use more secrets than it actually needs for its current task.
That applies to ChatGPT- or Claude-based agents just as much as to coding agents, custom-built agent systems, MCP servers, CI/CD agents, and local AI tools.
For secrets, OWASP recommends centralized management, least privilege, automated rotation, short lifetimes, and avoiding unnecessary human access to the actual credentials.
Why secrets are especially critical for AI agents
API keys are nothing new in principle. But AI agents change the threat model.
An agent may be able to:
- search files
- open configuration files
- run terminal commands
- analyze logs
- search Git history
- send HTTP requests
- query databases
- start MCP tools
- modify cloud resources
That means an agent may already possess exactly the capabilities an attacker would need to immediately use a discovered secret.
On top of that comes the context of an AI system. If a secret accidentally becomes part of a prompt, a tool result, or a debug log, there is a risk that it gets processed further or stored somewhere.
OWASP now explicitly lists "Token Mismanagement and Secret Exposure" as a risk for MCP-based systems. It specifically warns against placing tokens in configuration files, prompt templates, or persistent model context, and instead recommends short-lived, scoped tokens along with a clear separation of context and permissions.
Things get especially risky when AI tools are used without any official approval inside a company. Without a central overview and policy, credentials quickly end up in unapproved tools and environments where nobody is checking their security – see Preventing Shadow AI: Technical and Organizational Measures (Read article) for more on that.
Three layers of secure secret management
For AI agents, secrets should be considered on three layers:
- Storage: Where does the secret live?
- Delivery: How does the agent obtain the secret?
- Permission: What is it allowed to do with it?
Many setups only take care of the first point.
That is not enough.
A perfectly encrypted API key doesn't help much if the resulting token then carries administrator rights across the entire infrastructure.
Option 1: .env – practical, but not a secret vault
One of the most common approaches in development projects is a .env file.
Example:
OPENAI_API_KEY=your-api-key
DATABASE_HOST=db01.internal
DATABASE_USER=agent
DATABASE_PASSWORD=your-password
The application reads these values at startup.
For local development environments, this approach is simple and convenient.
It does, however, have limits.
Always exclude .env from Git
A .env file containing real credentials should never end up in a Git repository.
A suitable .gitignore entry might look like this:
.env
.env.*
!.env.example
A .env.example file, by contrast, contains only the required variable names:
OPENAI_API_KEY=
DATABASE_HOST=
DATABASE_USER=
DATABASE_PASSWORD=
That tells a developer which settings are needed, without exposing any real credentials.
GitHub additionally offers Secret Scanning and Push Protection. Push Protection can block detected API keys and other credentials right at push time, before they ever land in the repository. GitHub also scans the Git history for known secret patterns.
That is particularly useful for projects that involve coding agents. An agent can just as easily commit a configuration file by accident as a human can.
Don't forget file permissions
On Linux systems, a local secret file should be readable only by the user that actually needs it.
Example:
chmod 600 .env
Then:
ls -l .env
Expected result:
-rw------- 1 agent agent 512 Aug 31 10:00 .env
It's even better to run the actual agent process under its own dedicated service account.
For example:
agent-research
agent-github
agent-monitoring
agent-deployment
instead of:
root
or a shared administrator account.
Why .env is often not enough for production
A .env file mainly solves an organizational problem: secrets no longer have to sit directly in the source code.
That does not automatically turn it into a secure secrets management system, though.
Environment variables can be exposed through debug output, diagnostic data, dumps, or misconfigured logs. OWASP therefore recommends using environment variables for secrets only when more suitable mechanisms are not available.
A good rule of thumb, then, looks like this:
| Environment | Recommendation |
|---|---|
| Local development | .env acceptable |
| Test system | Prefer a secret store |
| CI/CD | CI secret store |
| Docker production | Docker Secrets / secret store |
| Kubernetes | Secret manager / external secret solution |
| Critical production | Vault or a comparable solution |
| AI agent with infrastructure access | Vault + least privilege |
.env is not inherently bad. It just shouldn't be confused with a real vault.
Matching product · German-language edition
AI Assisted Coding - Vibe Coding Projektstart
Build a vibe-coding project the professional way from day one: secure credentials, agent permissions, MCP, and a solid project structure instead of unstructured experimenting. This German-language guide pairs well with the article above.
Option 2: HashiCorp Vault and centralized secret stores
Once multiple servers, services, or agents are involved, a centralized secret store becomes interesting.
A well-known example is HashiCorp Vault.
Instead of storing a database key permanently inside the project, the application authenticates against Vault and receives only the secret it needs.
The basic principle looks like this:
AI agent
│
│ authenticates
▼
Vault
│
│ checks policy
▼
approved secret
│
▼
API / database / service
Vault uses policies to define which paths an application may read or modify. Access that isn't explicitly granted is denied by default. HashiCorp explicitly recommends keeping policies simple and as narrowly scoped as possible, following the least-privilege principle.
Example: an agent may read exactly one secret
Suppose a monitoring agent only needs access to:
secret/data/agents/monitoring
Its Vault policy should not look like this:
path "secret/*" {
capabilities = ["read"]
}
That would let the agent read every secret stored there.
A much better version:
path "secret/data/agents/monitoring" {
capabilities = ["read"]
}
Now the agent can read exactly the path it needs. Nothing more.
This principle should run through the entire agent architecture.
Even better: dynamic secrets
One particularly interesting Vault concept is dynamic secrets.
Instead of permanently storing something like this for a database:
username=agent
password=SomePasswordThatStaysTheSameForYears
Vault can generate temporary credentials on demand. For example:
username=v-agent-f8a731
password=RandomGeneratedPassword
valid for=60 minutes
Once the defined period expires, these credentials lose their validity.
Vault uses leases and time-to-live values for this. Dynamically generated credentials can be automatically revoked once they expire. For databases, Vault can even create separate users for individual services or instances, making it easier to attribute access to the right agent.
That is extremely useful for AI agents. An agent no longer needs database access that stays valid for five years.
It might only need:
DB account
Valid for: 30 minutes
Rights: SELECT
Database: reporting
and that's exactly what it gets.
The most important security principle: least privilege
Where an API key is safely stored is only half the solution.
At least as important is what that key is allowed to do. For a deeper look at how to scope such permissions for AI agents in general, see What Permissions Should an AI Agent Get? Security Rules for Agents (Read article).
An AI agent that is supposed to analyze GitHub issues doesn't automatically need:
Delete repository
Delete branches
Modify secrets
Configure Actions
Manage users
It may only need:
Issues: Read
Repository Content: Read
Metadata: Read
The same applies to databases.
A reporting agent often needs:
SELECT
but not:
DROP
ALTER
DELETE
CREATE USER
GRANT
And a monitoring agent may need access to:
GET /api/status
GET /api/metrics
but not:
POST /api/shutdown
DELETE /api/server
OWASP explicitly recommends fine-grained access control and least privilege for secrets. Individuals or applications should not get blanket access to every secret in a centralized secret store.
One agent, one identity
A dangerous setup looks like this:
MASTER_API_TOKEN=xxxxxxxx
and then ten different agents all use the same token.
That's convenient. But it's a security problem.
Better:
agent-readonly-github
agent-monitoring
agent-backup-check
agent-deployment
agent-ticket-system
Each agent gets:
- its own identity,
- its own credentials,
- its own permissions,
- its own logs,
- its own token lifetime.
If agent-monitoring gets compromised, the deployment agent doesn't automatically have to be affected too.
It's also much easier to trace which agent actually performed a given action.
Especially dangerous: agents with root or administrator rights
A common mistake with coding agents is simply starting the agent with the rights of the logged-in administrator.
For example:
sudo agent
after which the agent is allowed to:
read /etc
stop services
install packages
read SSH keys
modify network configuration
administer Docker
delete files
That's convenient. But it contradicts the least-privilege principle.
An agent should only get the tools and operating system rights it actually needs for its specific task.
That could look like this, for example:
Agent
├── project directory: Read/Write
├── /etc/nginx/: Read
├── systemctl status nginx: allowed
├── journalctl nginx: allowed
├── systemctl restart nginx: only after approval
└── /root: no access
This separation is essential, especially on production systems.
Handle secrets in MCP servers with particular care
MCP – the Model Context Protocol – lets AI systems use external tools and data sources.
An MCP server might have access to:
GitHub
PostgreSQL
MySQL
Jira
Slack
File systems
Kubernetes
Monitoring
Internal REST APIs
That turns the MCP server into a particularly critical security component. For a complete picture of how to run an MCP server securely, see How to Operate MCP Servers Securely: Permissions, Tools, and Risks Explained (Read article).
API keys should therefore never be written directly into a shared agent or MCP configuration.
In the context of MCP, OWASP recommends, among other things:
- storing secrets in vault systems,
- providing tokens only at runtime,
- using short-lived tokens,
- binding tokens to specific agents, tools, or sessions,
- removing secrets from logs,
- rotating or invalidating credentials immediately in case of suspicion.
An MCP agent for GitHub, for example, shouldn't know an AWS key. And a database agent doesn't need access to the deployment token.
Keep agents away from the secret itself
One interesting architecture is to never show the language model the actual secret at all.
Instead of:
Agent receives API key
↓
Agent builds an HTTP request
better:
Agent
↓
approved tool
↓
Credential proxy / MCP server
↓
Secret store
↓
API
The agent simply says, for example:
create_github_issue(
repository="company/project",
title="Bug in version 2.1"
)
The tool itself authenticates against GitHub. The language model never has to know the GitHub token.
This pattern reduces the number of components the secret ever passes through. For a walkthrough of building your own MCP server as exactly this kind of controlled middle layer, see Build Your Own MCP Server: Architecture and an Example (Read article).
Docker: don't bake secrets into Dockerfiles
A particularly problematic example would be:
ENV OPENAI_API_KEY=sk-xxxxxxxx
or:
ARG API_KEY=xxxxxxxx
Docker explicitly warns against embedding sensitive data via ARG or ENV in images, since this information can remain in the resulting image or its metadata. For builds, Docker recommends secret mounts instead.
Docker Compose also offers secrets support.
A service then only receives the secrets explicitly granted to it. Docker recommends this approach over passing sensitive data as regular environment variables.
The principle is, once again, the same: only make the secret visible where it's actually needed.
.agentsignore is not a real security boundary either
Another important point for coding agents: files like .env can partly be excluded from the normal agent context through ignore files.
That's useful. But it doesn't replace operating system permissions or a sandbox.
Docker, for example, notes for its own agents that an ignore rule can prevent a secret file from being read through certain filesystem tools. But if the agent also has shell access, it could theoretically still run something like:
cat .env
An ignore file is therefore a safeguard against unintentional access – not a hard security boundary. Critical secrets need real permission boundaries such as sandboxing, approvals, and a well-thought-out backup strategy, the way this has proven to work well for coding agents like Codex – see How to Use OpenAI Codex Safely: Git, Sandbox, Backups, and Approvals (Read article).
Secrets never belong in prompts
You should also avoid prompts like:
Connect to the API.
API key:
sk-xxxxxxxxxxxxxxxx
Then analyze ...
Better:
Use the approved monitoring_api tool and analyze
the current system messages.
Authentication happens inside the tool. The agent needs neither the API key nor its value.
The same applies to:
- system prompts
- AGENTS.md
- CLAUDE.md
- README files
- MCP configurations
- knowledge bases
- agent memory
- tickets
- chat history
Since AGENTS.md and CLAUDE.md have become the central instruction files for coding agents in so many projects today, it's worth taking a deliberate look at what does and doesn't belong in them – see AGENTS.md vs. CLAUDE.md: Which File Does Your Project Need? (Read article).
A secret should never become part of an AI agent's normal knowledge context.
Logs are an underestimated risk
Debug code like this can have serious consequences:
print(os.environ)
or:
DEBUG configuration:
OPENAI_API_KEY=sk-xxxxxxxx
DATABASE_PASSWORD=xxxxxxxx
Suddenly, the secret may end up in:
- journalctl
- Docker logs
- Kubernetes logs
- Elasticsearch
- Loki
- Splunk
- SIEM systems
- CI/CD logs
- debug reports
OWASP explicitly recommends never logging secrets in plaintext, and using masking or redaction instead.
Instead of:
API_KEY=sk-proj-abc123xyz456
only this should appear, for example:
API_KEY=sk-proj-************
or, even better:
API credentials loaded successfully.
What to do if an API key ends up in Git anyway
In that case: don't just delete the file.
The key can still exist in the Git history.
The first and most important step is: revoke or rotate the secret.
After that, you should check:
- Where was the key published?
- How long has it been there?
- What permissions does the key have?
- Has it already been used?
- Are there suspicious API calls?
- Does it also show up in logs?
- Does it show up in forks or backups?
- Has it become part of an agent's context?
For secrets that were genuinely exposed, GitHub also recommends revoking and, where appropriate, rotating them first.
Only afterward should you deal with cleaning up the repository history.
Plan for API key rotation
A secret shouldn't only be replaceable once a security incident has already happened.
Rotation belongs in the architecture from the start.
A good process allows for:
old key active
↓
generate new key
↓
switch applications over
↓
verify functionality
↓
deactivate old key
With dynamic secrets, this process can largely be automated.
OWASP recommends automatic rotation wherever it makes sense. HashiCorp Vault can also assign dynamic credentials a defined TTL and revoke them once it expires.
A sensible permission model for AI agents
For production agents, you might use a classification like this:
| Agent class | Typical permissions |
|---|---|
| Analysis agent | read-only |
| Monitoring agent | read metrics and logs |
| Support agent | read and write tickets |
| Coding agent | edit project directory |
| Deployment agent | trigger defined deployments |
| Admin agent | a particularly restricted special role |
What's interesting here: the admin agent should not be the default.
Quite the opposite. The more powerful the agent, the stronger the additional controls should be. These can include:
- human approval
- a restricted tool selection
- command allowlisting
- network restrictions
- short-lived credentials
- session isolation
- audit logging
- sandboxing
- separate service accounts
A permission model like this only works in practice if it is documented in a binding way. A company-wide AI policy is exactly the right place for that – see AI Policy for Companies: What Employees Can and Cannot Do (Read article).
Three security tiers for practical use
Tier 1: small local development environment
Suitable for personal development projects.
- .env
- .gitignore
- chmod 600
- a separate development key
- restricted API permissions
- secret scanning
Important: never use production credentials.
Tier 2: servers and company applications
Suitable for production services and internal agents.
- centralized secret store
- separate service accounts
- least privilege
- CI/CD secret store
- rotation
- audit logs
- separate test/production credentials
At this point, .env should no longer serve as the central secret database.
Tier 3: critical AI agents
Suitable for agents with access to infrastructure, databases, Git, the cloud, or production systems.
- Vault / secret manager
- short-lived credentials
- a distinct identity per agent
- a policy per tool
- no secrets in the model context
- human approval for critical actions
- sandboxing
- centralized audit logs
- automatic rotation
That's a lot more effort. But these are also exactly the systems with the greatest potential for damage.
Matching product · German-language edition
MCP Server Praxisleitfaden 2026
The Model Context Protocol explained clearly: architecture, security, least privilege, OAuth/OIDC, and GDPR considerations for running your own MCP servers. German-language guide.
An example of a secure agent architecture
A robust architecture might look like this, for example:
┌─────────────────┐
│ AI model │
└────────┬────────┘
│
no credentials
│
┌────────▼────────┐
│ Agent runtime │
└────────┬────────┘
│
defined tools
│
┌───────────────┴───────────────┐
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ GitHub tool │ │ DB tool │
└──────┬──────┘ └──────┬──────┘
│ │
own token own account
│ │
└──────────────┬────────────────┘
│
┌──────▼──────┐
│ Vault / IAM │
└─────────────┘
The crucial difference from an insecure setup: the model itself is never handed a large bundle of API keys.
Instead, individual tools each carry precisely defined identities and permissions.
A practical security checklist
Before deploying an AI agent in production, at least the following questions should be answered:
- Are API keys present in the source code?
- Are secrets stored in .env files inside the repository?
- Is .env listed in .gitignore?
- Is there a .env.example without any real credentials?
- Are production secrets stored centrally?
- Does every agent have its own identity?
- Are test and production credentials kept separate?
- Are permissions assigned according to least privilege?
- Can tokens be time-limited?
- Is there a documented rotation process?
- Are secrets stripped out of logs?
- Does the agent have access to files it doesn't actually need?
- Can the agent run shell commands without restriction?
- Does it genuinely need write access?
- Are dangerous actions protected by human approval?
- Are secrets stored in the agent's context or memory?
- Can individual tokens be revoked immediately?
- Is there audit logging in place?
- Are repositories automatically scanned for secrets?
If several of these questions get answered with "no," the agent architecture should be reviewed again before it goes into production.
Conclusion: the best API key is the one the agent never sees
AI agents need access to tools and systems.
But that doesn't automatically mean the language model itself has to know every credential involved.
For local development, a properly protected .env file can be entirely sufficient.
But once production systems, multiple agents, or critical permissions come into play, it's time to think about professional secrets management.
The most important rules are: no secrets in code. No secrets in prompts. No universal admin tokens. Keep lifetimes as short as possible. One identity per agent. And always only the minimum permissions required.
Vault and other secret managers don't just solve the problem of secure storage. They enable centralized access control, rotation, auditing, and, in some cases, dynamically generated credentials.
That's especially critical for autonomous AI agents.
Because the question shouldn't be: "Where do I hide my API key from the agent?"
It should be: "Why should this agent need to see the API key at all?"
Anyone who builds their architecture around that principle significantly reduces the risk of compromised credentials – and can deploy AI agents in a far more controlled way across production IT environments.
FAQ: API keys and AI agents
Is a .env file safe?
For local development environments, a .env file can be a reasonable solution as long as it is not checked into Git and has restrictive file permissions. For critical production environments, a dedicated secrets management system should be preferred instead.
Should an AI agent have direct access to API keys?
If possible, no. A better architecture lets an approved tool or an MCP server handle authentication, while the agent only calls the permitted function.
What is better: .env or HashiCorp Vault?
.env is simple and works well for local development. Vault additionally offers centralized access control, policies, auditability, rotation, and dynamic credentials, which makes it far better suited to complex or production infrastructure.
What does least privilege mean for AI agents?
An agent receives only the permissions it actually needs for its specific task. An analysis agent, for example, typically does not need delete permissions, and a monitoring agent does not need administrative database rights.
What should I do if an API key ends up in Git?
The key should be revoked or rotated immediately. After that, repository history, logs, agent contexts, and audit data should be checked for possible use or further copies of the secret.
Are environment variables safe for secrets?
They are better than credentials hard-coded into source code, but they are not a full secret store. Environment variables can be exposed under certain circumstances, for example through debugging, logs, or diagnostic data. OWASP therefore recommends more suitable secret management approaches for sensitive production environments.
Sources and technical background
The technical security recommendations in this article draw on current documentation and guidance from OWASP, HashiCorp Vault, GitHub Secret Scanning, and Docker. OWASP recommends least privilege, centralized secrets management, rotation, and avoiding secrets in logs, among other things. HashiCorp documents policies, TTL-based leases, and dynamic credentials; GitHub offers Secret Scanning and Push Protection; and Docker recommends dedicated secret mechanisms over ARG or ENV values baked permanently into images for sensitive data.
Technical review date: September 17, 2026.
Related topics and sources
What Permissions Should an AI Agent Get? Security Rules for Agents (Read article)
How to Operate MCP Servers Securely: Permissions, Tools, and Risks Explained (Read article)
Build Your Own MCP Server: Architecture and an Example (Read article)
How to Use OpenAI Codex Safely: Git, Sandbox, Backups, and Approvals (Read article)
Preventing Shadow AI: Technical and Organizational Measures (Read article)
AI Policy for Companies: What Employees Can and Cannot Do (Read article)
AGENTS.md vs. CLAUDE.md: Which File Does Your Project Need? (Read article)