Skip to content

fix: avoid format strings in FrontendUtils.console - #25048

Merged
caalador merged 11 commits into
vaadin:mainfrom
hej090224:fix/frontend-utils-console-format
Aug 26, 2026
Merged

fix: avoid format strings in FrontendUtils.console#25048
caalador merged 11 commits into
vaadin:mainfrom
hej090224:fix/frontend-utils-console-format

Conversation

@hej090224

@hej090224 hej090224 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Description

FrontendUtils.console() passed a caller-controlled format parameter
straight into String.format(), which static analysis tools flag as
CWE-134 (uncontrolled format string), since the method's contract does not
guarantee the argument is a compile-time constant.

Additionally, review feedback pointed out that even after removing
String.format(), console(String, String) still let the color and
message arguments be swapped by mistake, since both were plain Strings.

Changes

  • flow-server/.../internal/FrontendUtils.java:
    • The ANSI color String constants (YELLOW, RED, GREEN,
      BRIGHT_BLUE) and ANSI_RESET are replaced by a nested AnsiColor
      enum. Each constant holds its own escape code, and
      AnsiColor.wrap(String message) concatenates the code, the literal
      message, and the reset sequence.
    • console(String format, Object message) is now
      console(AnsiColor ansiColor, String message); its body is
      System.out.print(ansiColor.wrap(message));. The color and message
      arguments can no longer be confused at compile time, and the message is
      never interpreted as a format string.
    • AnsiColor is nested inside FrontendUtils (matching how other
      single-purpose enums are scoped in this package, e.g.
      BrowserLiveReload.Backend); it's public only because the sole
      external caller needs to reference the constants across modules.
    • YELLOW's color code is corrected from 111 (a light blue, not yellow)
      to 220 (a normal warning yellow), per review.
  • vaadin-dev-server/.../AbstractDevServerRunner.java: the three
    FrontendUtils.console(...) call sites now pass
    FrontendUtils.AnsiColor.GREEN/RED instead of the old string
    constants.
  • flow-server/.../internal/FrontendUtilsTest.java: updated to the new
    enum-based API and extended with a test asserting the reset sequence is
    appended exactly once.

Testing

FrontendUtilsTest verifies:

  • a plain message is wrapped with the given color and the reset sequence
  • embedded newlines in the message are preserved exactly
  • messages containing %s, %c, %n, and a literal % are printed
    verbatim rather than being interpreted as format specifiers
  • the reset sequence is appended exactly once

