Dark tech illustration: a central server with a large padlock is connected via glowing circuit lines to several smaller lock icons, symbolizing centrally managed secrets and controlled access for AI agents

KI-Buster Blog · IT Security

Protecting Secrets and API Keys in AI Agents: Using .env, Vault, and Permissions the Right Way

AI agents read files, call APIs, and connect to external systems through MCP – which means they can easily end up with access to more secrets than they actually need. Here is when a .env file is enough, when Vault pays off, and how least privilege, rotation, and per-agent identities keep API keys genuinely protected.

Published and reviewed on September 17, 2026

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:

  1. Storage: Where does the secret live?
  2. Delivery: How does the agent obtain the secret?
  3. 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:

EnvironmentRecommendation
Local development.env acceptable
Test systemPrefer a secret store
CI/CDCI secret store
Docker productionDocker Secrets / secret store
KubernetesSecret manager / external secret solution
Critical productionVault or a comparable solution
AI agent with infrastructure accessVault + least privilege

.env is not inherently bad. It just shouldn't be confused with a real vault.

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 classTypical permissions
Analysis agentread-only
Monitoring agentread metrics and logs
Support agentread and write tickets
Coding agentedit project directory
Deployment agenttrigger defined deployments
Admin agenta 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.

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)