Skip to content

Commit 98256c6

Browse files
authored
fix: strip authorization and x-api-key headers in maas-headers-guard (opendatahub-io#422)
Client auth credentials (MaaS API key) were leaking to upstream model pods for internal models (LLMISvc) because apikey-injection skips internal models and nothing else stripped the Authorization header. Strip authorization and x-api-key in maas-headers-guard so they never reach the upstream. For ExternalModels, apikey-injection re-adds the correct provider credential later in the chain.
1 parent a846538 commit 98256c6

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

pkg/plugins/maas-headers-guard/plugin.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ func (p *Plugin) ProcessRequest(ctx context.Context, cycleState *plugin.CycleSta
7070
logger.Info("internal header captured and stripped", "header", key)
7171
}
7272

73+
// Strip client auth credentials so they never reach the upstream model.
74+
// For ExternalModels, apikey-injection re-adds the provider credential later.
75+
// For internal models (LLMISvc), no credential is needed (mTLS handles auth).
76+
request.RemoveHeader("authorization")
77+
request.RemoveHeader("x-api-key")
78+
7379
cycleState.Write(MaaSHeadersKey, captured)
7480

7581
return nil

pkg/plugins/maas-headers-guard/plugin_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ func TestProcessRequest_StripsInternalHeaders(t *testing.T) {
5555
_, hasSub := req.Headers["x-maas-subscription"]
5656
assert.False(t, hasSub, "x-maas-subscription must be stripped")
5757

58+
// Auth headers stripped (must not leak to upstream model)
59+
_, hasAuth := req.Headers["authorization"]
60+
assert.False(t, hasAuth, "authorization must be stripped")
61+
5862
// Non-internal headers preserved
5963
assert.Equal(t, "application/json", req.Headers["content-type"])
60-
assert.Equal(t, "Bearer sk-oai-test", req.Headers["authorization"])
6164

6265
// All values saved in CycleState as a single map
6366
captured, err := plugin.ReadCycleStateKey[map[string]string](cs, MaaSHeadersKey)
@@ -67,6 +70,21 @@ func TestProcessRequest_StripsInternalHeaders(t *testing.T) {
6770
assert.Equal(t, "premium", captured["x-maas-subscription"])
6871
}
6972

73+
func TestProcessRequest_StripsXApiKey(t *testing.T) {
74+
instance, _ := Factory("test", nil, nil)
75+
cs := plugin.NewCycleState()
76+
req := requesthandling.NewInferenceRequest()
77+
req.Headers["x-api-key"] = "sk-oai-test"
78+
req.Headers["content-type"] = "application/json"
79+
80+
err := instance.(*Plugin).ProcessRequest(context.Background(), cs, req)
81+
require.NoError(t, err)
82+
83+
_, hasKey := req.Headers["x-api-key"]
84+
assert.False(t, hasKey, "x-api-key must be stripped")
85+
assert.Equal(t, "application/json", req.Headers["content-type"])
86+
}
87+
7088
func TestProcessRequest_NoInternalHeaders(t *testing.T) {
7189
instance, _ := Factory("test", nil, nil)
7290
cs := plugin.NewCycleState()

0 commit comments

Comments
 (0)