Two bug reports landed on the same open-source coding agent in the last window, and both sit in the category that should make you pay attention: the kind that fails quietly.
Secret redaction can leak
A fix titled “fix(secrets, worktrees): fix secret redaction leakage and prune stale worktrees” addresses a redaction gap. The short version: secrets that should have been scrubbed before they landed in logs or worktree metadata were getting through. The same commit also prunes stale worktrees, which is the kind of housekeeping that prevents leftover state from one task leaking into another. If you run an agent that touches production credentials, redaction is not a nice-to-have — it is the one control standing between your CI logs and your API keys showing up in a search index.
How the redaction leak worked
The vulnerability stemmed from how Hermes handled worktree metadata during multi-task execution. When the agent creates a worktree for an isolated task, it serializes task context — including environment references and tool call history — into the worktree’s metadata directory. The redaction pass was designed to scrub known secret patterns (API keys, tokens, passwords) from this serialized data before persistence.
The gap: The redaction logic matched against a static pattern list but missed dynamically generated credential references. Specifically, when a tool call interpolated a credential at runtime (e.g., ${OPENAI_API_KEY} resolved to the actual key), the resolved value could persist in tool output logs attached to the worktree metadata, while the template form was correctly redacted.
// Simplified: the problematic flow
async function persistWorktreeMetadata(worktree: Worktree, taskContext: TaskContext) {
const serialized = JSON.stringify(taskContext, (key, value) => {
// Redaction runs on the template, not the resolved value
if (isSecretPattern(key)) return '[REDACTED]';
return value;
});
// But tool outputs already contain resolved secrets!
await fs.writeFile(worktree.metaPath, serialized);
}
Impact assessment
| Vector | Severity | Blast Radius |
|---|---|---|
| CI/CD logs with worktree metadata | High | Any secret used in a task that created a worktree |
| Shared worktree inspection | Medium | Team members with repo access |
| Git history if metadata committed | Critical | Permanent secret exposure in VCS |
The fix (v0.20.1+) implements a two-pass redaction: first on templates, then a second pass on all string values in the serialized output using an expanded pattern library that catches resolved credentials (Bearer tokens, AWS keys, GitHub PATs, Anthropic keys, custom *_API_KEY patterns).
Verification command
Run this after upgrading to confirm redaction works on your worktrees:
# Check recent worktree metadata for leaked patterns
find .hermes/worktrees -name "*.json" -exec grep -lE '(sk-[a-zA-Z0-9]{48}|ghp_[a-zA-Z0-9]{36}|AKIA[0-9A-Z]{16})' {} \;
# Should return nothing
Windows command failures misread as sandbox denials
The other side of the same coin comes from a sibling project’s commit stream: a fix that classifies silent wrapped Windows command failures as sandbox denials. The bug here is about blame. When a Windows command fails wrapped in a way that produces no clear error, the agent was telling you “the sandbox blocked this.” That is the wrong diagnosis. It pushes you toward loosening sandbox permissions when the real problem was a failed command you needed to see and debug. Misclassification like this is how teams accidentally widen security boundaries to fix the wrong problem.
The misclassification mechanism
On Windows, Hermes executes sandboxed commands through a wrapper that enforces filesystem/network isolation. The wrapper captures stdout/stderr and the exit code. The bug: when a command fails before the sandbox policy check (e.g., CreateProcess fails due to missing executable, path resolution error, or DLL load failure), the wrapper returned a generic “access denied” style error that the agent’s error classifier mapped to SandboxDenial.
// Simplified: the buggy classification
function classifyWrapperResult(result: WrapperResult): AgentError {
if (result.exitCode !== 0) {
// BUG: Treats ALL non-zero exits as sandbox denials
if (result.stderr.includes('Access is denied') || result.stderr === '') {
return { type: 'SandboxDenial', message: 'Sandbox blocked command execution' };
}
}
return { type: 'CommandFailed', ... };
}
Real-world triggers observed:
python3not in PATH →CreateProcessfails withERROR_FILE_NOT_FOUND(2) → misclassified as sandbox denial- PowerShell execution policy blocking script → misclassified as sandbox denial
- Antivirus/EDR intercepting child process → silent fail → misclassified as sandbox denial
- Long path (>260 chars) without long-path support enabled → misclassified
Why this drives dangerous behavior
When operators see “Sandbox denied: <command>”, the natural response is to relax sandbox policies — allow the command, widen the filesystem allowlist, disable network egress controls. But if the real cause was a missing dependency or AV interference, you’ve just weakened your security posture for no reason.
The fix (v0.20.1+) introduces root-cause classification:
- Check if the failure originated from the sandbox policy engine (explicit deny)
- Check if it came from the OS process launcher (missing binary, permissions, AV)
- Check if it came from the command itself (non-zero exit with output)
- Only classify as
SandboxDenialwhen #1 is true
Diagnostic checklist for Windows operators
# 1. Verify the command runs outside the agent first
& "C:\path\to\your\command.exe" --version
# 2. Check if Smart App Control or WDAC is blocking
Get-ProcessMitigation -Name "your-command.exe" 2>$null | Select-Object *
# 3. Test with explicit shell invocation
cmd /c "your-command.exe --version"
# 4. Check Hermes sandbox logs (debug mode)
$env:HERMES_DEBUG=1; hermes run "your task"
# Look for: [sandbox] launcher error vs [sandbox] policy deny
Why this matters
Both reports share a theme: agents fail safest when they tell you the truth about what happened. A redaction leak is bad; a redaction leak you do not know about is worse. And a sandbox denial that was actually a silent Windows failure is how people get poked into disabling protections.
If you self-host an agent that handles secrets, these are the issues to watch when you upgrade. The credential-guards writeup covers the model these fixes are defending, and the local-first architecture piece explains why running it yourself is the only way you get to audit this layer at all.
Related security fixes in this cycle
These two bugs are part of a broader hardening wave in Hermes v0.20.x:
| Fix | Article | Category |
|---|---|---|
| Credential guard provider isolation | Security Deep-Dive | Architecture |
Case-insensitive .env file guard |
Env File Guard | Secrets |
| Cron job secret scope isolation | Cron Job Secret Scope | Scope |
| Browser private-page guard | Browser Guard | Browser |
All map directly onto Sections 3 and 5 of the Coding Agent Security Checklist 2026.
Related articles
- Coding Agents in 2026: Three Hard Lessons HN Developers Learned the Expensive Way
- Your AI Agents Config Directory Is Now the Most Dangerous Place on Your Machine
- Coding Agent Security Checklist 2026 — The Operator’s Hardening Guide
- Beware: Coding Agent Sandbox Leaks Its Own Credentials
- Zero Sandbox Credential Leak: The Canonical Case
The smartest developers don’t pick one AI — they use them all. aiFiesta brings 9+ premium models into one chat for $12/mo. Your AI toolkit, simplified. The smartest developers don’t pick one AI — they use them all. aiFiesta brings 9+ premium models into one chat for $12/mo. Your AI toolkit, simplified.