Skip to content

fix(cli): json reporter escaping#9256

Merged
ematipico merged 1 commit intomainfrom
fix/json-reporter-escaping
Mar 1, 2026
Merged

fix(cli): json reporter escaping#9256
ematipico merged 1 commit intomainfrom
fix/json-reporter-escaping

Conversation

@ematipico
Copy link
Member

@ematipico ematipico commented Feb 26, 2026

Summary

Bug found when I was testing the JSON reporter in the ecosystem CI

I generated the code with AI. The escaping uses the same code of checklist reporter.

Test Plan

Added a test

Docs

@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

🦋 Changeset detected

Latest commit: 830d6ba

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the A-CLI Area: CLI label Feb 26, 2026
@ematipico ematipico requested review from a team February 26, 2026 23:30
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Walkthrough

This PR adds proper JSON escaping to the Biome CLI's JSON reporter. A private json_escape helper function has been introduced to escape backslashes, quotes, and control characters. The function is applied to suggestion text and report messages during serialization to ensure valid JSON output. A new test case verifies the reporter handles escaped quotes and unusual identifiers correctly.

Possibly related PRs

  • fix(cli): json reporter #9221: Modifies JSON reporter serialisation logic in the same file to affect how suggestion text and report messages are produced.

Suggested labels

A-CLI, A-Diagnostic

Suggested reviewers

  • Netail
  • dyc3
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing JSON reporter escaping. It directly relates to the changeset which adds escaping logic to the JSON reporter.
Description check ✅ Passed The description explains the bug context (found during ecosystem CI testing), discloses AI assistance as required, and mentions the test addition. It relates directly to the JSON reporter escaping fix in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/json-reporter-escaping

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_cli/src/reporter/json.rs`:
- Around line 14-24: The current json_escape function only handles some
characters via chained replace calls and misses many control characters; change
json_escape to iterate over the input chars (replacing the existing chained
replace implementation) and for each char emit the appropriate escape:
keep/backslash-escape '"' and '\\' and map
'\n','\r','\t','\u0008'('\b'),'\u000C'('\f') to their short escapes, and for any
codepoint <= 0x1F produce a "\\u00XX" escape (hex uppercase or lowercase is
fine) so every control character in U+0000..U+001F is encoded; update references
to the function name json_escape only — no other public API changes.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d0b8e6 and 830d6ba.

⛔ Files ignored due to path filters (1)
  • crates/biome_cli/tests/snapshots/main_cases_reporter_json/reports_diagnostics_json_with_escaped_quotes.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (3)
  • .changeset/fix-json-reporter-escaped-quotes.md
  • crates/biome_cli/src/reporter/json.rs
  • crates/biome_cli/tests/cases/reporter_json.rs

Comment on lines +14 to +24
/// Escapes special characters in a string for safe JSON output
fn json_escape(input: &str) -> String {
input
.replace('\\', "\\\\")
.replace('"', "\\\"")
.replace('\n', "\\n")
.replace('\r', "\\r")
.replace('\t', "\\t")
.replace('\x08', "\\b")
.replace('\x0C', "\\f")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Escape every control character (\u0000..\u001F) to guarantee valid JSON.

Line 17-Line 23 cover common escapes, but not all JSON-required control chars. Values containing e.g. \u0000 or \u000B can still break output validity.

Suggested fix
 fn json_escape(input: &str) -> String {
-    input
-        .replace('\\', "\\\\")
-        .replace('"', "\\\"")
-        .replace('\n', "\\n")
-        .replace('\r', "\\r")
-        .replace('\t', "\\t")
-        .replace('\x08', "\\b")
-        .replace('\x0C', "\\f")
+    let mut out = String::with_capacity(input.len());
+    for ch in input.chars() {
+        match ch {
+            '\\' => out.push_str("\\\\"),
+            '"' => out.push_str("\\\""),
+            '\n' => out.push_str("\\n"),
+            '\r' => out.push_str("\\r"),
+            '\t' => out.push_str("\\t"),
+            '\u{08}' => out.push_str("\\b"),
+            '\u{0C}' => out.push_str("\\f"),
+            c if c <= '\u{1F}' => {
+                use std::fmt::Write as _;
+                let _ = write!(out, "\\u{:04X}", c as u32);
+            }
+            c => out.push(c),
+        }
+    }
+    out
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Escapes special characters in a string for safe JSON output
fn json_escape(input: &str) -> String {
input
.replace('\\', "\\\\")
.replace('"', "\\\"")
.replace('\n', "\\n")
.replace('\r', "\\r")
.replace('\t', "\\t")
.replace('\x08', "\\b")
.replace('\x0C', "\\f")
}
/// Escapes special characters in a string for safe JSON output
fn json_escape(input: &str) -> String {
let mut out = String::with_capacity(input.len());
for ch in input.chars() {
match ch {
'\\' => out.push_str("\\\\"),
'"' => out.push_str("\\\""),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
'\u{08}' => out.push_str("\\b"),
'\u{0C}' => out.push_str("\\f"),
c if c <= '\u{1F}' => {
use std::fmt::Write as _;
let _ = write!(out, "\\u{:04X}", c as u32);
}
c => out.push(c),
}
}
out
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_cli/src/reporter/json.rs` around lines 14 - 24, The current
json_escape function only handles some characters via chained replace calls and
misses many control characters; change json_escape to iterate over the input
chars (replacing the existing chained replace implementation) and for each char
emit the appropriate escape: keep/backslash-escape '"' and '\\' and map
'\n','\r','\t','\u0008'('\b'),'\u000C'('\f') to their short escapes, and for any
codepoint <= 0x1F produce a "\\u00XX" escape (hex uppercase or lowercase is
fine) so every control character in U+0000..U+001F is encoded; update references
to the function name json_escape only — no other public API changes.

use camino::{Utf8Path, Utf8PathBuf};

/// Escapes special characters in a string for safe JSON output
fn json_escape(input: &str) -> String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add json_escape() for AnyJsonValue::JsonStringValue(json_string_value(json_string_literal(&location.path))) too since Windows path contains back slash like this(C:\Projects\File\hoge.rs)?

@ematipico ematipico merged commit 65ae4c1 into main Mar 1, 2026
14 checks passed
@ematipico ematipico deleted the fix/json-reporter-escaping branch March 1, 2026 07:19
@github-actions github-actions bot mentioned this pull request Feb 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants