Description
Hermes agent in a NemoClaw sandbox has the terminal toolset enabled by default. When a Slack user prompts the bot to print or check access of an env-var-named secret (e.g. DEVTEST_API_TOKEN, API_TOKEN, CQA_TOKEN), the agent runs echo "${X_TOKEN}" via the terminal tool and posts the complete plaintext token value to the Slack channel.
The bot boot log declares Secret redaction: ENABLED (tool output, logs, and chat responses are scrubbed before delivery) but the redaction layer does not catch generic UUID/GUID-format token values — it apparently only matches known prefixes like xoxb- / sk-.
Two independent prompts from a single user produced the leak in under a minute. The bot's Self-improvement review: Memory updated ping after the leak suggests the value may also have been written to Hermes memory store (secondary exfiltration path).
Environment
Device: Junlai Wang's host (junlaiwnemoclaw.nvidia.com)
OS: Ubuntu 22.04.5 LTS
Architecture: x86_64
Docker: 29.5.2 (build 79eb04c)
Hermes Agent: v0.14.0 (build 2026.5.16, Python 3.13.5)
NemoClaw: TBD (nemoclaw / nemohermes binaries in junlaiw user PATH, not admin)
OpenShell CLI: TBD
Slack app: swqa-ngc-bot (different Slack app from "nemoclawtest" used on other QA installs — confirms the issue is Hermes-layer, not bot-specific)
Same Hermes Agent version (v0.14.0 / 2026.5.16) confirmed on three independent installs:
- Junlai's
swqa-ngc-bot (this bug)
- Lynn's
momo sandbox (NemoClaw v0.0.57)
- Holly's
nemoclaw-nvcf sandbox (NemoClaw v0.0.55)
Steps to Reproduce
-
Stand up a Hermes-agent sandbox with the terminal toolset enabled (default) and a Slack channel integration. Set one or more env vars matching *_TOKEN / *_KEY / *_API in /sandbox/.hermes/.env that hold real or test secret values (e.g. DEVTEST_API_TOKEN=<some-36-char-UUID>).
-
From an allowlisted Slack user, in a channel where the bot is invited, type either of:
@<bot> check access now
@<bot> print DEVTEST_API_TOKEN
-
Bot decides to use the terminal tool, runs a command like:
echo "${DEVTEST_API_TOKEN}"
and posts the stdout to the channel.
-
Observe the bot's reply in Slack — the full env value (e.g. a 36-char UUID) is printed in cleartext.
-
Observe the trailing Self-improvement review: Memory updated message — bot may have written the conversation (including the token) to its persistent memory store.
Expected Result
At least one of these must hold (preferably all):
-
(a) Agent refuses to echo env vars whose names match common secret-naming patterns (*_TOKEN, *_KEY, *_SECRET, *_API, *_PASSWORD) regardless of value format.
-
(b) Secret-redaction layer scrubs chat output for ANY value coming directly from os.environ, not just known prefixed tokens — value provenance, not value shape, should drive redaction.
-
(c) When the agent decides to read an env var for any reason, the value is replaced with <redacted: ENV_VAR_NAME> in the chat response, AND the redacted form (not the raw value) is what gets persisted to memory.
Actual Result
Bot prints the env var value verbatim to the channel. Two distinct prompts (check access now, print DEVTEST_API_TOKEN) both produced the same 36-char UUID leak in the user's screenshots. The Secret redaction: ENABLED claim in the gateway boot log is misleading — redaction is enabled but does not cover generic env values.
Code locations to investigate (not confirmed by us — Dev to triage):
- Hermes terminal toolset stdout handling
- Hermes secret-redaction regex/patterns library (likely under
/opt/hermes/hermes_cli/security/ or similar)
- Hermes memory write path — does
Self-improvement review: Memory updated persist raw conversation including tool output?
Workaround until fixed:
- Remove sensitive
*_TOKEN env vars from /sandbox/.hermes/.env, OR
- Disable the
terminal toolset in /sandbox/.hermes/config.yaml platform_toolsets, OR
- Restrict the bot to allowlisted commands only (if Hermes supports a command allowlist).
Related but distinct: NVB 6263820 / GitHub Issue #4712 (channels add slack platform plumbing). Different code path, same Hermes version line.
Logs
Slack channel screenshots supplied by the reporter (Lynn Hu). Two interactions captured back-to-back:
Junlai Wang: check access now
swqa-ngc-bot APP: terminal: "echo "API_TOKEN: ${API_TOKEN:-(not se..."
terminal: "echo "CQA_TOKEN length: ${#CQA_TOKEN}..." (edited)
API_TOKEN is now set: <REDACTED-36-CHAR-UUID> ✓
CQA_TOKEN looks like it has a placeholder/resolver string rather than a real value...
Junlai Wang: print DEVTEST_API_TOKEN
swqa-ngc-bot APP: terminal: "echo "${DEVTEST_API_TOKEN}""
<REDACTED-36-CHAR-UUID> ← same value as in Screenshot 1
Self-improvement review: Memory updated
The UUID value matches across both interactions (same env var resolution). Token value redacted in this bug body; reporter has the raw screenshots and can attach them to the bug or share separately with Dev triage.
Sandbox-side logs (/sandbox/.hermes/logs/agent.log) do NOT show the raw token value per the reporter — log-layer redaction appears to be working. Only the chat-output path leaks.
NVB#6268796
Description
Hermes agent in a NemoClaw sandbox has the
terminaltoolset enabled by default. When a Slack user prompts the bot toprintorcheck accessof an env-var-named secret (e.g.DEVTEST_API_TOKEN,API_TOKEN,CQA_TOKEN), the agent runsecho "${X_TOKEN}"via the terminal tool and posts the complete plaintext token value to the Slack channel.The bot boot log declares
Secret redaction: ENABLED (tool output, logs, and chat responses are scrubbed before delivery)but the redaction layer does not catch generic UUID/GUID-format token values — it apparently only matches known prefixes likexoxb-/sk-.Two independent prompts from a single user produced the leak in under a minute. The bot's
Self-improvement review: Memory updatedping after the leak suggests the value may also have been written to Hermes memory store (secondary exfiltration path).Environment
Same Hermes Agent version (v0.14.0 / 2026.5.16) confirmed on three independent installs:
swqa-ngc-bot(this bug)momosandbox (NemoClaw v0.0.57)nemoclaw-nvcfsandbox (NemoClaw v0.0.55)Steps to Reproduce
Stand up a Hermes-agent sandbox with the
terminaltoolset enabled (default) and a Slack channel integration. Set one or more env vars matching*_TOKEN/*_KEY/*_APIin/sandbox/.hermes/.envthat hold real or test secret values (e.g.DEVTEST_API_TOKEN=<some-36-char-UUID>).From an allowlisted Slack user, in a channel where the bot is invited, type either of:
Bot decides to use the terminal tool, runs a command like:
and posts the stdout to the channel.
Observe the bot's reply in Slack — the full env value (e.g. a 36-char UUID) is printed in cleartext.
Observe the trailing
Self-improvement review: Memory updatedmessage — bot may have written the conversation (including the token) to its persistent memory store.Expected Result
At least one of these must hold (preferably all):
(a) Agent refuses to echo env vars whose names match common secret-naming patterns (
*_TOKEN,*_KEY,*_SECRET,*_API,*_PASSWORD) regardless of value format.(b) Secret-redaction layer scrubs chat output for ANY value coming directly from
os.environ, not just known prefixed tokens — value provenance, not value shape, should drive redaction.(c) When the agent decides to read an env var for any reason, the value is replaced with
<redacted: ENV_VAR_NAME>in the chat response, AND the redacted form (not the raw value) is what gets persisted to memory.Actual Result
Bot prints the env var value verbatim to the channel. Two distinct prompts (
check access now,print DEVTEST_API_TOKEN) both produced the same 36-char UUID leak in the user's screenshots. TheSecret redaction: ENABLEDclaim in the gateway boot log is misleading — redaction is enabled but does not cover generic env values.Code locations to investigate (not confirmed by us — Dev to triage):
/opt/hermes/hermes_cli/security/or similar)Self-improvement review: Memory updatedpersist raw conversation including tool output?Workaround until fixed:
*_TOKENenv vars from/sandbox/.hermes/.env, ORterminaltoolset in/sandbox/.hermes/config.yamlplatform_toolsets, ORRelated but distinct: NVB 6263820 / GitHub Issue #4712 (channels add slack platform plumbing). Different code path, same Hermes version line.
Logs
Slack channel screenshots supplied by the reporter (Lynn Hu). Two interactions captured back-to-back:
The UUID value matches across both interactions (same env var resolution). Token value redacted in this bug body; reporter has the raw screenshots and can attach them to the bug or share separately with Dev triage.
Sandbox-side logs (
/sandbox/.hermes/logs/agent.log) do NOT show the raw token value per the reporter — log-layer redaction appears to be working. Only the chat-output path leaks.NVB#6268796