Summary
The MCP find_in_file tool mirrors the unbounded before / after issue from excerpt: only the lower bound (< 0) is validated, leaving the upper bound open to arbitrary client values.
Evidence
src/CodeIndex/Mcp/McpToolHandlers.cs:1087-1095:
var beforeValue = args?["before"]?.GetValue<int>();
if (beforeValue.HasValue && beforeValue.Value < 0)
return CreateToolErrorResponse(id, "before must be greater than or equal to 0");
var before = beforeValue ?? 0;
var afterValue = args?["after"]?.GetValue<int>();
if (afterValue.HasValue && afterValue.Value < 0)
return CreateToolErrorResponse(id, "after must be greater than or equal to 0");
var after = afterValue ?? 0;
When find_in_file matches N lines, each match expands by before + after, so the raw cost is O(matches * (before + after)).
Impact
- Same DoS class as the
excerpt issue but multiplied by match count: 100 matches in one file × before=1000, after=1000 = 200K context lines.
- Worst case can blow past the 1 MB
McpServer.MaxLineLength.
Proposed direction
Share a ClampWindow helper with excerpt. Cap and signal truncation in the response.
Repro env
- Branch:
main @ 2ee912d (release v1.21.0)
Summary
The MCP
find_in_filetool mirrors the unboundedbefore/afterissue fromexcerpt: only the lower bound (< 0) is validated, leaving the upper bound open to arbitrary client values.Evidence
src/CodeIndex/Mcp/McpToolHandlers.cs:1087-1095:When
find_in_filematches N lines, each match expands bybefore + after, so the raw cost isO(matches * (before + after)).Impact
excerptissue but multiplied by match count: 100 matches in one file ×before=1000, after=1000= 200K context lines.McpServer.MaxLineLength.Proposed direction
Share a
ClampWindowhelper withexcerpt. Cap and signal truncation in the response.Repro env
main@ 2ee912d (release v1.21.0)