mirror of
https://github.com/openai/codex.git
synced 2026-04-28 08:34:54 +00:00
107 lines
3.9 KiB
Markdown
107 lines
3.9 KiB
Markdown
# PR #1591: Added mcp-server name validation
|
|
|
|
- URL: https://github.com/openai/codex/pull/1591
|
|
- Author: preetDev004
|
|
- Created: 2025-07-16 16:38:38 UTC
|
|
- Updated: 2025-07-16 23:00:51 UTC
|
|
- Changes: +18/-2, Files changed: 1, Commits: 6
|
|
|
|
## Description
|
|
|
|
This PR implements server name validation for MCP (Model Context Protocol) servers to ensure they conform to the required pattern ^[a-zA-Z0-9_-]+$. This addresses the TODO comment in mcp_connection_manager.rs:82.
|
|
|
|
+ Added validation before spawning MCP client tasks
|
|
+ Invalid server names are added to errors map with descriptive messages
|
|
|
|
I have read the CLA Document and I hereby sign the CLA
|
|
|
|
## Full Diff
|
|
|
|
```diff
|
|
diff --git a/codex-rs/core/src/mcp_connection_manager.rs b/codex-rs/core/src/mcp_connection_manager.rs
|
|
index 6ae1865f16..7cf6762752 100644
|
|
--- a/codex-rs/core/src/mcp_connection_manager.rs
|
|
+++ b/codex-rs/core/src/mcp_connection_manager.rs
|
|
@@ -79,9 +79,19 @@ impl McpConnectionManager {
|
|
|
|
// Launch all configured servers concurrently.
|
|
let mut join_set = JoinSet::new();
|
|
+ let mut errors = ClientStartErrors::new();
|
|
|
|
for (server_name, cfg) in mcp_servers {
|
|
- // TODO: Verify server name: require `^[a-zA-Z0-9_-]+$`?
|
|
+ // Validate server name before spawning
|
|
+ if !is_valid_mcp_server_name(&server_name) {
|
|
+ let error = anyhow::anyhow!(
|
|
+ "invalid server name '{}': must match pattern ^[a-zA-Z0-9_-]+$",
|
|
+ server_name
|
|
+ );
|
|
+ errors.insert(server_name, error);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
join_set.spawn(async move {
|
|
let McpServerConfig { command, args, env } = cfg;
|
|
let client_res = McpClient::new_stdio_client(command, args, env).await;
|
|
@@ -117,7 +127,6 @@ impl McpConnectionManager {
|
|
|
|
let mut clients: HashMap<String, std::sync::Arc<McpClient>> =
|
|
HashMap::with_capacity(join_set.len());
|
|
- let mut errors = ClientStartErrors::new();
|
|
|
|
while let Some(res) = join_set.join_next().await {
|
|
let (server_name, client_res) = res?; // JoinError propagation
|
|
@@ -208,3 +217,10 @@ pub async fn list_all_tools(
|
|
|
|
Ok(aggregated)
|
|
}
|
|
+
|
|
+fn is_valid_mcp_server_name(server_name: &str) -> bool {
|
|
+ !server_name.is_empty()
|
|
+ && server_name
|
|
+ .chars()
|
|
+ .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
|
|
+}
|
|
```
|
|
|
|
## Review Comments
|
|
|
|
### codex-rs/core/src/mcp_connection_manager.rs
|
|
|
|
- Created: 2025-07-16 16:40:53 UTC | Link: https://github.com/openai/codex/pull/1591#discussion_r2210941410
|
|
|
|
```diff
|
|
@@ -79,9 +80,17 @@ impl McpConnectionManager {
|
|
|
|
// Launch all configured servers concurrently.
|
|
let mut join_set = JoinSet::new();
|
|
+ let mut errors = ClientStartErrors::new();
|
|
|
|
for (server_name, cfg) in mcp_servers {
|
|
- // TODO: Verify server name: require `^[a-zA-Z0-9_-]+$`?
|
|
+ // Validate server name before spawning
|
|
+ if !is_valid_server_name(&server_name) {
|
|
+ let error = anyhow::anyhow!("invalid server name '{}': must match pattern ^[a-zA-Z0-9_-]+$", server_name);
|
|
+ errors.insert(server_name, error);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ let server_name_cloned = server_name.clone();
|
|
```
|
|
|
|
> Is this necessary? If we have reached this point, nothing else has taken ownership of `server_name`, correct?
|
|
|
|
### codex-rs/core/src/util.rs
|
|
|
|
- Created: 2025-07-16 16:42:26 UTC | Link: https://github.com/openai/codex/pull/1591#discussion_r2210945426
|
|
|
|
```diff
|
|
@@ -64,3 +64,9 @@ pub fn is_inside_git_repo(config: &Config) -> bool {
|
|
|
|
false
|
|
}
|
|
+
|
|
+pub fn is_valid_server_name(server_name: &str) -> bool {
|
|
```
|
|
|
|
> I don't really like having generic "util" files because it's not clear what goes in there: please keep this in `mcp_connection_manager.rs` since that is the only place it is used. |