Skip to content

fix(tools): add logging filter to redact secrets from libtmux log output - #4871

Merged
simonrosenberg merged 3 commits into
mainfrom
fix/redact-libtmux-log-secrets
Sep 11, 2026
Merged

simonrosenberg merged 3 commits into
mainfrom
fix/redact-libtmux-log-secrets

Conversation

@all-hands-bot

@all-hands-bot all-hands-bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Collaborator

HUMAN:


AGENT:

Why

libtmux.common logs the full tmux command string when command execution raises. Commands passed through send-keys can contain API keys or tokens, which can then appear in agent-server stderr logs.

Python logging does not run filters attached to an ancestor logger for records emitted by child loggers. Therefore, attaching the filter only to libtmux does not redact records emitted by libtmux.common, the source of the leaking exception log.

Summary

  • Apply the API-key redaction filter to the loaded libtmux logger and all loaded libtmux.* child loggers.
  • Install filters during TmuxTerminal construction, before terminal operations can emit logs.
  • Add regression coverage proving a libtmux.common record reaches its handler with the secret replaced by <redacted>.

Issue Number

Fixes #4951

Related incident tracking: OpenHands/evaluation#446 and OpenHands/evaluation#383.

How to Test

Ran:

uv run pytest -q tests/tools/terminal
uv run pre-commit run --files tests/tools/terminal/test_tmux_log_redaction.py openhands-tools/openhands/tools/terminal/terminal/tmux_terminal.py

Results:

  • Terminal suite: 345 passed, 15 skipped.
  • All applicable pre-commit hooks passed, including Ruff, pycodestyle, Pyright, import rules, and tool registration.

Video/Screenshots

Not applicable; this changes backend log filtering and is covered by automated tests.

Design Doc

Not applicable for this focused logging fix.

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

The review claim was verified directly: a child logger record propagated to an ancestor handler without invoking the ancestor logger's filter. The focused regression test exercises the actual leaking child logger name, libtmux.common.


This PR was created by an AI agent (OpenHands) on behalf of the security scan workflow.


🐳 Agent Server images for this PR — GHCR package, pull/run commands, and all pushed tags (click to expand)

• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python-slim amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:bb57854-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-bb57854-python \
  ghcr.io/openhands/agent-server:bb57854-python

All tags pushed for this build

ghcr.io/openhands/agent-server:bb57854-golang-amd64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-golang-amd64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-golang-amd64
ghcr.io/openhands/agent-server:bb57854-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:bb57854-golang-arm64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-golang-arm64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-golang-arm64
ghcr.io/openhands/agent-server:bb57854-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:bb57854-java-amd64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-java-amd64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-java-amd64
ghcr.io/openhands/agent-server:bb57854-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:bb57854-java-arm64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-java-arm64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-java-arm64
ghcr.io/openhands/agent-server:bb57854-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:bb57854-python-amd64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-python-amd64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-python-amd64
ghcr.io/openhands/agent-server:bb57854-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:bb57854-python-arm64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-python-arm64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-python-arm64
ghcr.io/openhands/agent-server:bb57854-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:bb57854-python-slim-amd64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-python-slim-amd64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-python-slim-amd64
ghcr.io/openhands/agent-server:bb57854-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-slim-amd64
ghcr.io/openhands/agent-server:bb57854-python-slim-arm64
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-python-slim-arm64
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-python-slim-arm64
ghcr.io/openhands/agent-server:bb57854-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-slim-arm64
ghcr.io/openhands/agent-server:bb57854-golang
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-golang
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-golang
ghcr.io/openhands/agent-server:bb57854-golang_tag_1.21-bookworm
ghcr.io/openhands/agent-server:bb57854-java
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-java
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-java
ghcr.io/openhands/agent-server:bb57854-eclipse-temurin_tag_17-jdk
ghcr.io/openhands/agent-server:bb57854-python-slim
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-python-slim
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-python-slim
ghcr.io/openhands/agent-server:bb57854-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-slim
ghcr.io/openhands/agent-server:bb57854-python
ghcr.io/openhands/agent-server:bb578547b6252652b2f18a3f3d19a796476d046a-python
ghcr.io/openhands/agent-server:fix-redact-libtmux-log-secrets-python
ghcr.io/openhands/agent-server:bb57854-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim

About Multi-Architecture Support

  • Each variant tag (e.g., bb57854-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., bb57854-python-amd64) are also available if needed

The libtmux library logs full tmux command strings (including send-keys
arguments) to stderr when exceptions occur. This can leak API keys and
other secrets that agents send through the terminal.

Add a SecretRedactFilter to the libtmux logger that applies
redact_api_key_literals() from the SDK's redaction utilities to all
log messages before they are emitted.

Refs: OpenHands/evaluation#446

Co-authored-by: openhands <openhands@all-hands.dev>
@all-hands-bot

Copy link
Copy Markdown
Collaborator Author

👋 This PR needs a couple of things fixed before OpenHands can review it:

  • the PR description's HUMAN: section needs at least 20 characters describing what you tested, not just the template placeholder

Push an update once this is addressed and this check re-runs automatically.

This is an automated check - no AI was used to generate this comment.

@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result: ✅ PASSED

Action log

@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result: ✅ PASSED

Action log

@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-tools/openhands/tools/terminal/terminal
   tmux_terminal.py1267144%34–38, 42–43, 47–50, 117–118, 120, 123–124, 126–128, 130, 132, 134–136, 143–144, 148–149, 152–153, 158–162, 166, 169, 171–173, 177–182, 186–187, 204, 211–212, 217–218, 233, 255, 267–274, 282–283, 285–286, 288, 290–292
TOTAL428272222948% 

@enyst enyst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feedback from Astra:

Request changes: child loggers bypass the filter.

(I did not verify it myself FWIW)

@simonrosenberg

Copy link
Copy Markdown
Member

@OpenHands verify that claim
"Feedback from Astra:

Request changes: child loggers bypass the filter.

(I did not verify it myself FWIW)
" and fix the CI (pr description)

@openhands-ai

openhands-ai Bot commented Sep 11, 2026

Copy link
Copy Markdown

I'm on it! simonrosenberg can track my progress at all-hands.dev

Co-authored-by: openhands <openhands@all-hands.dev>

Copy link
Copy Markdown
Member

Verified: the Astra claim is correct. Python logging calls handlers on ancestor loggers for propagated child records, but it does not run filters attached to those ancestor loggers. libtmux emits the leaking exception from the libtmux.common child logger, so the previous filter on libtmux was bypassed.

Fixed in bb57854 by installing the redaction filter on the loaded libtmux logger and each loaded libtmux.* child logger during TmuxTerminal construction. Added a regression test against libtmux.common.

Validation:

  • uv run pytest -q tests/tools/terminal → 345 passed, 15 skipped
  • targeted pre-commit checks → all passed

I also restored the PR template, added test evidence, and linked the new focused issue #4951. The only remaining PR-description failure is intentionally human-only: @simonrosenberg, please add at least 20 visible characters between HUMAN: and AGENT: in your own words. Repository policy prohibits AI agents from filling that field.

There is also an unrelated deprecation-deadline failure for LLM.modify_params, which is present identically on current main; this PR does not modify it.

This comment was created by an AI agent (OpenHands) on behalf of the user.

@openhands-ai

openhands-ai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Verified: Astra’s claim is correct. Python logging does not run filters attached to ancestor loggers for propagated child records, and the leaking call comes from libtmux.common.

Completed:

Validation:

  • Terminal tests: 345 passed, 15 skipped
  • Pre-commit: passed
  • Remote pre-commit/security checks: passed

One required action remains: a human must add at least 20 visible characters between HUMAN: and AGENT: in the PR description. Repository policy forbids AI agents from filling that field. The latest validator confirms this is the only PR-description error.

There is also an unrelated LLM.modify_params deprecation-deadline CI failure that is present on current main.

PR: #4871

@simonrosenberg
simonrosenberg merged commit 8a55925 into main Sep 11, 2026
49 of 53 checks passed
@simonrosenberg
simonrosenberg deleted the fix/redact-libtmux-log-secrets branch September 11, 2026 07:27
sohamb117 pushed a commit to sohamb117/openhands-software-agent-sdk that referenced this pull request Sep 12, 2026
…put (OpenHands#4871)

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: simonrosenberg <157206163+simonrosenberg@users.noreply.github.com>
Bowbee pushed a commit to PlayCastDotIo/openhands-software-agent-sdk that referenced this pull request Sep 15, 2026
…put (OpenHands#4871)

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: simonrosenberg <157206163+simonrosenberg@users.noreply.github.com>
@github-actions github-actions Bot mentioned this pull request Sep 15, 2026
6 of 7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Redact secrets from libtmux child logger output

4 participants