Changelog

View on GitHub →

New: Header Allowlist Transform

Adds a header_allowlist transform that strips any request header not present in a configured allowlist before forwarding the request upstream. The allowlist uses a default-deny model — every header must match either a literal name (case-insensitive) or a /regex/ pattern to pass through. Stripped header names are recorded in the trace annotation stripped_headers. An optional rules field scopes the allowlist to specific host/method/path combinations. Place this transform after any transforms that inject headers (e.g. secrets) so injected headers survive the allowlist.

transforms:
  - name: header_allowlist
    config:
      headers:
        - "Authorization"
        - "Content-Type"
        - "User-Agent"
        - "Accept"
        - "/^X-Trace-.*$/"
      # Optional: limit to specific hosts/methods/paths.
      # Omit to apply to all requests.
      rules:
        - host: "api.openai.com"
View on GitHub →

New: Regex Patterns in match_headers

The secrets transform's match_headers list now accepts regex patterns alongside literal header names. Patterns use /…/ delimiters and are compiled at config time as case-insensitive regular expressions matched against canonical header names. Literal entries continue to work and can be mixed with regex entries in the same list.

- source:
    type: env
    var: MY_API_KEY
  replace:
    proxy_value: "proxy-key-abc"
    match_headers:
      - "Authorization"      # literal (unchanged)
      - "/^X-My-Api-.+/"    # regex (new)

Fixes

  • MITM-generated certificate chains now include the configured signing CA, enabling deployments where clients trust a long-lived root CA and the proxy signs with a short-lived intermediate. Previously, leaf-only certificates caused chain validation failures in such setups.
View on GitHub →

New: Management API With Hot Reload

iron-proxy can now expose an opt-in, bearer-authenticated HTTP management API. The first endpoint, POST /v1/reload, re-reads the YAML config from disk and atomically swaps in a freshly built transform pipeline with no restart and no dropped connections. Parse or build errors return 422 and leave the running pipeline untouched.

management:
  listen: "127.0.0.1:9092"
  # Env var holding the bearer token; defaults to IRON_MANAGEMENT_API_KEY.
  api_key_env: "IRON_MANAGEMENT_API_KEY"

Reload a running proxy:

curl -X POST http://127.0.0.1:9092/v1/reload \
  -H "Authorization: Bearer $IRON_MANAGEMENT_API_KEY"

Binding on a loopback address is recommended.

View on GitHub →

New: 1Password Secret Source

The secrets transform now supports 1password as a secret source, alongside env, aws_sm, and aws_ssm. The resolver uses the 1Password Go SDK with service-account-token auth; the token is read from OP_SERVICE_ACCOUNT_TOKEN by default or from a configurable token_env. References use the standard op://vault/item/[section/]field syntax.

transforms:
  - name: secrets
    config:
      secrets:
        - source:
            type: 1password
            secret_ref: "op://Engineering/OpenAI/credential"
            token_env: OP_SERVICE_ACCOUNT_TOKEN  # optional; this is the default
            ttl: "15m"                            # optional; 0 = no refresh
        # ...

Note: a bug in onepassword-sdk-go breaks builds with CGO_ENABLED=0, so iron-proxy pins a fork via a replace directive in go.mod until the fix lands upstream.

View on GitHub →

New: Upstream IP Deny List

Add CIDR ranges to proxy.upstream_deny_cidrs, and the proxy will refuse to dial any address that matches regardless of allowlist contents. This is useful when you want extra protection against unintended egress to sensitive ranges such as cloud metadata services and loopback.

By default, the proxy will block cloud instance metadata and loopback via the following CIDRs:

  • 169.254.169.254/32 (AWS / GCP / Azure IPv4 IMDS)
  • fd00:ec2::254/128 (AWS IPv6 IMDS)
  • 127.0.0.0/8 (IPv4 loopback)
  • ::1/128 (IPv6 loopback)

The defaults intentionally omit RFC1918, since many iron-proxy deployments target private corporate networks.

Provide an explicit list to override the defaults, or an empty list to opt out entirely:

proxy:
  upstream_deny_cidrs:
    - "169.254.169.254/32"
    - "127.0.0.0/8"

If your workload talks to IMDS or loopback upstreams today, you must set this field before upgrading or the proxy will refuse those connections.

New: Path Scanning for Secret Replacement

The secrets replace transform can now scan req.URL.Path for the proxy token and swap it for the resolved secret. This enables routing through iron-proxy for upstreams that embed credentials in the URL, such as Telegram's /bot<TOKEN>/sendMessage. The new match_path flag is off by default because URL paths often appear in access logs on either side of the proxy.

- source:
    type: env
    var: TELEGRAM_BOT_TOKEN
  replace:
    proxy_value: "proxy-tg-token-123"
    match_headers: []
    match_path: true
    require: true
  rules:
    - host: "api.telegram.org"