-
Notifications
You must be signed in to change notification settings - Fork 21
Add OIDC fail-fast validation to TOML config path #3538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -336,6 +336,51 @@ func TestGetAPIKey_ReturnsKey(t *testing.T) { | |||||||||||||||||||||||||||||||||||||||||
| assert.Equal(t, "super-secret-key", cfg.GetAPIKey()) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // TestLoadFromFile_OIDCAuthMissingEnvVar verifies that LoadFromFile returns an error | ||||||||||||||||||||||||||||||||||||||||||
| // when a server uses github-oidc auth but ACTIONS_ID_TOKEN_REQUEST_URL is not set. | ||||||||||||||||||||||||||||||||||||||||||
| // This ensures parity with the JSON stdin config path (Spec §9 Fail-Fast Startup). | ||||||||||||||||||||||||||||||||||||||||||
| func TestLoadFromFile_OIDCAuthMissingEnvVar(t *testing.T) { | ||||||||||||||||||||||||||||||||||||||||||
| t.Setenv("ACTIONS_ID_TOKEN_REQUEST_URL", "") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| path := writeTempTOML(t, ` | ||||||||||||||||||||||||||||||||||||||||||
| [servers.secure] | ||||||||||||||||||||||||||||||||||||||||||
| type = "http" | ||||||||||||||||||||||||||||||||||||||||||
| url = "https://example.com/mcp" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| [servers.secure.auth] | ||||||||||||||||||||||||||||||||||||||||||
| type = "github-oidc" | ||||||||||||||||||||||||||||||||||||||||||
| audience = "https://example.com" | ||||||||||||||||||||||||||||||||||||||||||
| `) | ||||||||||||||||||||||||||||||||||||||||||
| cfg, err := LoadFromFile(path) | ||||||||||||||||||||||||||||||||||||||||||
| require.Error(t, err) | ||||||||||||||||||||||||||||||||||||||||||
| assert.Nil(t, cfg) | ||||||||||||||||||||||||||||||||||||||||||
| assert.Contains(t, err.Error(), "ACTIONS_ID_TOKEN_REQUEST_URL") | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // TestLoadFromFile_OIDCAuthWithEnvVarSet verifies that LoadFromFile succeeds | ||||||||||||||||||||||||||||||||||||||||||
| // when a server uses github-oidc auth and ACTIONS_ID_TOKEN_REQUEST_URL is set. | ||||||||||||||||||||||||||||||||||||||||||
| func TestLoadFromFile_OIDCAuthWithEnvVarSet(t *testing.T) { | ||||||||||||||||||||||||||||||||||||||||||
| t.Setenv("ACTIONS_ID_TOKEN_REQUEST_URL", "https://token.actions.example.com") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| path := writeTempTOML(t, ` | ||||||||||||||||||||||||||||||||||||||||||
| [servers.secure] | ||||||||||||||||||||||||||||||||||||||||||
| type = "http" | ||||||||||||||||||||||||||||||||||||||||||
| url = "https://example.com/mcp" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| [servers.secure.auth] | ||||||||||||||||||||||||||||||||||||||||||
| type = "github-oidc" | ||||||||||||||||||||||||||||||||||||||||||
| audience = "https://example.com" | ||||||||||||||||||||||||||||||||||||||||||
| `) | ||||||||||||||||||||||||||||||||||||||||||
| cfg, err := LoadFromFile(path) | ||||||||||||||||||||||||||||||||||||||||||
| require.NoError(t, err) | ||||||||||||||||||||||||||||||||||||||||||
| require.NotNil(t, cfg) | ||||||||||||||||||||||||||||||||||||||||||
| server := cfg.Servers["secure"] | ||||||||||||||||||||||||||||||||||||||||||
| require.NotNil(t, server) | ||||||||||||||||||||||||||||||||||||||||||
| require.NotNil(t, server.Auth) | ||||||||||||||||||||||||||||||||||||||||||
| assert.Equal(t, "github-oidc", server.Auth.Type) | ||||||||||||||||||||||||||||||||||||||||||
| assert.Equal(t, "https://example.com", server.Auth.Audience) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
| // TestLoadFromFile_AuthOnNonHTTPServerRejected verifies that TOML configs reject | |
| // auth blocks on non-HTTP servers so TOML validation stays aligned with stdin/local rules. | |
| func TestLoadFromFile_AuthOnNonHTTPServerRejected(t *testing.T) { | |
| path := writeTempTOML(t, ` | |
| [servers.local] | |
| command = "docker" | |
| args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] | |
| [servers.local.auth] | |
| type = "github-oidc" | |
| audience = "https://example.com" | |
| `) | |
| cfg, err := LoadFromFile(path) | |
| require.Error(t, err) | |
| assert.Nil(t, cfg) | |
| assert.Contains(t, err.Error(), "auth") | |
| assert.Contains(t, err.Error(), "http") | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LoadFromFile calls validateAuthConfig whenever serverCfg.Auth is non-nil, but it doesn’t first enforce that the server is an HTTP backend. As written, a TOML config can attach auth to stdio/local servers and still pass validation (or fail with an unrelated OIDC env-var error), which is inconsistent with validateStandardServerConfig (stdin path) that rejects auth on non-HTTP servers. Consider checking serverCfg.Type == "http" (and possibly that serverCfg.URL is non-empty) before calling validateAuthConfig, and returning a clear unsupported-field error when auth is set on non-HTTP servers.