nodejs/node · error · InvalidArgumentError

Proxy-Authorization should be sent in ProxyAgent constructor

Error message

Proxy-Authorization should be sent in ProxyAgent constructor

What it means

Thrown by throwIfProxyAuthIsSent when a 'proxy-authorization' header is found in the per-request headers passed to ProxyAgent.dispatch. For security, Proxy-Authorization must be supplied once at construction (via auth/token/url credentials) so it is not leaked or overridden per request; the per-request check (added to fix a security vulnerability) blocks the older pattern. The check is case-insensitive on the header key and is scheduled for removal in the next major version for performance.

Source

Thrown at deps/undici/src/lib/dispatcher/proxy-agent.js:375

 */
function throwIfProxyAuthIsSent (headers) {
  for (const key in headers) {
    if (isProxyAuthorizationHeader(key)) {
      throwProxyAuthError()
    }
  }
}

/**
 * @param {string} key
 * @returns {boolean}
 */
function isProxyAuthorizationHeader (key) {
  return key.length === proxyAuthorization.length && key.toLowerCase() === proxyAuthorization
}

function throwProxyAuthError () {
  throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor')
}

module.exports = ProxyAgent

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Remove any 'proxy-authorization' header from per-request headers.
  2. Move the credential to ProxyAgent construction via opts.token, opts.auth, or the proxy URL's user info.
  3. Strip proxy-authorization in a header-sanitizing middleware before dispatch.
  4. If a library auto-injects it, configure that library to stop doing so for proxied requests.

Example fix

// before
proxyAgent.dispatch({ ..., headers: { 'proxy-authorization': `Basic ${b64}` } })
// after
new ProxyAgent({ uri, token: `Basic ${b64}` })
proxyAgent.dispatch({ ..., headers: {} })
Defensive patterns

Strategy: validation

Validate before calling

function stripProxyAuth(headers = {}) {
  const out = {}
  for (const [k, v] of Object.entries(headers)) {
    if (k.toLowerCase() !== 'proxy-authorization') out[k] = v
  }
  return out
}
proxyAgent.dispatch({ ..., headers: stripProxyAuth(reqHeaders) })

Type guard

function hasProxyAuthHeader(headers = {}) {
  return Object.keys(headers).some(k => k.toLowerCase() === 'proxy-authorization')
}

Try / catch

try {
  proxyAgent.dispatch(req)
} catch (e) {
  if (e.code === 'UND_ERR_INVALID_ARG' && /Proxy-Authorization/.test(e.message)) {
    delete req.headers['proxy-authorization']
    proxyAgent.dispatch(req)
  } else throw e
}

Prevention

When it happens

Trigger: Calling proxyAgent.dispatch({ ..., headers: { 'proxy-authorization': 'Basic ...' } }) or any case variant like 'Proxy-Authorization'. The dispatch path routes headers through throwIfProxyAuthIsSent, which iterates keys and matches via isProxyAuthorizationHeader.

Common situations: Migrating from code that set Proxy-Authorization per request; HTTP libraries that auto-attach proxy auth headers from env; merging upstream request headers that include a proxy-authorization copied from elsewhere.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/909be2bb841c6a18. Report an issue: GitHub.