Skip to content

fix(security): add proxy-aware transport with MITM warning and opt-out#247

Merged
maochengwei1024-create merged 1 commit intomainfrom
fix/proxy-mitm-hardening
Apr 3, 2026
Merged

fix(security): add proxy-aware transport with MITM warning and opt-out#247
maochengwei1024-create merged 1 commit intomainfrom
fix/proxy-mitm-hardening

Conversation

@maochengwei1024-create
Copy link
Copy Markdown
Collaborator

@maochengwei1024-create maochengwei1024-create commented Apr 3, 2026

Summary

  • Replace all http.DefaultTransport usage with util.NewBaseTransport(), which clones DefaultTransport and supports LARK_CLI_NO_PROXY=1 to disable proxy entirely
  • Add one-time proxy detection warning (with credential redaction) when proxy env vars are detected
  • Suppress warning when proxy is already disabled via LARK_CLI_NO_PROXY

Test plan

  • go build ./... passes
  • All existing tests pass (internal/cmdutil, internal/auth, internal/update)
  • New tests cover: proxy detection, base transport creation, warning output, credential redaction (scheme-prefixed and bare URL), silent-when-disabled, only-once semantics

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Detects proxy environment variables and emits a one-time warning (proxy info is redacted).
    • Honor LARK_CLI_NO_PROXY=1 to disable proxy behavior.
  • Chores

    • Improved HTTP client/transport handling across the CLI for more reliable network behavior.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 3, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added the size/L Large or sensitive change across domains or core paths label Apr 3, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a1aac79-d95e-40c5-be31-3ea57d47211d

📥 Commits

Reviewing files that changed from the base of the PR and between a752404 and 8924208.

📒 Files selected for processing (6)
  • internal/auth/transport.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport.go
  • internal/update/update.go
  • internal/util/proxy.go
  • internal/util/proxy_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/auth/transport.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport.go
  • internal/util/proxy_test.go
  • internal/update/update.go

📝 Walkthrough

Walkthrough

Adds a proxy utility and tests, and updates several HTTP transport initializations to use the new util base/fallback transports and emit a one-time proxy warning where clients are constructed.

Changes

Cohort / File(s) Summary
Proxy Utility Module
internal/util/proxy.go, internal/util/proxy_test.go
Adds proxy environment detection and handling: EnvNoProxy constant, DetectProxyEnv(), WarnIfProxied(io.Writer), NewBaseTransport(), and FallbackTransport(). Implements proxy URL credential redaction and one-time warning emission; includes comprehensive unit tests.
Transport Layer Updates
internal/auth/transport.go, internal/cmdutil/transport.go, internal/cmdutil/factory_default.go, internal/update/update.go
Replaces usages of http.DefaultTransport with util.NewBaseTransport() or util.FallbackTransport() as appropriate. factory_default.go now calls util.WarnIfProxied(os.Stderr) before building base transports. update.go constructs default HTTP client with util.NewBaseTransport() as its Transport.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI Client
  participant Factory as client factory
  participant Util as util package
  participant Env as Proxy Env
  participant Net as Network

  CLI->>Factory: request HTTP client
  Factory->>Util: WarnIfProxied(os.Stderr)
  Util->>Env: DetectProxyEnv()
  Env-->>Util: proxy key/value (maybe empty)
  alt proxy detected and not disabled
    Util-->>Factory: prints one-time warning (redacted)
  end
  Factory->>Util: NewBaseTransport() / FallbackTransport()
  Util-->>Factory: *http.Transport (proxy configured or disabled)
  CLI->>Net: HTTP request using returned Transport
  Net-->>CLI: HTTP response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I sniffed the env for hidden streams and trace,
I hid the secrets in a safer place,
New transports hop, warnings said once, neat—
A crunchy carrot of code, tidy and sweet. 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description covers the key aspects but lacks comprehensive alignment with the template structure. The Summary and Test plan sections are present, but the Changes section is missing and Related Issues is not explicitly addressed. Add a structured Changes section listing the main modifications (e.g., new proxy.go file, transport updates across multiple files) and explicitly address Related Issues to fully comply with the template.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding proxy-aware transport with MITM warning and opt-out capability, which aligns with the core objectives of the pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/proxy-mitm-hardening

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR introduces proxy-aware HTTP transport across the CLI by replacing all http.DefaultTransport usages with util.NewBaseTransport(), which clones DefaultTransport and optionally disables proxy via LARK_CLI_NO_PROXY. A one-time warning (WarnIfProxied) is emitted to stderr when a proxy env var is detected. Previous review concerns (connection-pool fragmentation, missing warning in the Lark SDK path, and os.Setenv without cleanup in tests) have all been addressed in this revision.

