Repository navigation
feat: enhance HTTP tool parameter parsing - #911
Conversation
- Add support for stringified JSON arrays in headers parameter. - Introduce timeout_secs parameter parsing to accept both numbers and string representations. - Implement save_to parameter parsing to handle empty strings as None. - Update HTTP request handling to incorporate timeout and save_to parameters. - Add unit tests for new parsing functions to ensure correct behavior.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
zmanian
left a comment
There was a problem hiding this comment.
Review: feat: enhance HTTP tool parameter parsing
The overall intent is good -- tolerating LLM-generated stringified parameters is a practical improvement. However, there are several issues that should be addressed before merging.
Issues
1. Security: Recursive parse_headers_param with unbounded depth (Medium)
The new String arm in parse_headers_param deserializes the string into a serde_json::Value and then recursively calls parse_headers_param(Some(&parsed)). If the parsed result is also a String (e.g., "\"[]\"" -- a JSON string containing another JSON string), this recurses again. While serde won't produce infinite depth from a finite input, the recursion depth is data-dependent and not explicitly bounded. Consider either:
- Matching only on
Object/Arrayafter parsing (not calling the full function recursively), or - Adding a comment documenting that recursion terminates because
serde_json::from_stron a JSON string produces aValue::Stringonly if the inner content is a plain string (not parseable further), so one level of recursion is the max in practice.
Actually, re-reading more carefully: if input is "\"hello\"", serde_json::from_str produces Value::String("hello"), and the recursive call hits the String arm again, tries serde_json::from_str("hello") which fails, returning an error. So it terminates -- but with a confusing error message ("headers string must contain valid JSON object/array: ...") for what was originally a doubly-quoted string. A comment explaining the recursion bound would help maintainability.
2. Bug: Timeout error handler still hardcodes 30 seconds
The existing error handler at the request.send().await call reports ToolError::Timeout(Duration::from_secs(30)) regardless of the actual timeout_secs value. Now that timeout is configurable, this should use the parsed value:
ToolError::Timeout(Duration::from_secs(timeout_secs.unwrap_or(30)))3. Missing upper bound on timeout_secs (Security/DoS)
There is no upper bound on the timeout value. An LLM could pass timeout_secs: 999999999 which would create a request that blocks for ~31 years. Add a reasonable cap (e.g., 300 seconds) and reject or clamp values above it.
4. save_to result still references the original save_to variable after .clone() refactor
In the save_to response JSON:
"saved_to": save_to,After the refactor, save_to is now a String (from parse_save_to_param), which is the trimmed version. This is actually fine behavior-wise (trimmed is better), but the .clone() on the next line (save_to.clone()) is unnecessary -- save_to_owned could just be save_to directly since it's already an owned String. Minor nit.
5. Test test_extract_host_from_params_error is misleading
The test name says "error" but it calls requires_approval and discards the result with let _ = .... It doesn't assert anything. This appears to be a smoke test for the specific malformed payload shape, but:
- It should have at least one assertion
- The name should describe what it's testing (e.g.,
test_requires_approval_with_stringified_params) - Without assertions, this test provides no regression protection
6. Validation checklist in PR body shows clippy and tests NOT checked
The PR description shows clippy and test checkboxes are unchecked, with a note that cargo test couldn't run due to proxy issues. This is a concern -- the code should be verified to compile and pass tests before merge.
Minor / Style
- The
method_upperextraction is a nice cleanup (avoids calling.to_uppercase()twice). - The empty-body-string handling is correct and prevents unnecessary body attachment on GET requests.
Summary
The two blocking issues are:
- Timeout error handler hardcodes 30s -- bug that reports wrong timeout to the user
- No upper bound on timeout_secs -- potential DoS vector
The rest are improvements that would make the code more robust and the tests more useful.
…ments - Introduced default and maximum request timeout constants to manage resource usage. - Refactored header parsing logic to separate functions for better readability and maintainability. - Updated timeout handling to ensure it respects the maximum allowed value. - Added unit tests to validate new header parsing functionality.
…able in HTTP tool error handling
zmanian
left a comment
There was a problem hiding this comment.
Solid PR -- the parameter normalization is well-scoped and correctly handles the common LLM-generated shape issues (stringified JSON headers, numeric strings for timeout, empty-string-as-unset). Code quality is good.
Checked:
- No
.unwrap()in production code -- confirmed, only in tests. - Edge cases -- empty strings, null, stringified objects/arrays, malformed JSON all handled with proper error messages.
- Security --
MAX_TIMEOUT_SECScap prevents LLM-controlled DoS via long timeouts. Stringified headers still go through the same validation pipeline (object or array-of-{name,value}).save_tostill goes throughvalidate_save_to_path. No new injection vectors. - Pattern consistency -- follows existing
parse_*_paramextraction style, returns properToolError::InvalidParameters.
Two minor observations (non-blocking):
-
timeout_secs: 0is accepted --Duration::from_secs(0)would make every request fail immediately with a timeout error. Consider a minimum like1or treating0as "use default". Not a security issue, just a usability footgun if the LLM sends it. -
method_uppervsmethod.to_uppercase()--method_upperis computed early but thematchon line ~482 still callsmethod.to_uppercase()again. Could reusemethod_upperthere. Trivial.
LGTM.
* feat: enhance HTTP tool parameter parsing - Add support for stringified JSON arrays in headers parameter. - Introduce timeout_secs parameter parsing to accept both numbers and string representations. - Implement save_to parameter parsing to handle empty strings as None. - Update HTTP request handling to incorporate timeout and save_to parameters. - Add unit tests for new parsing functions to ensure correct behavior. * feat(http): enhance HTTP tool with timeout and header parsing improvements - Introduced default and maximum request timeout constants to manage resource usage. - Refactored header parsing logic to separate functions for better readability and maintainability. - Updated timeout handling to ensure it respects the maximum allowed value. - Added unit tests to validate new header parsing functionality. * refactor(http): replace hardcoded timeout with effective_timeout variable in HTTP tool error handling
* feat: enhance HTTP tool parameter parsing - Add support for stringified JSON arrays in headers parameter. - Introduce timeout_secs parameter parsing to accept both numbers and string representations. - Implement save_to parameter parsing to handle empty strings as None. - Update HTTP request handling to incorporate timeout and save_to parameters. - Add unit tests for new parsing functions to ensure correct behavior. * feat(http): enhance HTTP tool with timeout and header parsing improvements - Introduced default and maximum request timeout constants to manage resource usage. - Refactored header parsing logic to separate functions for better readability and maintainability. - Updated timeout handling to ensure it respects the maximum allowed value. - Added unit tests to validate new header parsing functionality. * refactor(http): replace hardcoded timeout with effective_timeout variable in HTTP tool error handling
Summary
failing on valid intent with invalid typing.
outgoing request.
failures on GET requests.
Change Type
Linked Issue
None
Validation
tools::builtin::http::tests --lib
Security Impact
Low. This change only relaxes input normalization for the existing built-in http tool. It does not broaden
URL allowlists, approval policy, secret injection behavior, or file-write scope. save_to still requires a
validated path under /tmp/.
Database Impact
None
Blast Radius
Touches only the built-in HTTP tool parameter parsing and request construction path. Potential regressions
are limited to:
Core HTTP safety checks, approval behavior, and path validation remain unchanged.
Rollback Plan
Revert the changes in src/tools/builtin/http.rs to restore strict parameter handling. No migrations,
config changes, or data rollback are required.
———
Review track: B