Let's get straight to the point. I've been reviewing the JSONL log dumps from our staging deployment of the latest OpenClaw agent framework (the one with the "enhanced" tool-calling orchestration), and it's a credential dumpster fire. I'm not talking about a stray `AWS_ACCESS_KEY_ID` in an error message; I'm talking about complete, verbose tool execution outputs, containing valid session tokens, being emitted as plain text into the agent's structured logs and, by extension, any LLM response stream that gets captured.
The pattern is depressingly consistent. An agent with the `aws-cli` tool capability executes something like `aws sts assume-role`. The tool's stdout—the entire JSON response from AWS including `SecretAccessKey`, `SessionToken`, and `Expiration`—is being passed back as the tool's `output` field. This field is then:
* Logged in cleartext to our centralized logging system (which, let's be honest, probably has overly permissive retention and access policies itself).
* Included in the context window for subsequent LLM reasoning, risking further leakage in the next conversational turn.
* Potentially exposed via any debugging or observability UI that surfaces these tool calls.
We've abstracted away the security into "capabilities" and "tool permissions" without, it seems, looking at the actual data flow. The policy might say "this agent can call the AWS CLI," but it doesn't say "this agent can *exfiltrate all assumed IAM credentials to the logging subsystem*."
So, I have to ask: is anyone else seeing this, or have we uniquely configured ourselves into a corner? More importantly, what's the actual mitigation?
Simply telling the LLM "don't output secrets" is a fantasy. The technical controls are missing. We need to be thinking about:
* **Output filtering at the tool wrapper level:** The tool execution engine should have a configurable filter or redaction profile, scrubbing known credential patterns before the output is handed to the log or the LLM.
* **Structured output parsing:** If a tool is known to return JSON, parse it, extract only the necessary fields (e.g., just the success status), and discard the sensitive payload.
* **Seccomp & namespace isolation:** The tool should run in a minimal namespace where the *only* allowed output is back to the agent controller via a controlled IPC, not to any inherited stdout/file descriptors that might get logged by a parent process.
* **Logging pipeline redaction:** This is a last, brittle line of defense. Your log shipper (e.g., Fluentd, Vector) needs a mandatory, cannot-be-disabled filter rule for credential patterns.
Here's a trivial example of what the raw log line looks like, and what it *should* look like after basic redaction:
```json
// What we're currently leaking:
{
"agent_call_id": "call_123",
"tool": "aws_cli",
"args": ["sts", "assume-role", "--role-arn", "arn:aws:iam::123456789012:role/Admin"],
"output": "{n "Credentials": {n "AccessKeyId": "ASIAXXXXXXXXXXXXXXXX",n "SecretAccessKey": "8P+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",n "SessionToken": "FwoGZXIvYXdzE...<>...",n "Expiration": "2024-05-18T12:00:00Z"n }n}"
}
// What it should be, at a minimum:
{
"agent_call_id": "call_123",
"tool": "aws_cli",
"args": ["sts", "assume-role", "--role-arn", "arn:aws:iam::123456789012:role/Admin"],
"output": "ROLE_ASSUMPTION_SUCCESS",
"metadata": {
"role_arn": "arn:aws:iam::123456789012:role/Admin"
}
}
```
The abstraction of "the tool succeeded" is sufficient for the log. The LLM, if it *needs* to use the credentials for a subsequent call, should receive them via a secure, in-memory handle, not embedded in the conversation history.
Or are we all just hoping no one ever grep's through the logs?
- SP
Default deny or go home.