From b3d7774d9c5bcbdcc992fcf393ee807819c6bbde Mon Sep 17 00:00:00 2001 From: lpf Date: Thu, 19 Feb 2026 21:11:27 +0800 Subject: [PATCH] fix loop --- pkg/agent/context.go | 2 ++ pkg/agent/loop.go | 36 ++++++++++++++++++++++++++++++++++- pkg/agent/loop_secret_test.go | 26 +++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 pkg/agent/loop_secret_test.go diff --git a/pkg/agent/context.go b/pkg/agent/context.go index ec57663..200da33 100644 --- a/pkg/agent/context.go +++ b/pkg/agent/context.go @@ -78,6 +78,8 @@ Your workspace is at: %s %s Always be helpful, accurate, and concise. When using tools, explain what you're doing. +For operational tasks (for example configuring git remotes/credentials), prefer executing tools directly instead of only giving manual steps. +If user provides credentials/tokens for a requested operation, you may use them to execute the task, but never expose full secrets in visible output. When remembering something, write to %s/memory/MEMORY.md`, now, runtime, workspacePath, workspacePath, workspacePath, workspacePath, toolsSection, workspacePath) } diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index e64fe70..38bcac6 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -3381,7 +3381,8 @@ func (al *AgentLoop) executeSingleToolCall( progress *stageReporter, ) toolCallExecResult { if !systemMode { - argsJSON, _ := json.Marshal(tc.Arguments) + safeArgs := sanitizeSensitiveToolArgs(tc.Arguments) + argsJSON, _ := json.Marshal(safeArgs) argsPreview := truncate(string(argsJSON), 200) logger.InfoCF("agent", fmt.Sprintf("Tool call: %s(%s)", tc.Name, argsPreview), map[string]interface{}{ "tool": tc.Name, @@ -4326,6 +4327,39 @@ func truncate(s string, maxLen int) string { return s[:maxLen-3] + "..." } +func sanitizeSensitiveToolArgs(args map[string]interface{}) map[string]interface{} { + if len(args) == 0 { + return map[string]interface{}{} + } + raw, err := json.Marshal(args) + if err != nil { + return map[string]interface{}{"_masked": true} + } + redacted := redactSecretsInText(string(raw)) + out := map[string]interface{}{} + if err := json.Unmarshal([]byte(redacted), &out); err != nil { + return map[string]interface{}{"_masked": true} + } + return out +} + +func redactSecretsInText(text string) string { + if strings.TrimSpace(text) == "" { + return text + } + out := text + authHeaderPattern := regexp.MustCompile(`(?i)(authorization\s*[:=]\s*["']?(?:bearer|token)\s+)([^\s"']+)`) + out = authHeaderPattern.ReplaceAllString(out, "${1}[REDACTED]") + + keyValuePattern := regexp.MustCompile(`(?i)("?(?:token|api[_-]?key|password|passwd|secret|authorization|access[_-]?token|refresh[_-]?token)"?\s*:\s*")([^"]+)(")`) + out = keyValuePattern.ReplaceAllString(out, "${1}[REDACTED]${3}") + + commonTokenPattern := regexp.MustCompile(`(?i)\b(ghp_[A-Za-z0-9_]+|glpat-[A-Za-z0-9_-]+)\b`) + out = commonTokenPattern.ReplaceAllString(out, "[REDACTED]") + + return out +} + // GetStartupInfo returns information about loaded tools and skills for logging. func (al *AgentLoop) GetStartupInfo() map[string]interface{} { info := make(map[string]interface{}) diff --git a/pkg/agent/loop_secret_test.go b/pkg/agent/loop_secret_test.go new file mode 100644 index 0000000..cf0d452 --- /dev/null +++ b/pkg/agent/loop_secret_test.go @@ -0,0 +1,26 @@ +package agent + +import "testing" + +func TestRedactSecretsInText(t *testing.T) { + in := `{"token":"abc123","authorization":"Bearer sk-xyz","password":"p@ss","note":"ok"}` + out := redactSecretsInText(in) + + if out == in { + t.Fatalf("expected redaction to change input") + } + if containsAnySubstring(out, "abc123", "sk-xyz", "p@ss") { + t.Fatalf("expected sensitive values to be redacted, got: %s", out) + } +} + +func TestSanitizeSensitiveToolArgs(t *testing.T) { + args := map[string]interface{}{ + "command": "git -c http.extraHeader='Authorization: token abc123' ls-remote https://example.com/repo.git", + "token": "abc123", + } + safe := sanitizeSensitiveToolArgs(args) + if safe["token"] == "abc123" { + t.Fatalf("expected token field to be redacted") + } +}