Skip to content

Upstream TLS connections forced to TLS 1.2 due to incorrect SSLMaxVersion default and inverted condition #7798

@byungwook-min

Description

@byungwook-min

Branch/Environment/Version

  • Branch/Version: All active releases (v5.8.x LTS through master, verified on v5.8.5, v5.8.12-rc1, v5.9.2, v5.10.2, v5.11.1, release-5.12, master)
  • Environment: All (On-prem/Hybrid/MDCB)

Describe the bug

Tyk Gateway forces TLS 1.2 as the maximum version for upstream (outbound) TLS connections, preventing TLS 1.3 negotiation. This is caused by two separate code issues:

Bug 1 — Inverted condition in gateway/api_loader.go

// gateway/api_loader.go:168 (master)
if spec.Proxy.Transport.SSLMaxVersion > 0 {       // BUG: should be == 0
    spec.Proxy.Transport.SSLMaxVersion = tls.VersionTLS12
}

The intent is to set a default when the value is unconfigured (== 0), but the condition > 0 overwrites any explicitly set value back to TLS 1.2. Setting ssl_max_version: 772 (TLS 1.3) in an API definition gets reset to 771 (TLS
1.2) because 772 > 0 is true.

Bug 2 — Global default hardcodes TLS 1.2 in gateway/server.go

// gateway/server.go:1571 (master)
if gwConfig.ProxySSLMaxVersion == 0 {
    gwConfig.ProxySSLMaxVersion = tls.VersionTLS12
}

In Go's crypto/tls, MaxVersion = 0 means "negotiate the highest supported version" (TLS 1.3 in Go 1.18+). Tyk treats 0 as "not configured" and forces it to TLS 1.2, contradicting Go's standard behavior. The same pattern exists for
downstream at line 1579.

Reproduction steps
Steps to reproduce the behavior:

  1. Deploy Tyk Gateway with default config (no proxy_ssl_max_version set)
  2. Create an API with an upstream that supports TLS 1.3
  3. Observe that the connection is negotiated at TLS 1.2, not TLS 1.3

To verify via API-level config:

  1. Set proxy.transport.ssl_max_version: 772 in an API definition
  2. Observe the value is overwritten to 771 (TLS 1.2) by api_loader.go:168

Actual behavior

  • All upstream TLS connections are capped at TLS 1.2
  • API-level ssl_max_version setting is silently ignored (overwritten)

Expected behavior
A clear and concise description of what you expected to happen.

  • With no config: TLS version should be negotiated up to TLS 1.3 (Go default)
  • With ssl_max_version: 772: TLS 1.3 should be used as the maximum version

Screenshots/Video
If applicable, add screenshots or video to help explain your problem.

Logs (debug mode or log file):
Not applicable — no error is logged. The TLS version downgrade happens silently during config initialization.

Configuration (tyk config file):

Default configuration (no TLS version settings):

{
  "proxy_ssl_max_version": 0,
  "proxy_ssl_min_version": 0
}

Additional context
Add any other context about the problem here.

Affected code locations across branches:

Branch api_loader.go (Bug 1) server.go (Bug 2)
master line 168 line 1571, 1579
v5.8.12-rc1 (LTS) line 164 line 1503, 1511
v5.9.2 line 180 line 1400, 1408
v5.10.2 line 167 line 1468, 1476
v5.11.1 line 167 line 1477, 1485
release-5.12 line 167 line 1571, 1579

Workaround:

  • Gateway level: Set TYK_GW_PROXYSSLMAXVERSION=772 (or "proxy_ssl_max_version": 772 in tyk.conf)
  • API level: Set both ssl_min_version: 772 and ssl_max_version: 772 (min > max correction at api_loader.go:172 restores the value, but this results in TLS 1.3 only — no TLS 1.2 fallback)

Proposed fix:

  1. api_loader.go:168 — Change > 0 to == 0
  2. server.go:1571, 1579 — Change default from tls.VersionTLS12 to tls.VersionTLS13 (update outdated 2021 default to reflect current TLS landscape)

I would like to submit a PR for this fix. Backport to release-5.8 (LTS) would be appreciated as well.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions