Facio's Secret Hygiene: Why AI Agents Never See Raw Credentials and Never Should
An AI agent that sees raw credentials is a security incident waiting to happen. The agent reads the database password from a config file. The agent writes the API token to a log file. The agent echoes the SSH key into a chat reply. The agent's context window becomes the leak vector — the model is trained on user input, the credentials are user input, the credentials leak.
Production AI agents never see raw credentials. The agent knows that a credential exists for a system; the agent knows what the credential authorizes; the agent does not know the credential's value. The agent's operations are authenticated through the runtime, the secrets are stored in the runtime's vault, and the agent's interaction is "use this credential" — not "read this secret, then use it."
Facio's secret hygiene is the structural discipline that keeps credentials out of the agent's context, out of the agent's outputs, and out of the agent's reasoning. The discipline is built into the runtime; the agent doesn't have to remember to apply it. Here's how the discipline works and why every production agent needs it.
The Credential Exposure Reality
Traditional automation scripts handle credentials through environment variables, config files, or hardcoded values. The script reads the credential; the credential is in the script's memory; the script uses the credential.
AI agents introduce a new exposure surface: the context window. The context window is everything the model sees when reasoning. If a credential is in the context, it's effectively in the model's "mind" for the duration of the session. If the model echoes the credential in an output, the credential has leaked. If the model's training data includes the credential somehow, the credential is in the weights.
The exposure surfaces are numerous:
- Config files. The agent reads
/etc/myapp/config.yaml. The password is in the file. The agent now has the password in context. - Environment dumps. The agent runs
envfor debugging. The DATABASE_URL is in the output. The agent now has the credential in context. - Tool outputs. The agent calls a tool that returns the auth token. The token is in the response. The agent now has the token in context.
- Log messages. The agent logs a successful API call. The log includes the bearer token. The agent now has the token in logs that may be persisted, indexed, and reviewed.
- Error messages. The agent gets a 401 with "Authentication failed: token=abc123". The token is in the error message. The agent now has the token in context.
- Reasoning traces. The agent's reasoning says "I'll use the database password XYZ to connect." The password is in the reasoning. The reasoning is in the context, in the audit log, and potentially in the output.
Each surface is a potential leak. The naive agent that doesn't manage credentials actively will leak them.
The Discipline: Three Principles
Facio's secret hygiene is built on three principles that together eliminate credential exposure.
Principle 1: Secrets Never Enter the Context
The credential's value is never in the agent's context window. The agent sees the credential's identifier; the agent does not see the credential's value.
# Naive: Agent sees the value
DATABASE_URL=postgres://user:password123@host:5432/db
# Result: "password123" is in context
# Disciplined: Agent sees only the identifier
DATABASE_URL_SECRET_REF=database-production-credentials
# Result: The reference is in context, the value is not
The runtime stores the credentials in a vault. The agent references credentials by identifier. The runtime resolves the identifier to a value at the moment of use. The agent's context only contains references, never values.
The discipline applies to every tool and every interaction. When the agent runs a shell command, the runtime injects the credentials at execution time. When the agent makes an API call, the runtime adds the auth header at request time. When the agent reads a file with credentials, the runtime redacts the values before showing the file to the agent.
Principle 2: Tool Outputs Are Scanned and Redacted
Every tool output is scanned for credential patterns. Matches are redacted before the output reaches the agent's context:
# Tool output (raw)
cat /var/log/app.log | tail -50
# Output includes: "INFO: Connected to database with password=P@ssw0rd!abc"
# After runtime scanning
cat /var/log/app.log | tail -50
# Output: "INFO: Connected to database with password=[REDACTED]"
The scanning patterns include:
- API keys. Patterns matching common API key formats (AWS keys, OpenAI keys, GitHub tokens, etc.)
- Passwords. Strings after "password=", "passwd=", "secret=", "token=" in config files.
- Private keys. Multi-line PEM blocks for SSH, SSL, PGP.
- Bearer tokens. JWT-like strings and Bearer headers.
- Connection strings. URLs containing credentials (postgres://user:pass@host).
- Email addresses with credentials. Patterns like user:pass@example.com.
- Credit card numbers. PCI patterns for safety.
The scanning runs automatically on every tool output. The agent doesn't see the redacted values; the agent sees [REDACTED] markers. The redacted values are logged separately for audit but not exposed to the agent.
Principle 3: Agent Outputs Are Scanned Before Delivery
The agent's outputs are scanned before delivery to the user or downstream systems. If the agent's response includes a credential, the response is blocked or redacted:
# Agent output (raw)
"Connection successful. The database password is P@ssw0rd!abc, you can use it for direct queries."
# After output scanning
"Connection successful. [Credential redacted from output for security.]"
The output scanning catches cases where the agent might try to share credentials, either from memory or from reasoning. The block prevents the leak.
The output scanning also catches credentials the agent might have reconstructed from partial information. If the agent reasons about "the third character of the password is..." and includes that in an output, the scanning can detect the reconstruction attempt.
The Credential Resolution Mechanism
When the agent needs to use a credential, the agent references the credential by identifier. The runtime resolves the identifier and uses the credential:
# Agent's request (in tool call)
exec(command="psql -h db.example.com -U app_user -d app_db -c 'SELECT 1'")
# Runtime's resolution
# 1. Recognize that this command needs database credentials
# 2. Look up the appropriate credential by context (the host, user, db)
# 3. Inject the credential as an environment variable or option
# 4. Execute the command with the credential available
# 5. The credential is in the process environment, not the agent's context
# Agent's view (in context)
exec_result = {"status": "success", "rows": [{"?column?": 1}]}
# No credential in the result
The credential resolution is invisible to the agent. The agent doesn't know the credential's value; the agent just sees that the operation succeeded. The runtime handles the credential's lifecycle: fetching, injecting, using, and clearing.
The Credential Reference Patterns
The agent references credentials using specific patterns that the runtime recognizes:
Environment variable references. The agent references an env var name; the runtime ensures it's set.
exec(command="deploy.sh")
# Runtime sees the deploy script needs DEPLOY_TOKEN
# Runtime injects DEPLOY_TOKEN from the vault before execution
Configuration references. The agent references a config key; the runtime resolves to the credential.
# Agent's request: "Update the production database schema"
# Runtime resolves: needs schema_migration_tool credentials
# Runtime injects: appropriate API token for the schema tool
Tool-specific references. The agent uses a tool that needs specific credentials; the runtime knows which.
# Agent's request: slack.send_message(channel="#alerts", text="...")
# Runtime resolves: needs Slack bot token for this channel
# Runtime injects: token in the Slack API call
The agent doesn't have to know how the credentials are provided. The agent just has to use the right tool or reference. The runtime handles the credential mechanics.
The Credential Rotation
Credentials rotate. API tokens expire. Database passwords change. The discipline requires the runtime to handle rotation transparently:
# Credential vault entry
{
"id": "database-production-credentials",
"type": "postgres",
"value_ref": "vault://prod/db/password",
"rotation_policy": "every 90 days",
"last_rotated": "2026-04-15T00:00:00Z",
"next_rotation": "2026-07-14T00:00:00Z"
}
The runtime fetches the credential at use time. If the credential has rotated since the last fetch, the runtime gets the new value. The agent always uses the current credential.
The rotation is transparent to the agent. The agent doesn't have to know when credentials rotate. The runtime handles it.
The Credential Audit Trail
Every credential use is logged. The audit trail captures:
- Which credential was used. The identifier, not the value.
- What operation was performed. The tool call, the system accessed.
- When the credential was used. The timestamp.
- Who (or what) used it. The agent session, the user.
- Whether the operation succeeded. The result.
{
"timestamp": "2026-07-02T10:15:23Z",
"session_id": "agent-2026-07-02-101500",
"credential_ref": "database-production-credentials",
"operation": "exec:psql-migration",
"target_system": "postgres://prod-db.example.com/app_db",
"result": "success"
}
The audit trail enables:
- Compliance. Auditors can verify which credentials were used for which operations.
- Detection. Unusual credential use patterns can be flagged.
- Investigation. When an incident occurs, the audit trail shows the credential activity.
The audit trail never contains credential values. The values are in the vault; the audit trail has identifiers.
The Secret Hygiene Failure Modes
Even with the discipline, failure modes exist. The agent must be aware of them:
Failure mode 1: Credentials embedded in code or configs. The agent reads a config file that has credentials inline. The scanning catches the credentials, but the agent now knows that a credential exists and may try to reconstruct or reference it.
Failure mode 2: Credentials in error messages. A failing API call returns the auth header in the error message. The scanning catches and redacts, but the agent may try to recover by re-authenticating with the same value.
Failure mode 3: Credentials in user input. A user pastes a credential into the chat. The scanning should catch this, but the agent may have already seen the credential in the user's message before redaction.
Failure mode 4: Credentials in MCP server responses. An MCP server returns data that includes credentials. The scanning catches them, but the agent may act on knowledge of the credential.
Failure mode 5: Credentials in tool descriptions. A tool's description or help text includes an example that has a real-looking credential. The agent may treat it as real.
The discipline addresses these by:
- Re-scanning after every redacted output to confirm
- Training the agent to never echo credentials even from context
- Providing safe ways for the agent to use credentials without seeing values
- Regularly testing the scanning with known credential patterns
The Secret Hygiene Doesn't Do
Honest limitations:
- It doesn't catch every credential format. New credential formats emerge. The scanning patterns have to be updated. There's always a window where a new format might slip through.
- It doesn't prevent the agent from learning about credentials indirectly. The agent can infer that a credential exists for a system from the system's behavior. The discipline prevents direct exposure but not inferential knowledge.
- It doesn't substitute for good operational security. A leaked credential in any system is a problem. The agent's discipline helps with the agent's exposure but not the underlying system's exposure.
- It can break legitimate workflows. If the agent needs to know a specific credential value (rare, but possible), the discipline prevents it. The team has to explicitly bypass the discipline for these cases.
- It requires constant maintenance. The scanning patterns, the credential references, and the rotation policies all need updates as the environment changes.
The Secret Hygiene as a Culture
Beyond the technical discipline, secret hygiene is a culture. The team that builds and operates the agent must commit to:
- No credentials in code. Configs reference credentials by identifier.
- No credentials in chat. Users don't paste credentials; they reference them.
- No credentials in logs. Loggers redact sensitive values before writing.
- No credentials in agent outputs. Output scanning blocks any leakage.
- Regular rotation. Credentials rotate on a schedule, not on demand.
The culture is what makes the discipline sustainable. The technical mechanisms catch mistakes; the culture prevents the mistakes in the first place.
Bottom Line
An AI agent that sees raw credentials is a security incident waiting to happen. The credentials enter the context, leak through outputs, and become part of the model's effective knowledge. The naive agent is a credential leak vector.
Facio's secret hygiene keeps credentials out of the agent's reach. The agent references credentials by identifier; the runtime resolves and uses them. Tool outputs are scanned and redacted. Agent outputs are scanned before delivery. Credential rotation is transparent. The audit trail tracks usage without values.
The agent without secret hygiene is a security risk. The agent with it is a secure operator. The enterprise can trust the secure one with sensitive operations. The risky one is limited to non-sensitive work.
Because agents with credential access are powerful. Agents without credential hygiene are dangerous. The discipline is what makes power safe.
See the secret hygiene documentation for credential reference patterns, scanning configuration, and rotation policies.