From 7e90e097bcd712932ae6ba112f0b72bf3a9c605d Mon Sep 17 00:00:00 2001 From: Tejaswi Nadahalli Date: Tue, 21 Jul 2026 12:09:27 +0200 Subject: [PATCH] feat(cresettings): add GatewayConfidentialRelayUserRate ingress limit Adds a GatewayConfidentialRelayUserRate setting (default 100rps, burst 10) so the confidential relay gateway handler in chainlink core can throttle inbound user requests before fan-out to DON nodes. The existing relay limiters only bound node responses, leaving the ingress path unthrottled. Consumed by chainlink core for CL112-03 / PRIV-436 (Sigma Prime audit). --- pkg/settings/cresettings/README.md | 1 + pkg/settings/cresettings/defaults.json | 1 + pkg/settings/cresettings/defaults.toml | 1 + pkg/settings/cresettings/settings.go | 6 ++++++ pkg/settings/cresettings/settings_test.go | 2 ++ 5 files changed, 11 insertions(+) diff --git a/pkg/settings/cresettings/README.md b/pkg/settings/cresettings/README.md index b35fe840b0..2a65d1fdb2 100644 --- a/pkg/settings/cresettings/README.md +++ b/pkg/settings/cresettings/README.md @@ -64,6 +64,7 @@ flowchart GatewayHTTPPerNodeRate[\GatewayHTTPPerNodeRate/]:::rate GatewayConfidentialRelayGlobalRate[\GatewayConfidentialRelayGlobalRate/]:::rate GatewayConfidentialRelayPerNodeRate[\GatewayConfidentialRelayPerNodeRate/]:::rate + GatewayConfidentialRelayUserRate[\GatewayConfidentialRelayUserRate/]:::rate GatewayHTTPActionMtlsRequestRate[\GatewayHTTPActionMtlsRequestRate/]:::rate GatewayHTTPActionMtlsConcurrencyLimit([GatewayHTTPActionMtlsConcurrencyLimit]):::resource end diff --git a/pkg/settings/cresettings/defaults.json b/pkg/settings/cresettings/defaults.json index 9e85fd8747..d6e9903466 100644 --- a/pkg/settings/cresettings/defaults.json +++ b/pkg/settings/cresettings/defaults.json @@ -21,6 +21,7 @@ "GatewayHTTPPerNodeRate": "100rps:100", "GatewayConfidentialRelayGlobalRate": "50rps:10", "GatewayConfidentialRelayPerNodeRate": "10rps:10", + "GatewayConfidentialRelayUserRate": "100rps:10", "GatewayHTTPActionMtlsRequestRate": "every30s:0", "GatewayHTTPActionMtlsConcurrencyLimit": "50", "TriggerRegistrationStatusUpdateTimeout": "0s", diff --git a/pkg/settings/cresettings/defaults.toml b/pkg/settings/cresettings/defaults.toml index ddc1214969..83c0f4d67e 100644 --- a/pkg/settings/cresettings/defaults.toml +++ b/pkg/settings/cresettings/defaults.toml @@ -20,6 +20,7 @@ GatewayHTTPGlobalRate = '500rps:500' GatewayHTTPPerNodeRate = '100rps:100' GatewayConfidentialRelayGlobalRate = '50rps:10' GatewayConfidentialRelayPerNodeRate = '10rps:10' +GatewayConfidentialRelayUserRate = '100rps:10' GatewayHTTPActionMtlsRequestRate = 'every30s:0' GatewayHTTPActionMtlsConcurrencyLimit = '50' TriggerRegistrationStatusUpdateTimeout = '0s' diff --git a/pkg/settings/cresettings/settings.go b/pkg/settings/cresettings/settings.go index 9caee6dc69..f39f7795db 100644 --- a/pkg/settings/cresettings/settings.go +++ b/pkg/settings/cresettings/settings.go @@ -75,6 +75,7 @@ var Default = Schema{ GatewayHTTPPerNodeRate: Rate(rate.Limit(100), 100), GatewayConfidentialRelayGlobalRate: Rate(rate.Limit(50), 10), GatewayConfidentialRelayPerNodeRate: Rate(rate.Limit(10), 10), + GatewayConfidentialRelayUserRate: Rate(rate.Limit(100), 10), GatewayHTTPActionMtlsRequestRate: Rate(rate.Every(30*time.Second), 0), GatewayHTTPActionMtlsConcurrencyLimit: Int(50), TriggerRegistrationStatusUpdateTimeout: Duration(0 * time.Second), @@ -345,6 +346,11 @@ type Schema struct { GatewayHTTPPerNodeRate Setting[config.Rate] GatewayConfidentialRelayGlobalRate Setting[config.Rate] GatewayConfidentialRelayPerNodeRate Setting[config.Rate] + // GatewayConfidentialRelayUserRate bounds inbound user (ingress) requests to the + // confidential relay handler, before they are fanned out to DON nodes. The + // GlobalRate/PerNodeRate limiters above only bound node responses, so without this + // an unauthenticated caller can amplify one request into per-node attestation work. + GatewayConfidentialRelayUserRate Setting[config.Rate] GatewayHTTPActionMtlsRequestRate Setting[config.Rate] GatewayHTTPActionMtlsConcurrencyLimit Setting[int] `unit:"{request}"` TriggerRegistrationStatusUpdateTimeout Setting[time.Duration] diff --git a/pkg/settings/cresettings/settings_test.go b/pkg/settings/cresettings/settings_test.go index 565808d9c0..5457a9c60c 100644 --- a/pkg/settings/cresettings/settings_test.go +++ b/pkg/settings/cresettings/settings_test.go @@ -73,6 +73,7 @@ func TestSchema_Unmarshal(t *testing.T) { "GatewayVaultManagementEnabled": "true", "GatewayConfidentialRelayGlobalRate": "20rps:7", "GatewayConfidentialRelayPerNodeRate": "4rps:2", + "GatewayConfidentialRelayUserRate": "30rps:9", "PerOrg": { "ZeroBalancePruningTimeout": "48h" }, @@ -141,6 +142,7 @@ func TestSchema_Unmarshal(t *testing.T) { assert.False(t, cfg.VaultSignedResponseRequestIDEnabled.DefaultValue) assert.Equal(t, config.Rate{Limit: rate.Limit(20), Burst: 7}, cfg.GatewayConfidentialRelayGlobalRate.DefaultValue) assert.Equal(t, config.Rate{Limit: rate.Limit(4), Burst: 2}, cfg.GatewayConfidentialRelayPerNodeRate.DefaultValue) + assert.Equal(t, config.Rate{Limit: rate.Limit(30), Burst: 9}, cfg.GatewayConfidentialRelayUserRate.DefaultValue) assert.Equal(t, 48*time.Hour, cfg.PerOrg.ZeroBalancePruningTimeout.DefaultValue) assert.Equal(t, 99, cfg.PerOwner.WorkflowExecutionConcurrencyLimit.DefaultValue) assert.Equal(t, 250*config.MByte, cfg.PerWorkflow.WASMMemoryLimit.DefaultValue)