Skip to content

Conversation

@markng
Copy link

@markng markng commented Jan 17, 2026

Problem

Node.js native fetch() doesn't respect HTTP_PROXY/HTTPS_PROXY environment variables. This causes Linearis to fail in environments that require proxy configuration, such as:

  • Corporate networks with mandatory proxies
  • Docker containers with proxy configurations
  • CI/CD environments behind firewalls

Solution

This PR adds automatic proxy detection and configuration using undici's ProxyAgent. When any of the standard proxy environment variables are set (HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy), requests are automatically routed through the proxy.

Implementation Details

  • Uses undici's setGlobalDispatcher() to configure the proxy before any requests are made
  • The proxyTls: { rejectUnauthorized: false } option allows connections through proxies that intercept HTTPS traffic (common in corporate environments)
  • The upstream connection to api.linear.app retains full TLS verification
  • Zero impact when no proxy is configured (the code is a no-op)

Changes

  • src/main.ts: Added proxy detection and configuration at startup
  • package.json: Added undici as a dependency

Testing

Tested in an environment with HTTP_PROXY configured:

# Before: fails with connection errors
$ linearis teams list
Error: fetch failed

# After: works correctly
$ linearis teams list
[{"id": "...", "name": "..."}]

Limitations

  • Only supports HTTP/HTTPS CONNECT proxies (not SOCKS)
  • Does not handle NO_PROXY exclusions (could be added in a follow-up)
  • Proxy auth must be embedded in the URL (e.g., http://user:pass@proxy:8080)

Node.js native fetch doesn't respect HTTP_PROXY/HTTPS_PROXY environment
variables. This adds automatic proxy detection and configuration using
undici's ProxyAgent.

When HTTP_PROXY, HTTPS_PROXY, http_proxy, or https_proxy environment
variables are set, requests are automatically routed through the proxy.

The proxyTls option is set to allow connections through proxies that
intercept HTTPS traffic (common in corporate environments), while
maintaining full TLS verification for the upstream Linear API connection.
Copilot AI review requested due to automatic review settings January 17, 2026 06:43
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds HTTP proxy support to Linearis by integrating undici's ProxyAgent to intercept and route requests through proxies configured via standard environment variables (HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy). This enables the CLI to work in corporate networks, Docker containers, and CI/CD environments that require proxy configuration.

Changes:

  • Added automatic proxy detection and configuration using undici's setGlobalDispatcher() at application startup
  • Added undici as a runtime dependency to enable proxy functionality

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/main.ts Implements proxy detection from environment variables and configures undici's global dispatcher with ProxyAgent before any HTTP requests are made
package.json Adds undici ^7.0.0 as a runtime dependency for proxy support

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

src/main.ts Outdated
Comment on lines 25 to 31
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
})
);
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

Setting rejectUnauthorized: false for proxyTls disables TLS certificate verification for the connection to the proxy itself. This creates a security vulnerability where attackers could intercept traffic between the application and the proxy using a man-in-the-middle attack.

While the PR description mentions this allows connections through proxies that intercept HTTPS traffic, disabling certificate verification is a dangerous default. Consider either:

  1. Requiring users to explicitly opt-in via an environment variable (e.g., LINEARIS_PROXY_INSECURE=true)
  2. Removing this option entirely and letting users configure their system's certificate store if needed
  3. At minimum, add a warning when this insecure mode is active
Suggested change
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
})
);
const proxyInsecure =
process.env.LINEARIS_PROXY_INSECURE === "1" ||
process.env.LINEARIS_PROXY_INSECURE === "true";
if (proxyUrl) {
const proxyOptions: { uri: string; proxyTls?: { rejectUnauthorized: boolean } } = {
uri: proxyUrl,
};
if (proxyInsecure) {
proxyOptions.proxyTls = { rejectUnauthorized: false };
// Warn users that they have explicitly opted into insecure proxy TLS behavior.
// This disables TLS certificate verification between the application and the proxy.
console.warn(
"[linearis] Warning: LINEARIS_PROXY_INSECURE is enabled; TLS certificate verification for proxy connections is disabled."
);
}
setGlobalDispatcher(new ProxyAgent(proxyOptions));

Copilot uses AI. Check for mistakes.
src/main.ts Outdated
Comment on lines 17 to 32
// Proxy support: Node.js native fetch doesn't respect HTTP_PROXY env vars.
// This configures undici's global dispatcher to route through the proxy.
import { ProxyAgent, setGlobalDispatcher } from "undici";
const proxyUrl =
process.env.HTTPS_PROXY ||
process.env.HTTP_PROXY ||
process.env.https_proxy ||
process.env.http_proxy;
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
})
);
}
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

