From a06ee832881f4adc990225e2371289b1954a4832 Mon Sep 17 00:00:00 2001 From: proxy-turkey Date: Tue, 14 Jul 2026 22:24:09 +0300 Subject: [PATCH 1/3] fix: address all high/medium/low issues from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit High: - Guard all 5 context type assertions with ccAPIKeyFromContext helper (handlers.go) — prevents panic if middleware ordering changes - Handle rand.Read error in randomHex, fall back to timestamp (converter.go) Medium: - Replace global consecutiveTimeouts with per-session sync.Map keyed by sessionID — prevents timeout counter leaking across users - Guard Choices[0] index access with length check (handlers.go) - Make CORS origin configurable instead of hardcoded "*" (middleware.go) - Build settings JSON via python3 json.dumps in claude-proxy.sh to prevent injection if token contains quotes/backslashes - Add config package tests: missing file, permission denied, invalid JSON, valid JSON, env overrides, validation (config_test.go) Low: - Merge double message iteration into single pass (converter.go) - Extract buildCommandCodeConfig helper to eliminate duplicated 14-field Config block across both converters - Fix snake_case cc_apiKey param to ccAPIKey across client.go/init.go - Replace header blocklist with allowlist (anthropic-* + standard) for safer upstream forwarding (client.go) - Use custom http.Transport with connection pooling instead of http.Client timeout that kills long streaming responses (client.go) - Fix modelRefreshIntervalMs JSON tag to modelRefreshInterval (was silently treated as nanoseconds instead of duration) --- claude-proxy.sh | 44 ++++++++--- internal/client/client.go | 53 +++++++++----- internal/client/init.go | 4 +- internal/config/config.go | 2 +- internal/config/config_test.go | 129 +++++++++++++++++++++++++++++++++ internal/http/handlers.go | 101 +++++++++++++++++--------- internal/http/handlers_test.go | 2 +- internal/http/middleware.go | 34 +++++---- internal/http/server.go | 2 +- internal/protocol/converter.go | 77 ++++++++------------ 10 files changed, 318 insertions(+), 130 deletions(-) create mode 100644 internal/config/config_test.go diff --git a/claude-proxy.sh b/claude-proxy.sh index aa81404..536777b 100755 --- a/claude-proxy.sh +++ b/claude-proxy.sh @@ -53,20 +53,39 @@ while [[ $# -gt 0 ]]; do esac done -# Build settings JSON that overrides the global settings.json env block. -# --settings MERGES with the global config, so we must explicitly override -# every env var that interferes: -# - ANTHROPIC_AUTH_TOKEN: global sets "dummy"; interactive (cli) mode uses -# this for auth, so it must be the real proxy token. -# - ANTHROPIC_CUSTOM_HEADERS: global injects Cloudflare gateway headers; -# cleared so they don't leak to the local proxy. -# - ANTHROPIC_BASE_URL: global points at Cloudflare gateway. -SETTINGS=$(cat </dev/null; then + SETTINGS=$(python3 -c ' +import json, sys +token = sys.argv[1] +model = sys.argv[2] +haiku = sys.argv[3] +print(json.dumps({ + "env": { + "ANTHROPIC_BASE_URL": "http://127.0.0.1:3050", + "ANTHROPIC_API_KEY": token, + "ANTHROPIC_AUTH_TOKEN": token, + "ANTHROPIC_CUSTOM_HEADERS": "", + "ANTHROPIC_MODEL": model, + "ANTHROPIC_DEFAULT_HAIKU_MODEL": haiku, + "ANTHROPIC_DEFAULT_SONNET_MODEL": model, + "ANTHROPIC_DEFAULT_OPUS_MODEL": model + }, + "model": model +})) +' "$PROXY_TOKEN" "$MODEL" "$HAIKU") +else + # Fallback: escape token for JSON (handles " and \) + ESCAPED_TOKEN="${PROXY_TOKEN//\\/\\\\}" + ESCAPED_TOKEN="${ESCAPED_TOKEN//\"/\\\"}" + SETTINGS=$(cat < Date: Wed, 15 Jul 2026 16:51:58 +0300 Subject: [PATCH 2/3] Update internal/config/config_test.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- internal/config/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 72da57b..04247b1 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -93,7 +93,7 @@ func TestLoadEnvOverrides(t *testing.T) { t.Setenv("COMMANDCODE_PROXY_TOKEN", "envtoken") t.Setenv("LOG_LEVEL", "debug") - cfg, err := Load("/tmp/nonexistent-config-test.json") + cfg, err := Load(filepath.Join(t.TempDir(), "nonexistent-config-test.json")) if err != nil { t.Fatalf("Load() error = %v", err) } From d5246c5b77fc1a5bb526f47058873b4c87ee667d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kerem=20G=C3=B6k?= <229108989+KilimcininKorOglu@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:52:08 +0300 Subject: [PATCH 3/3] Update internal/config/config_test.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- internal/config/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 04247b1..ba831e5 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -8,7 +8,7 @@ import ( ) func TestLoadFallsBackToDefaultsWhenFileMissing(t *testing.T) { - cfg, err := Load("/tmp/nonexistent-config-test.json") + cfg, err := Load(filepath.Join(t.TempDir(), "nonexistent-config-test.json")) if err != nil { t.Fatalf("Load() error = %v, want nil for missing file", err) }