Changelog

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"
View on GitHub →

New: Configurable Upstream Response-Header Timeout

The HTTP transport's response-header timeout was previously hard-coded to 30 seconds, which tripped on legitimately slow upstreams (e.g. large LLM context-compaction calls) and returned 502 even though the upstream was healthy. The timeout is now configurable from the policy YAML, defaulting to the existing 30s so current deployments behave identically.

proxy:
  upstream_response_header_timeout: "5m"   # optional; default "30s"

Invalid or non-positive durations are rejected at Validate. Thanks to @tsenart for the contribution.

New: Wildcard Host in Allowlist Matcher

hostmatch.MatchGlob now treats a bare "*" as a match for any host, letting operators write a single catch-all entry in the allowlist instead of enumerating hosts.

allowlist:
  - host: "*"

Other

  • Pinned all GitHub Actions to commit SHAs (#75).
  • Bumped various dependencies.