Files
codex/prs/bolinfest/PR-1578.md
2025-09-02 15:17:45 -07:00

101 lines
3.4 KiB
Markdown

# PR #1578: Added mcp-server name validation with regex
- URL: https://github.com/openai/codex/pull/1578
- Author: preetDev004
- Created: 2025-07-15 03:50:03 UTC
- Updated: 2025-07-16 16:19:44 UTC
- Changes: +28/-5, Files changed: 4, Commits: 2
## 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/Cargo.toml
- Created: 2025-07-16 15:26:25 UTC | Link: https://github.com/openai/codex/pull/1578#discussion_r2210768032
```diff
@@ -24,7 +24,9 @@ fs2 = "0.4.3"
futures = "0.3"
mcp-types = { path = "../mcp-types" }
mime_guess = "2.0"
+once_cell = "1"
rand = "0.9"
+regex-lite = "0.1"
```
> I know that `regex-lite` is not as heavyweight as the `regex` crate, but it feels like it would be good to avoid adding this dependency for this one feature given that it seems it can be easily avoided. I asked chat for a solution and it gave me:
>
> ```rust
> fn is_valid(s: &str) -> bool {
> !s.is_empty() && s.chars().all(|c| {
> c.is_ascii_alphanumeric() || c == '_' || c == '-'
> })
> }
>
> fn main() {
> let test_cases = ["abc123", "abc_123", "abc-123", "abc$", ""];
>
> for &s in &test_cases {
> println!("{s}: {}", is_valid(s));
> }
> }
> ```
>
> do you want to update this PR or should I just do this in a separate one?