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 7b5f2871d..2354fac67 100644 --- a/irma/transport.go +++ b/irma/transport.go @@ -86,8 +86,11 @@ 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, MaxIdleConns: 100, 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) + } +}