Verification commands run locally:

  • mvn -pl flow-server -am -DskipITs -Dtest=FrontendUtilsTest -Dsurefire.failIfNoSpecifiedTests=false test4/4 passed
  • mvn -pl vaadin-dev-server -am -DskipITs -DskipTests installBUILD SUCCESS (confirms the only caller module compiles against the new AnsiColor-based signature)
  • mvn -pl flow-server spotless:checkBUILD SUCCESS
  • mvn -pl flow-server checkstyle:check → fails, but with the same pre-existing, unrelated parser error in flow-server/.../signals/shared/impl/MutableTreeRevision.java (a record pattern in instanceof that the bundled checkstyle grammar can't parse); this file is untouched by this PR and the failure reproduces on upstream/main without this change.

Fixes #9263

FrontendUtils.console() passed a caller-supplied format string to
String.format(), which static analysis flags as CWE-134. The ANSI color
constants (YELLOW, RED, GREEN, BRIGHT_BLUE) are changed to hold only the
color escape prefix, a new ANSI_RESET constant holds the reset sequence,
and console() now concatenates color, message and reset instead of
formatting the message, so the text is always printed literally.

Fixes vaadin#9263
@cla-assistant

cla-assistant Bot commented Jul 25, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@cla-assistant

cla-assistant Bot commented Jul 25, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@hej090224
hej090224 marked this pull request as ready for review July 25, 2026 16:34
@caalador caalador added the Contribution PRs coming from the community or external to the team label Jul 27, 2026
@mcollovati

Copy link
Copy Markdown
Collaborator

@hej090224 could you please sign the CLA? Otherwise we cannot proceed with this PR.

@hej090224

Copy link
Copy Markdown
Contributor Author

@mcollovati Apologies for the delayed response — I missed the CLA notification. I'll sign the CLA now via the link above.

Comment thread flow-server/src/main/java/com/vaadin/flow/internal/FrontendUtils.java Outdated
console(String, String) let the color and message arguments be swapped
by mistake since both were plain strings. The ANSI color constants
(YELLOW, RED, GREEN, BRIGHT_BLUE) are replaced by a nested AnsiColor
enum holding each color's escape code and reset sequence, so
console(AnsiColor, String) can no longer confuse the two arguments at
compile time. AnsiColor.wrap(String) builds the escaped message via
plain concatenation, same as before.

AnsiColor is nested in FrontendUtils, matching how other enums in this
package (e.g. BrowserLiveReload.Backend) are scoped close to their
single use; it is public only because the sole external caller,
AbstractDevServerRunner in the vaadin-dev-server module, needs to
reference it.

Also corrects YELLOW from color code 111 (a light blue, not yellow) to
220, a normal warning yellow, as suggested in review.

Fixes vaadin#9263

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8EXia4muFka28BmN6niq4
@hej090224

Copy link
Copy Markdown
Contributor Author

Updated (24c2c41) to address @caalador's review:

  • Replaced the ANSI color String constants with a nested AnsiColor enum (console(String, String) -> console(AnsiColor, String)), so the color and message arguments can't be swapped by mistake, and AnsiColor.wrap(message) builds the escaped output.
  • Applied the suggested yellow color code change (111 -> 220).
  • Updated FrontendUtilsTest for the new API and added a test for the reset sequence being appended exactly once.

Tests: FrontendUtilsTest 4/4 passing; full reactor build through vaadin-dev-server succeeds (confirms the only caller compiles against the new signature); spotless:check clean.

Ready for another look whenever convenient.

caalador
caalador previously approved these changes Aug 21, 2026
@mshabarov
mshabarov enabled auto-merge August 21, 2026 08:24
@mshabarov
mshabarov added this pull request to the merge queue Aug 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 21, 2026
@caalador
caalador added this pull request to the merge queue Aug 21, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 21, 2026
@hej090224

Copy link
Copy Markdown
Contributor Author

Hi, the latest GitHub Formatter and Flow Validation workflows are now passing, and the rerun of the TeamCity Gradle Tests also succeeded.

The remaining API-DIFF labeling, Validation, Formatter, and Validation-SlowTests statuses still point to the earlier failed TeamCity builds. Since the PR head has not changed, could the remaining TeamCity checks be rerun when convenient?

Please also let me know if the API-DIFF check requires a maintainer-applied label for the FrontendUtils.console signature change. Thanks!

@caalador
caalador added this pull request to the merge queue Aug 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 25, 2026
Comment thread flow-server/src/main/java/com/vaadin/flow/internal/FrontendUtils.java Outdated
@caalador
caalador enabled auto-merge August 26, 2026 05:57
@caalador
caalador disabled auto-merge August 26, 2026 06:21
@caalador
caalador enabled auto-merge August 26, 2026 06:21
@caalador
caalador added this pull request to the merge queue Aug 26, 2026
Merged via the queue into vaadin:main with commit a8a791d Aug 26, 2026
15 checks passed
@github-project-automation github-project-automation Bot moved this from 🔎Iteration reviews to Done in Vaadin Flow | Hilla | Kits ongoing work Aug 26, 2026
@caalador

Copy link
Copy Markdown
Contributor

Thank you for the contribution.
Finally merged, we need some fine tuning on the setup so we get the javaDocs checked before the merge queue.

Artur- added a commit that referenced this pull request Aug 26, 2026
#25309)

This PR cherry-picks changes from the original PR #25048 to branch 25.2.
---
#### Original PR description
> ## Description
> 
> `FrontendUtils.console()` passed a caller-controlled `format`
parameter
> straight into `String.format()`, which static analysis tools flag as
> CWE-134 (uncontrolled format string), since the method's contract does
not
> guarantee the argument is a compile-time constant.
> 
> Additionally, review feedback pointed out that even after removing
> `String.format()`, `console(String, String)` still let the color and
> message arguments be swapped by mistake, since both were plain
`String`s.
> 
> ## Changes
> 
> - `flow-server/.../internal/FrontendUtils.java`:
>   - The ANSI color `String` constants (`YELLOW`, `RED`, `GREEN`,
> `BRIGHT_BLUE`) and `ANSI_RESET` are replaced by a nested `AnsiColor`
>     enum. Each constant holds its own escape code, and
> `AnsiColor.wrap(String message)` concatenates the code, the literal
>     message, and the reset sequence.
>   - `console(String format, Object message)` is now
>     `console(AnsiColor ansiColor, String message)`; its body is
> `System.out.print(ansiColor.wrap(message));`. The color and message
> arguments can no longer be confused at compile time, and the message
is
>     never interpreted as a format string.
>   - `AnsiColor` is nested inside `FrontendUtils` (matching how other
>     single-purpose enums are scoped in this package, e.g.
>     `BrowserLiveReload.Backend`); it's `public` only because the sole
>     external caller needs to reference the constants across modules.
> - `YELLOW`'s color code is corrected from 111 (a light blue, not
yellow)
>     to 220 (a normal warning yellow), per review.
> - `vaadin-dev-server/.../AbstractDevServerRunner.java`: the three
>   `FrontendUtils.console(...)` call sites now pass
>   `FrontendUtils.AnsiColor.GREEN`/`RED` instead of the old string
>   constants.
> - `flow-server/.../internal/FrontendUtilsTest.java`: updated to the
new
> enum-based API and extended with a test asserting the reset sequence
is
>   appended exactly once.
> 
> ## Testing
> 
> `FrontendUtilsTest` verifies:
> - a plain message is wrapped with the given color and the reset
sequence
> - embedded newlines in the message are preserved exactly
> - messages containing `%s`, `%c`, `%n`, and a literal `%` are printed
>   verbatim rather than being interpreted as format specifiers
> - the reset sequence is appended exactly once
> 
> Verification commands run locally:
> - `mvn -pl flow-server -am -DskipITs -Dtest=FrontendUtilsTest
-Dsurefire.failIfNoSpecifiedTests=false test` → **4/4 passed**
> - `mvn -pl vaadin-dev-server -am -DskipITs -DskipTests install` →
**BUILD SUCCESS** (confirms the only caller module compiles against the
new `AnsiColor`-based signature)
> - `mvn -pl flow-server spotless:check` → **BUILD SUCCESS**
> - `mvn -pl flow-server checkstyle:check` → fails, but with the same
pre-existing, unrelated parser error in
`flow-server/.../signals/shared/impl/MutableTreeRevision.java` (a record
pattern in `instanceof` that the bundled checkstyle grammar can't
parse); this file is untouched by this PR and the failure reproduces on
`upstream/main` without this change.
> 
> Fixes #9263
>

