From 430744d0e675e6c015ba74435c67f9bae5e92f6e Mon Sep 17 00:00:00 2001 From: Widthdom Date: Fri, 5 Jun 2026 13:54:49 +0900 Subject: [PATCH] Fix Dockerfile JSON depth limit (#3034) --- changelog.d/unreleased/3034.security.md | 16 ++++++++++++++++ .../Symbols/SymbolExtractor.Dockerfile.cs | 12 +++++++++--- tests/CodeIndex.Tests/SymbolExtractorTests.cs | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 changelog.d/unreleased/3034.security.md diff --git a/changelog.d/unreleased/3034.security.md b/changelog.d/unreleased/3034.security.md new file mode 100644 index 0000000000..44acef423b --- /dev/null +++ b/changelog.d/unreleased/3034.security.md @@ -0,0 +1,16 @@ +--- +category: security +issues: + - 3034 +affected: + - src/CodeIndex/Indexer/Symbols/SymbolExtractor.Dockerfile.cs + - tests/CodeIndex.Tests/SymbolExtractorTests.cs +--- + +## English + +- **Dockerfile JSON-form extraction now enforces a parser depth limit (#3034)** — Dockerfile `VOLUME`, `SHELL`, `COPY`, and `ADD` JSON forms now use extractor-local `JsonDocumentOptions` so deeply nested JSON is rejected before symbol extraction work continues. + +## 日本語 + +- **Dockerfile JSON form の抽出でパーサー深さ制限を適用しました (#3034)** — Dockerfile の `VOLUME`、`SHELL`、`COPY`、`ADD` の JSON form は extractor ローカルの `JsonDocumentOptions` を使うようになり、深くネストした JSON をシンボル抽出処理の継続前に拒否します。 diff --git a/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Dockerfile.cs b/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Dockerfile.cs index dc3533c269..5c7bd1580c 100644 --- a/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Dockerfile.cs +++ b/src/CodeIndex/Indexer/Symbols/SymbolExtractor.Dockerfile.cs @@ -6,6 +6,12 @@ namespace CodeIndex.Indexer; public static partial class SymbolExtractor { + internal const int DockerfileJsonFormMaxDepth = 8; + private static readonly JsonDocumentOptions DockerfileJsonFormDocumentOptions = new() + { + MaxDepth = DockerfileJsonFormMaxDepth, + }; + private static void AddDockerfileAdditionalEnvSymbols( long fileId, string line, @@ -303,7 +309,7 @@ private static void AddDockerfileJsonVolumeSymbols( { try { - using var document = JsonDocument.Parse(body); + using var document = JsonDocument.Parse(body, DockerfileJsonFormDocumentOptions); if (document.RootElement.ValueKind != JsonValueKind.Array) return; @@ -389,7 +395,7 @@ private static void AddDockerfileShellSymbol( try { - using var document = JsonDocument.Parse(body); + using var document = JsonDocument.Parse(body, DockerfileJsonFormDocumentOptions); if (document.RootElement.ValueKind != JsonValueKind.Array) return; @@ -517,7 +523,7 @@ private static bool TryGetDockerfileInstructionBody(string line, string instruct try { - using var document = JsonDocument.Parse(body[jsonStart..]); + using var document = JsonDocument.Parse(body[jsonStart..], DockerfileJsonFormDocumentOptions); if (document.RootElement.ValueKind != JsonValueKind.Array) return null; diff --git a/tests/CodeIndex.Tests/SymbolExtractorTests.cs b/tests/CodeIndex.Tests/SymbolExtractorTests.cs index 7fa9b8cd46..360ab7e0a2 100644 --- a/tests/CodeIndex.Tests/SymbolExtractorTests.cs +++ b/tests/CodeIndex.Tests/SymbolExtractorTests.cs @@ -15277,6 +15277,20 @@ public void Extract_Dockerfile_DetectsJsonAddDestinationPathSymbols() Assert.Single(symbols); } + [Theory] + [InlineData("VOLUME ")] + [InlineData("SHELL ")] + [InlineData("COPY ")] + [InlineData("ADD ")] + public void Extract_Dockerfile_JsonFormsIgnorePayloadsBeyondParserDepthLimit(string prefix) + { + var depth = SymbolExtractor.DockerfileJsonFormMaxDepth + 1; + var content = prefix + new string('[', depth) + "\"/too-deep\"" + new string(']', depth) + "\n"; + var symbols = SymbolExtractor.Extract(1, "dockerfile", content); + + Assert.Empty(symbols); + } + [Fact] public void Extract_Dockerfile_DetectsOnbuildCopyDestinationPathSymbols() {