Key changes:

  • internal/util/proxy.go — new NewBaseTransport(), FallbackTransport() singleton, WarnIfProxied(), and redactProxyURL() helpers
  • internal/cmdutil/factory_default.goWarnIfProxied now called in both cachedHttpClientFunc and cachedLarkClientFunc; both use NewBaseTransport() as base
  • internal/cmdutil/transport.go / internal/auth/transport.go — all fallback paths replaced with util.FallbackTransport() (shared singleton, preserving TCP connection pooling)
  • internal/update/update.gohttpClient() now supplies a NewBaseTransport() transport
  • internal/util/proxy_test.go — comprehensive unit tests with correct t.Setenv usage throughout

Confidence Score: 5/5

Safe to merge; all previous P1 concerns are resolved and remaining findings are test-robustness suggestions only.

All three previously flagged P1/P2 issues (connection-pool fragmentation, missing WarnIfProxied in the Lark SDK path, os.Setenv without cleanup) have been addressed. The only remaining findings are P2 test-robustness gaps: three warn-tests that assert a warning IS emitted do not clear LARK_CLI_NO_PROXY first, so they could produce vacuously passing or spuriously failing results in CI environments where that var is pre-set. These do not affect production behaviour and do not block merge.

internal/util/proxy_test.go — three test functions (TestWarnIfProxied_WithProxy, TestWarnIfProxied_OnlyOnce, TestWarnIfProxied_RedactsCredentials) should clear LARK_CLI_NO_PROXY via t.Setenv before asserting warning output.

Important Files Changed

Filename Overview
internal/util/proxy.go Core proxy-detection and transport helpers; well-structured with sync.Once guards. Minor: proxyWarningOnce is consumed even on no-op paths (LARK_CLI_NO_PROXY set / no proxy detected), which is intentional but subtly tricky.
internal/util/proxy_test.go Good coverage of proxy detection, redaction, and once-semantics. Three warn-tests do not guard against a pre-set LARK_CLI_NO_PROXY in the host environment, which could cause spurious failures in CI.
internal/cmdutil/factory_default.go WarnIfProxied now called in both HTTP client paths; NewBaseTransport replaces DefaultTransport correctly.
internal/cmdutil/transport.go All fallback paths now use FallbackTransport() singleton, preserving connection pooling.
internal/auth/transport.go DefaultTransport fallback replaced with FallbackTransport(); no other changes.
internal/update/update.go Update checker now uses NewBaseTransport(), consistent with the rest of the codebase.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[HTTP Request] --> B{cachedHttpClientFunc\nor cachedLarkClientFunc}
    B --> C[util.WarnIfProxied\nsync.Once guard]
    C --> D{LARK_CLI_NO_PROXY set?}
    D -- yes --> E[Once consumed, silent]
    D -- no --> F{Proxy env var detected?}
    F -- no --> G[Once consumed, silent]
    F -- yes --> H[Emit redacted warning to stderr]
    H --> I[util.NewBaseTransport\nclone of DefaultTransport]
    E --> I
    G --> I
    I --> J{LARK_CLI_NO_PROXY set?}
    J -- yes --> K[t.Proxy = nil / no proxy]
    J -- no --> L[t.Proxy = ProxyFromEnvironment]
    K --> M[Transport middleware chain]
    L --> M
    M --> N[Outbound HTTP request]
    subgraph Fallback path
        O[Transport decorator Base == nil] --> P[util.FallbackTransport singleton]
        P --> M
    end
Loading

Reviews (2): Last reviewed commit: "fix(security): replace http.DefaultTrans..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@892420862f097584a483ade985e9296902dce51e

🧩 Skill update

npx skills add larksuite/cli#fix/proxy-mitm-hardening -y -g

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
internal/cmdutil/transport.go (1)

21-25: Cache the nil-Base fallback transport instead of cloning per call.

util.NewBaseTransport() returns a fresh clone of http.DefaultTransport. In the nil-Base path, this means a new connection pool on every request, and RetryTransport creates a different transport for each retry attempt (lines 37 and 53). Although all current instantiations in factory_default.go (lines 78–90, 103–110) and tests explicitly set Base, this fallback pattern creates an inefficiency footgun if any caller omits it. Cache one fallback transport and reuse it across all calls, applying the same treatment to:

  • RetryTransport.base() (lines 21–25)
  • UserAgentTransport.RoundTrip() (lines 64–70)
  • SecurityHeaderTransport.base() (lines 79–83)
  • SecurityPolicyTransport.base() in internal/auth/transport.go (lines 24–29)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmdutil/transport.go` around lines 21 - 25, The code currently calls
util.NewBaseTransport() each time a transport fallback is needed, which creates
a new connection pool per call; fix this by introducing a package-level cached
base transport (initialized once, e.g., via sync.Once or in init()) and return
that cached transport whenever t.Base is nil. Update RetryTransport.base(),
UserAgentTransport.RoundTrip() (nil-Base path), SecurityHeaderTransport.base(),
and SecurityPolicyTransport.base() to use the shared cachedBaseTransport instead
of calling util.NewBaseTransport() each time so all retries and requests reuse
the same connection pool.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmdutil/factory_default.go`:
- Around line 77-79: The proxy warning is only emitted in cachedHttpClientFunc,
so cachedLarkClientFunc (used by f.LarkClient()) can build its own HTTP stack
without calling util.WarnIfProxied; add a call to util.WarnIfProxied(os.Stderr)
inside the cachedLarkClientFunc initialization (or move the single-call into a
shared initialization used by both closures) so the MITM warning is emitted for
the SDK client path as well; locate cachedLarkClientFunc and
cachedHttpClientFunc and ensure util.WarnIfProxied is invoked before creating
the transport (util.NewBaseTransport()) in the Lark client path.

In `@internal/util/proxy_test.go`:
- Around line 175-190: In TestNewBaseTransport_RespectsNoProxyEnv replace the
direct call to os.Setenv(EnvNoProxy, "") with t.Setenv(EnvNoProxy, "") so the
test uses testing.T's environment cleanup stack; locate the call in the
TestNewBaseTransport_RespectsNoProxyEnv function (which calls NewBaseTransport)
and update it to t.Setenv to avoid leaking LARK_CLI_NO_PROXY across tests.

---

Nitpick comments:
In `@internal/cmdutil/transport.go`:
- Around line 21-25: The code currently calls util.NewBaseTransport() each time
a transport fallback is needed, which creates a new connection pool per call;
fix this by introducing a package-level cached base transport (initialized once,
e.g., via sync.Once or in init()) and return that cached transport whenever
t.Base is nil. Update RetryTransport.base(), UserAgentTransport.RoundTrip()
(nil-Base path), SecurityHeaderTransport.base(), and
SecurityPolicyTransport.base() to use the shared cachedBaseTransport instead of
calling util.NewBaseTransport() each time so all retries and requests reuse the
same connection pool.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 31d0fe64-bf87-4563-9583-55b0bb680700

📥 Commits

Reviewing files that changed from the base of the PR and between 8425898 and a752404.

📒 Files selected for processing (6)
  • internal/auth/transport.go
  • internal/cmdutil/factory_default.go
  • internal/cmdutil/transport.go
  • internal/update/update.go
  • internal/util/proxy.go
  • internal/util/proxy_test.go

…ansport to mitigate MITM risk

All HTTP clients previously used http.DefaultTransport which silently respects
HTTP_PROXY/HTTPS_PROXY env vars, allowing credentials to transit through
untrusted proxies. This adds a proxy detection warning and an opt-out switch
(LARK_CLI_NO_PROXY=1) so security-sensitive users can disable proxy entirely.

- Redact proxy credentials in warning output (handles both scheme-prefixed and bare URL formats)
- Suppress warning when LARK_CLI_NO_PROXY is already set
- Use FallbackTransport singleton for nil-Base fallback paths to preserve connection pooling
- Emit proxy warning on both HTTP client and Lark SDK client paths

Change-Id: Ibed7d0470409c73fbd42bccac6673f9fc5e87a83
@maochengwei1024-create maochengwei1024-create merged commit 77460ab into main Apr 3, 2026
14 checks passed
@maochengwei1024-create maochengwei1024-create deleted the fix/proxy-mitm-hardening branch April 3, 2026 08:38
@liangshuo-1 liangshuo-1 mentioned this pull request Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants