Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1968,6 +1968,9 @@ server over stdio. It reuses the existing CodeIndex database and exposes
`initialize`, `workspace/symbol`, `textDocument/documentSymbol`,
`textDocument/definition`, and `textDocument/references` for editors that can
launch an arbitrary LSP command but do not speak MCP.
Incoming `textDocument.uri` values are rejected before URI parsing when they
exceed 4096 characters, matching the MCP resource URI limit and keeping error
responses bounded.

Tool results include structured JSON in `structuredContent` plus a short text summary in `content`, so AI tools can parse typed data without scraping large text blocks.

Expand Down Expand Up @@ -4230,6 +4233,8 @@ cdidxには**MCP(Model Context Protocol)サーバー**が組み込まれて
任意の LSP command を起動できるが MCP には対応していない editor 向けに
`initialize`、`workspace/symbol`、`textDocument/documentSymbol`、
`textDocument/definition`、`textDocument/references` を公開します。
受信した `textDocument.uri` は 4096 文字を超える場合、URI parse の前に拒否されます。
これは MCP resource URI の上限と揃えており、エラー応答が過大にならないようにします。

ツール結果は `structuredContent` に構造化JSON、`content` に短い要約テキストを返すため、AIツールは巨大なテキストをパースせずに型付きデータを扱えます。

Expand Down
17 changes: 17 additions & 0 deletions changelog.d/unreleased/3129.security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
category: security
issues:
- 3129
affected:
- src/CodeIndex/Lsp/LspServer.cs
- tests/CodeIndex.Tests/LspServerTests.cs
- USER_GUIDE.md
---

## English

- **LSP text-document URIs are length-capped before parsing (#3129)** — LSP handlers now reject oversized `textDocument.uri` values before URI parsing or path normalization and keep the JSON-RPC error bounded.

## 日本語

- **LSP の text-document URI を parse 前に長さ制限するようになりました (#3129)** — LSP handler は過大な `textDocument.uri` を URI parse や path normalization の前に拒否し、JSON-RPC error を bounded に保ちます。
5 changes: 5 additions & 0 deletions src/CodeIndex/Lsp/LspServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Text.Json.Nodes;
using CodeIndex.Cli;
using CodeIndex.Database;
using CodeIndex.Mcp;
using CodeIndex.Models;

namespace CodeIndex.Lsp;
Expand All @@ -15,6 +16,7 @@ internal sealed class LspServer : IDisposable
internal const int MaxLspFrameBytes = 8 * 1024 * 1024;
internal const int MaxLspHeaderLineBytes = 8 * 1024;
internal const int MaxPositionDocumentBytes = 4 * 1024 * 1024;
internal const int MaxTextDocumentUriChars = McpBoundedText.MaxResourceUriChars;
internal const int MaxJsonDepth = 32;
private const int JsonRpcInvalidParamsCode = -32602;
private const int JsonRpcInternalErrorCode = -32603;
Expand Down Expand Up @@ -480,6 +482,9 @@ private static string GetDocumentPath(JsonElement root)
var uri = GetString(root, "params", "textDocument", "uri");
if (string.IsNullOrWhiteSpace(uri))
throw new ArgumentException("textDocument.uri is required.");
if (uri.Length > MaxTextDocumentUriChars)
throw new ArgumentException(
$"textDocument.uri is too long. Max length is {MaxTextDocumentUriChars} characters; actual length is {uri.Length}.");
return UriToPath(uri);
}

Expand Down
37 changes: 37 additions & 0 deletions tests/CodeIndex.Tests/LspServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,43 @@ public void HandleMessage_DocumentSymbol_ResolvesDuplicateBasenamesByRelativePat
}
}

[Fact]
public void HandleMessage_DocumentSymbol_RejectsOversizedTextDocumentUri_Issue3129()
{
var projectRoot = TestProjectHelper.CreateTempProject("cdidx_lsp_document_symbol_long_uri");
try
{
var dbPath = TestProjectHelper.CreateProjectDb(projectRoot);
using var db = new DbContext(dbPath);
using var server = new LspServer(new DbReader(db), "1.2.3", ProgramRunner.CreateDefaultJsonOptions(), projectRoot);
var oversizedUri = "file:///" + new string('a', LspServer.MaxTextDocumentUriChars);
var request = JsonSerializer.Serialize(new
{
jsonrpc = "2.0",
id = 3129,
method = "textDocument/documentSymbol",
@params = new
{
textDocument = new { uri = oversizedUri },
},
});

var response = server.HandleMessage(request);

Assert.NotNull(response);
var error = response!["error"]!;
Assert.Equal(-32602, error["code"]!.GetValue<int>());
var message = error["message"]!.GetValue<string>();
Assert.Equal("Invalid params", message);
Assert.True(message.Length < 120);
Assert.DoesNotContain(oversizedUri, message, StringComparison.Ordinal);
}
finally
{
TestProjectHelper.DeleteDirectory(projectRoot);
}
}

[Fact]
public void HandleMessage_Definition_ReturnsLocationForTokenAtPosition()
{
Expand Down
Loading