Skip to content

Redact user code and response data from Code.run debug logs (CWE-532)#13

Closed
sebastiondev wants to merge 1 commit into
agbcloud:masterfrom
sebastiondev:fix/cwe532-code-api-78a3
Closed

Redact user code and response data from Code.run debug logs (CWE-532)#13
sebastiondev wants to merge 1 commit into
agbcloud:masterfrom
sebastiondev:fix/cwe532-code-api-78a3

Conversation

@sebastiondev
Copy link
Copy Markdown

Summary

The Code.run() method in both agb/modules/code.py and python/agb/modules/code.py logs the full user-supplied code and the full response data through log_operation_start / log_operation_success. These calls emit at DEBUG level via loguru. When debug logging is enabled (e.g. AGB_LOG_LEVEL=DEBUG, a common troubleshooting setting), the logs end up containing whatever the caller passes to the sandbox and whatever the sandbox returns — which in practice often includes API keys, tokens, query results, file contents, and other data that callers reasonably expect to remain in-process.

This is a CWE-532 (Insertion of Sensitive Information into Log File) issue.

Affected:

  • agb/modules/code.pyCode.run()
  • python/agb/modules/code.pyCode.run() (mirrored copy)

Data flow:

  1. Caller invokes Code.run(code=..., language=...) with code that may embed secrets or process sensitive inputs.
  2. log_operation_start("Code.run", f"...Code={code}") writes the full source to the logger.
  3. On success, log_operation_success("Code.run", f"ResponseData={result.data}") writes the full execution output.
  4. With DEBUG enabled, both records reach configured sinks (stdout, log files, aggregators).

Fix

Replace the sensitive payloads with non-sensitive metadata that still preserves debugging value:

  • Code={code}CodeLength={len(code)}
  • ResponseData={result.data}RequestId={result.request_id}

The request ID is already used elsewhere as the correlation handle for support/debugging, and code length is sufficient to confirm the call shape without leaking content. The parsed result is still returned to the caller unchanged — only the log line is redacted.

Test results

  • The full Python test suite passes (481 tests) with no behavioral changes.
  • Manually verified that successful and failure paths still produce useful log lines (Language, TimeoutS, CodeLength, RequestId) at the same levels as before.
  • No public API surface, return values, or exception behavior changed.

Why this is worth fixing

Before submitting, we tried to disprove the finding. The main mitigation candidates would be (a) loguru's default level filtering out these records, or (b) the SDK never being run with debug logging in environments where logs are retained. Neither holds up: AGBLogger.set_level("DEBUG") and the AGB_LOG_LEVEL env var are documented entry points, debug logging is routinely enabled when diagnosing sandbox failures (which is exactly when the executed code matters), and loguru sinks frequently include rotating files or stdout captured by orchestrators. There is no scrubbing layer between these log calls and the sinks, so once DEBUG is on, the secrets are written verbatim. Exploitation requires DEBUG logging plus log access rather than being a remote-trigger bug, so severity is moderate — but the fix is one-line-per-site and removes the exposure entirely.

Diff scope

Two files, 7 insertions / 10 deletions. No dependency, config, or API changes.

cc @lewiswigmore

Code.run() previously logged the full code body and full response data
in plaintext via log_operation_start() and log_operation_success().
In agent frameworks where code may contain secrets, API keys, or
credentials, this creates a credential harvesting vector for anyone
with log access.

Changes:
- Replace Code={code} with CodeLength={len(code)} in operation start log
- Replace ResponseData={result.data} with RequestId={result.request_id}
  in operation success log

This follows the same pattern used by Command.execute which logs
command metadata without dumping the full content.
@lewiswigmore
Copy link
Copy Markdown

Closing this to reduce the open-PR pile-up — we have multiple outstanding security contributions to this repo and that volume is not fair on your review queue. Keeping #11 (fix: reject symlinks in extension upload to prevent arbitrary file exfiltration ) as the primary one to focus attention on.

Happy to revisit this finding separately later if it is still relevant. Apologies for the noise.

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.

2 participants