From 27b63489b04d492a54a27ae11930859cf52471e8 Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Sun, 16 Aug 2026 10:45:13 +0200 Subject: [PATCH 1/2] Re-apply patch --- irma/transport.go | 1 + 1 file changed, 1 insertion(+) diff --git a/irma/transport.go b/irma/transport.go index 7b5f2871d..b7436b972 100644 --- a/irma/transport.go +++ b/irma/transport.go @@ -90,6 +90,7 @@ func NewHTTPTransport(serverURL string, forceHTTPS bool) *HTTPTransport { innerTransport := &http.Transport{ TLSClientConfig: tlsClientConfig, ForceAttemptHTTP2: true, + Proxy: http.ProxyFromEnvironment, // Proxy support via env vars MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, From a8f221e95fcfe8372436607cb1ced8ddcfcf273a Mon Sep 17 00:00:00 2001 From: Ruben Hensen Date: Tue, 18 Aug 2026 10:58:22 +0200 Subject: [PATCH 2/2] Address review on proxy support - Move Proxy to the front of the http.Transport literal, matching http.DefaultTransport's field order, and fold the explanation into the comment above the literal instead of a trailing inline comment. - Add a CHANGELOG entry: the behaviour change is operator-visible, and anyone with a system-wide proxy needs to know NO_PROXY is the way to keep internal traffic off it. - Add TestNewHTTPTransport_UsesEnvironmentProxy, asserting the transport is proxy-aware and that loopback destinations stay unproxied. --- CHANGELOG.md | 2 ++ irma/transport.go | 6 ++++-- irma/transport_test.go | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd3d9807c..1bb3f93a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +### Fixed +- `irma.HTTPTransport` now honours the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables, so irmago can run where outgoing traffic must pass through a proxy; it was the only outbound transport in irmago that ignored them. Operators with a system-wide proxy can keep internal traffic (requestor callbacks, keyshare and revocation servers) off it with `NO_PROXY`; loopback addresses are never proxied ([#423](https://github.com/privacybydesign/irmago/issues/423)) ## [1.3.0] - 2026-08-12 ### Added diff --git a/irma/transport.go b/irma/transport.go index b7436b972..2354fac67 100644 --- a/irma/transport.go +++ b/irma/transport.go @@ -86,11 +86,13 @@ func NewHTTPTransport(serverURL string, forceHTTPS bool) *HTTPTransport { } // Create a transport that dials with a SIGPIPE handler (which is only active on iOS). - // The settings are inspired on the defaults of http.DefaultTransport. + // The settings are inspired on the defaults of http.DefaultTransport, including its + // Proxy: outbound requests honour the HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment + // variables, as the rest of irmago already does through http.DefaultTransport. innerTransport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, TLSClientConfig: tlsClientConfig, ForceAttemptHTTP2: true, - Proxy: http.ProxyFromEnvironment, // Proxy support via env vars MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, diff --git a/irma/transport_test.go b/irma/transport_test.go index 4a3ad5126..4a962722e 100644 --- a/irma/transport_test.go +++ b/irma/transport_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "net/http" "net/http/httptest" + "net/url" "testing" "github.com/stretchr/testify/require" @@ -146,3 +147,28 @@ func TestJsonRequest_RemoteErrorBodyIsPreserved(t *testing.T) { }) } } + +// TestNewHTTPTransport_UsesEnvironmentProxy covers issue #423: HTTPTransport was the +// only outbound transport in irmago that left http.Transport.Proxy unset, so it ignored +// the HTTP_PROXY/HTTPS_PROXY environment variables that everything routed through +// http.DefaultTransport already honours. +// +// The proxy function is inspected directly rather than exercised against a real proxy, +// because net/http reads the environment once behind a sync.Once: a test setting +// HTTP_PROXY would only take effect if it happened to run before any other code in the +// process resolved a proxy. +func TestNewHTTPTransport_UsesEnvironmentProxy(t *testing.T) { + inner, ok := NewHTTPTransport("https://example.com", true).client.HTTPClient.Transport.(*http.Transport) + require.True(t, ok) + require.NotNil(t, inner.Proxy, "outbound transport must honour HTTP_PROXY/HTTPS_PROXY") + + // Loopback destinations are never proxied, whatever the environment says, so local + // servers (including the ones in these tests) keep being dialled directly. + for _, dest := range []string{"http://localhost:8080/foo", "http://127.0.0.1:8080/foo"} { + u, err := url.Parse(dest) + require.NoError(t, err) + proxy, err := inner.Proxy(&http.Request{URL: u}) + require.NoError(t, err) + require.Nil(t, proxy, "loopback destination %s must not be proxied", dest) + } +}