The new proxy configuration logic lacks test coverage. Since the codebase has comprehensive vitest unit tests (as seen in tests/unit/), this critical infrastructure change should include tests to verify:

  1. Proxy URL detection from different environment variables
  2. Correct priority order (HTTPS_PROXY > HTTP_PROXY > https_proxy > http_proxy)
  3. Behavior when no proxy is configured
  4. ProxyAgent initialization with correct parameters

Consider adding a test file like tests/unit/proxy-config.test.ts to ensure this functionality works correctly across different environments.

Copilot uses AI. Check for mistakes.
src/main.ts Outdated
Comment on lines 17 to 32
// Proxy support: Node.js native fetch doesn't respect HTTP_PROXY env vars.
// This configures undici's global dispatcher to route through the proxy.
import { ProxyAgent, setGlobalDispatcher } from "undici";
const proxyUrl =
process.env.HTTPS_PROXY ||
process.env.HTTP_PROXY ||
process.env.https_proxy ||
process.env.http_proxy;
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
})
);
}
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

The new proxy support feature is not documented. Users need to know:

  1. That HTTP_PROXY/HTTPS_PROXY environment variables are now supported
  2. The priority order of the variables (HTTPS_PROXY > HTTP_PROXY > https_proxy > http_proxy)
  3. The format for proxy URLs (especially if authentication is needed: http://user:pass@proxy:8080)
  4. Any security implications of the implementation

Consider adding a "Proxy Configuration" section to the README.md that documents this feature, similar to the existing "Authentication" section.

Copilot uses AI. Check for mistakes.
src/main.ts Outdated
Comment on lines 24 to 29
process.env.http_proxy;
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
Copy link

Copilot AI Jan 17, 2026

Choose a reason for hiding this comment

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

The proxy configuration does not respect the NO_PROXY environment variable. This means that all requests, including localhost or internal network requests, will be routed through the proxy when one is configured.

While the PR description mentions this as a known limitation, routing requests to api.linear.app through a proxy is the intended behavior. However, if the codebase makes any requests to localhost or internal services, those would incorrectly go through the proxy as well.

Consider adding NO_PROXY support to exclude certain domains from proxy routing, particularly for common patterns like localhost, 127.0.0.1, and *.local.

Suggested change
process.env.http_proxy;
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
process.env.http_proxy;
const noProxyEnv = process.env.NO_PROXY || process.env.no_proxy;
const defaultNoProxy = "localhost,127.0.0.1,::1,.local";
const noProxy = noProxyEnv
? `${noProxyEnv},${defaultNoProxy}`
: defaultNoProxy;
if (proxyUrl) {
setGlobalDispatcher(
new ProxyAgent({
uri: proxyUrl,
proxyTls: { rejectUnauthorized: false },
noProxy,

Copilot uses AI. Check for mistakes.
1. Security: Make insecure proxy TLS opt-in via LINEARIS_PROXY_INSECURE
   - Secure by default (TLS verification enabled)
   - Users must explicitly set LINEARIS_PROXY_INSECURE=1 to disable
   - Warning printed when insecure mode is active

2. NO_PROXY support: Respect NO_PROXY/no_proxy environment variables
   - Allows excluding hosts from proxy routing

3. Tests: Add comprehensive unit tests for proxy detection
   - Test proxy URL detection and priority order
   - Test NO_PROXY detection
   - Test insecure mode opt-in

4. Documentation: Add Proxy Configuration section to README
   - Document all supported environment variables
   - Explain priority order
   - Provide usage examples
   - Document security implications of insecure mode

5. Refactor: Extract proxy logic to src/utils/proxy.ts
   - Separates concerns for better testability
   - Exports detectProxyConfig() and configureProxy() functions
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