Co-authored-by: 한의준 <fc49854985@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Artur Signell <artur@vaadin.com>
Co-authored-by: caalador <mikael.grankvist@vaadin.com>
Artur- added a commit that referenced this pull request Aug 26, 2026
#25310)

This PR cherry-picks changes from the original PR #25048 to branch 25.1.
---
#### Original PR description
> ## Description
> 
> `FrontendUtils.console()` passed a caller-controlled `format`
parameter
> straight into `String.format()`, which static analysis tools flag as
> CWE-134 (uncontrolled format string), since the method's contract does
not
> guarantee the argument is a compile-time constant.
> 
> Additionally, review feedback pointed out that even after removing
> `String.format()`, `console(String, String)` still let the color and
> message arguments be swapped by mistake, since both were plain
`String`s.
> 
> ## Changes
> 
> - `flow-server/.../internal/FrontendUtils.java`:
>   - The ANSI color `String` constants (`YELLOW`, `RED`, `GREEN`,
> `BRIGHT_BLUE`) and `ANSI_RESET` are replaced by a nested `AnsiColor`
>     enum. Each constant holds its own escape code, and
> `AnsiColor.wrap(String message)` concatenates the code, the literal
>     message, and the reset sequence.
>   - `console(String format, Object message)` is now
>     `console(AnsiColor ansiColor, String message)`; its body is
> `System.out.print(ansiColor.wrap(message));`. The color and message
> arguments can no longer be confused at compile time, and the message
is
>     never interpreted as a format string.
>   - `AnsiColor` is nested inside `FrontendUtils` (matching how other
>     single-purpose enums are scoped in this package, e.g.
>     `BrowserLiveReload.Backend`); it's `public` only because the sole
>     external caller needs to reference the constants across modules.
> - `YELLOW`'s color code is corrected from 111 (a light blue, not
yellow)
>     to 220 (a normal warning yellow), per review.
> - `vaadin-dev-server/.../AbstractDevServerRunner.java`: the three
>   `FrontendUtils.console(...)` call sites now pass
>   `FrontendUtils.AnsiColor.GREEN`/`RED` instead of the old string
>   constants.
> - `flow-server/.../internal/FrontendUtilsTest.java`: updated to the
new
> enum-based API and extended with a test asserting the reset sequence
is
>   appended exactly once.
> 
> ## Testing
> 
> `FrontendUtilsTest` verifies:
> - a plain message is wrapped with the given color and the reset
sequence
> - embedded newlines in the message are preserved exactly
> - messages containing `%s`, `%c`, `%n`, and a literal `%` are printed
>   verbatim rather than being interpreted as format specifiers
> - the reset sequence is appended exactly once
> 
> Verification commands run locally:
> - `mvn -pl flow-server -am -DskipITs -Dtest=FrontendUtilsTest
-Dsurefire.failIfNoSpecifiedTests=false test` → **4/4 passed**
> - `mvn -pl vaadin-dev-server -am -DskipITs -DskipTests install` →
**BUILD SUCCESS** (confirms the only caller module compiles against the
new `AnsiColor`-based signature)
> - `mvn -pl flow-server spotless:check` → **BUILD SUCCESS**
> - `mvn -pl flow-server checkstyle:check` → fails, but with the same
pre-existing, unrelated parser error in
`flow-server/.../signals/shared/impl/MutableTreeRevision.java` (a record
pattern in `instanceof` that the bundled checkstyle grammar can't
parse); this file is untouched by this PR and the failure reproduces on
`upstream/main` without this change.
> 
> Fixes #9263
>

Co-authored-by: 한의준 <fc49854985@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Artur Signell <artur@vaadin.com>
Co-authored-by: caalador <mikael.grankvist@vaadin.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Development

Successfully merging this pull request may close these issues.

FrontendUtils.console(): Non-constant format string in String.format() (CWE-134)

6 participants