feat: enhance debug logging and sensitive data handling#44
Conversation
- Added debug logging options to display full payloads or metadata only based on configuration. - Introduced `DebugLogPayloads` flag in the configuration to control logging behavior. - Updated `runStatus` to print debug configuration details. - Implemented redaction for sensitive API keys in configuration and logging outputs. - Enhanced environment variable handling to mask sensitive values and show only safe ones. - Added tests to verify the correct behavior of new logging and redaction features. - Improved tool safety checks to warn about sensitive outputs.
There was a problem hiding this comment.
Pull request overview
This PR tightens sensitive-data handling across tool outputs and debug logging, adding configuration to control whether full LLM request/response payloads are written to disk and expanding redaction/masking behavior in CLI output.
Changes:
- Added
debug_log_payloadsconfig to allow opting into full prompt/response logging whendebug=file; default remains metadata-only. - Hardened sensitive output handling: redacted provider API keys in
config show/ config-change prompts; environment tool now only reveals a small allowlist of env values and hides the rest. - Improved safety guardrails: added sensitive-tool warnings/prompts for
environmentandlist_memories, and injected an “untrusted tool output” system guardrail into the tool loop; added/updated tests accordingly.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| internal/tools/tools_test.go | Updates env-tool expectations to reflect value hiding/allowlist behavior. |
| internal/tools/tools_additional_test.go | Adds safety-warning assertions and improves cross-platform HOME/USERPROFILE setup. |
| internal/tools/tools.go | Updates env tool description and disables truncation for environment output. |
| internal/tools/safety_test.go | Aligns FilterEnvironment tests with new “[VALUE HIDDEN]” behavior. |
| internal/tools/safety.go | Implements safe allowlist for env values; hides unknown values and redacts sensitive keys. |
| internal/tools/runner_test.go | Verifies prompt-injection guardrail and prompting for sensitive tools in dangerous mode. |
| internal/tools/runner.go | Injects “tool output is untrusted” guardrail; marks env/memories as sensitive in safety checks. |
| internal/llm/prompt.go | Updates tool description text for environment. |
| internal/llm/client_test.go | Adds tests for debug-file metadata-only vs opted-in payload logging; checks log file perms (non-Windows). |
| internal/llm/client.go | Secures debug log file perms; adds debugMode/DebugLogPayloads handling to control payload logging. |
| internal/interactive/repl_test.go | Adds test ensuring config-change output masks API keys. |
| internal/interactive/repl.go | Masks displayed config-change values via config.DisplayValue. |
| internal/config/redact.go | Adds secret redaction helpers (RedactSecret, RedactedCopy, DisplayValue). |
| internal/config/config_test.go | Tests new redaction helpers and debug_log_payloads persistence/defaults. |
| internal/config/config.go | Adds DebugLogPayloads to config schema and default config. |
| cmd/status_wizard_test.go | Updates expected status output to include debug settings; tests metadata-only debug file mode. |
| cmd/status.go | Prints debug mode and (when file) whether log captures payloads or metadata only. |
| cmd/root_test.go | Adds helper to capture stdout; tests config-change output redacts secrets. |
| cmd/root.go | Updates NewClient signature usage; redacts secrets in config show; masks config-change output. |
| cmd/config.go | Adds debug_log_payloads to get/set/completions; redacts config show output via RedactedCopy. |
| cmd/cmd_test.go | Adds tests for debug_log_payloads get/set and verifies config show redaction. |
| README.md | Documents new debug logging behavior and expanded safety notes/guardrails. |
Comments suppressed due to low confidence (2)
internal/tools/tools.go:81
environmenttool output is returned without any size cap. Even with values hidden, a full environment dump can still be very large and may cause oversized LLM requests (token/context limit errors) or unnecessary latency/cost. Consider adding a reasonable truncation/line cap (or a "show all" flag) while still ensuring allowlisted keys like PATH remain included near the top (e.g., sort and/or always include a required subset).
output = execEnvironment()
// Do not truncate environment output; values are already hidden by
// default and callers may need to inspect the full variable list.
return output, nil
README.md:411
- The README states that
llm.logis created with user-only permissions, but on Windows the Unix permission bits used bychmod(0600)don't reliably enforce user-only access. Consider qualifying this statement (e.g., "on Unix-like systems") or documenting Windows behavior separately to avoid giving a false security guarantee.
- `debug=file` writes to `~/.ai-cli/llm.log`
- `debug=file` logs metadata only by default; full prompt and response bodies require `debug_log_payloads=true`
- `llm.log` is created with user-only permissions
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: abbca6824c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if len(secret) <= 8 { | ||
| return "****" | ||
| } |
There was a problem hiding this comment.
Keep empty secrets empty in redaction output
RedactSecret currently turns an empty API key into "****", and config show now marshals RedactedCopy, so unset api_key fields are rendered as non-empty placeholders. This makes it impossible to tell whether a key is actually configured and can lead users to copy/persist "****" back into config, causing avoidable authentication failures; returning an empty string for empty input would preserve the unset state while still masking real keys.
Useful? React with 👍 / 👎.
|
@copilot create a pull request to fix this issue: ```Keep empty secrets empty in redaction output RedactSecret currently turns an empty API key into "", and config show now marshals RedactedCopy, so unset api_key fields are rendered as non-empty placeholders. This makes it impossible to tell whether a key is actually configured and can lead users to copy/persist "" back into config, causing avoidable authentication failures; returning an empty string for empty input would preserve the unset state while still masking real keys``` |
|
@kriserickson I've opened a new pull request, #45, to work on those changes. Once the pull request is ready, I'll request review from you. |
DebugLogPayloadsflag in the configuration to control logging behavior.runStatusto print debug configuration details.