This is an automated email from the ASF dual-hosted git repository. luigidemasi pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-kit.git
commit 49161b00eb0fee5547969468c5b1ae41293a38f7 Author: Jinal Sarvaiya <[email protected]> AuthorDate: Fri Nov 6 08:16:29 2026 +0000 fix #100: reject inline-backtick-wrapped stage-result envelopes --- .../camel/kit/ship/controller/ShipStageResult.java | 6 ++++++ .../kit/ship/controller/ShipStageResultTest.java | 23 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java b/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java index 23907b16..40110174 100644 --- a/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java +++ b/kit/camel-kit-core/src/main/java/org/apache/camel/kit/ship/controller/ShipStageResult.java @@ -380,6 +380,8 @@ record ShipStageResult( return result; } + private static final String ENVELOPE_MARKER = "\"materialAmbiguity\""; + private static boolean hasBareJsonStart(String fragment) { int i = 0; int len = fragment.length(); @@ -391,6 +393,10 @@ record ShipStageResult( j++; } if (j < len && fragment.charAt(j) == '`') { + String span = fragment.substring(i + 1, j); + if (span.contains(ENVELOPE_MARKER)) { + return true; + } i = j + 1; continue; } diff --git a/kit/camel-kit-core/src/test/java/org/apache/camel/kit/ship/controller/ShipStageResultTest.java b/kit/camel-kit-core/src/test/java/org/apache/camel/kit/ship/controller/ShipStageResultTest.java index bb0ec226..a1b400cf 100644 --- a/kit/camel-kit-core/src/test/java/org/apache/camel/kit/ship/controller/ShipStageResultTest.java +++ b/kit/camel-kit-core/src/test/java/org/apache/camel/kit/ship/controller/ShipStageResultTest.java @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -507,6 +508,28 @@ class ShipStageResultTest { "fenced then same-line bare correction"); } + @Test + void rejectsInlineBacktickWrappedCorrection() throws Exception { + ObjectNode fenced = result(null, null); + ObjectNode bare = result(null, null); + bare.put("materialAmbiguity", true); + bare.withArray("unansweredQuestions").addObject() + .put("question", "Which retry limit?").putNull("defaultApplied"); + String input = "```json\n" + JSON.writeValueAsString(fenced) + + "\n```\nCorrection, use this instead: `" + JSON.writeValueAsString(bare) + "`"; + assertRejected(Stage.DESIGN, input, + "backtick-wrapped correction envelope"); + } + + @Test + void acceptsHarmlessInlineJsonExample() throws Exception { + ObjectNode valid = result("149-local-controller", null); + String input = "Here is `{\"status\":\"ok\"}` for reference.\n```json\n" + + JSON.writeValueAsString(valid) + "\n```\n"; + ShipStageResult parsed = ShipStageResult.parse(Stage.DISCOVERY, input); + assertNotNull(parsed, "harmless inline JSON example should not cause rejection"); + } + @Test void rejectsArrayWrappedEnvelope() throws Exception { ObjectNode valid = result("149-local-controller", null);
