feat(mcp): support custom HTTP headers for non-OAuth MCP servers (#639)#704
feat(mcp): support custom HTTP headers for non-OAuth MCP servers (#639)#704reidliu41 wants to merge 1 commit intonearai:mainfrom
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances IronClaw's compatibility by introducing the capability to configure and utilize custom HTTP headers for MCP server connections. This change broadens the range of supported authentication mechanisms beyond OAuth, enabling seamless interaction with various internal services and browser-use cases that rely on static header-based authentication. The implementation includes robust handling of header parsing, validation, and intelligent conflict resolution for Authorization headers, ensuring both functionality and security. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces support for custom HTTP headers for MCP servers. While the implementation includes robust validation and masking of sensitive header values in CLI output, a critical security concern was identified regarding the plaintext storage of these headers in configuration files and the database. It is strongly recommended to encrypt these headers using the existing SecretsStore or ensure restricted filesystem permissions for configuration files, aligning with best practices for handling sensitive tokens. Additionally, a minor suggestion is provided to improve code readability and maintainability in the header processing logic.
| /// Used for MCP servers that require non-OAuth authentication | ||
| /// (e.g., `X-API-Key`, `Authorization: Bearer <static-token>`). | ||
| #[serde(default, skip_serializing_if = "Option::is_none")] | ||
| pub headers: Option<HashMap<String, String>>, |
There was a problem hiding this comment.
Insecure Storage of Sensitive Custom Headers
Severity: Medium
Sub-category: Insecure Data Handling
Description:
Custom HTTP headers provided via the --header flag are stored in plaintext in the mcp-servers.json configuration file and the database settings table. These headers are intended for authentication (e.g., Authorization: Bearer <token>) and frequently contain sensitive API keys or session tokens. Storing them in plaintext increases the risk of credential theft if the configuration file or database is accessed by unauthorized users or compromised. While the application correctly masks these values when displaying them in the terminal, the underlying storage remains unencrypted.
Impact:
An attacker with local access to the user's filesystem or access to the database can retrieve sensitive API keys and tokens, potentially gaining unauthorized access to the associated MCP servers and services.
Remediation:
Sensitive headers should be stored in the encrypted SecretsStore instead of the plaintext configuration. Alternatively, the application should ensure that the mcp-servers.json file is created with restricted file permissions (e.g., 0600 on Unix-like systems) to prevent other users on the same machine from reading its contents.
References
- This rule highlights the necessity of supporting custom headers for service-specific requirements, which often involve sensitive authentication tokens. Consequently, the secure storage and handling of these headers are paramount to prevent credential leakage.
| let has_custom_auth = if let Some(ref config) = self.server_config | ||
| && config.has_custom_headers() | ||
| { | ||
| let has_auth = config.has_custom_auth_header(); | ||
| if let Some(ref headers) = config.headers { | ||
| for (name, value) in headers { | ||
| // Headers were validated at config time (CRLF-safe) | ||
| req_builder = req_builder.header(name.as_str(), value.as_str()); | ||
| } | ||
| } | ||
| has_auth | ||
| } else { | ||
| false | ||
| }; |
There was a problem hiding this comment.
This block for adding custom headers and checking for a custom Authorization header is a bit complex, as it mixes a side effect (modifying req_builder) inside an expression. This can be refactored for better readability and maintainability by separating the action of adding headers from the check for the authorization header.
let has_custom_auth = if let Some(config) = self.server_config.as_ref() {
if let Some(headers) = &config.headers {
for (name, value) in headers {
// Headers were validated at config time (CRLF-safe)
req_builder = req_builder.header(name.as_str(), value.as_str());
}
config.has_custom_auth_header()
} else {
false
}
} else {
false
};
Many MCP servers (Browser-Use, internal services) authenticate via
static HTTP headers rather than OAuth. Previously these servers could
not be connected because IronClaw only supported the OAuth flow.
Add a
headersfield to McpServerConfig that lets users declarearbitrary HTTP headers injected into every MCP request. Key design
decisions:
has_custom_headers()is independent ofrequires_auth()soexisting OAuth semantics are untouched
auth header injection
injection
--header "Name:Value"arg,mcp testheader-only passthrough,and
mcp list --verbosevalue maskingUsage:
ironclaw mcp add browser-use https://api.browser-use.com
--header "Authorization:Bearer sk-xxx"
Fixes #639