Java 27 JFR Now Auto-Redacts Passwords: Why Your Diagnostic Files Were Leaking Secrets

Java 27 introduces JFR in-process data redaction (JEP 536) that automatically masks sensitive environment variables, system properties, and JVM arguments matching default glob patterns like *password*, *secret*, *token*, and *api*key*, with support for custom patterns via FlightRecorderOptions, though custom JFR events and child processes remain unprotected.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Java 27 JFR Now Auto-Redacts Passwords: Why Your Diagnostic Files Were Leaking Secrets

While troubleshooting a Spring Boot CPU spike, the author captured a JFR recording and realized that JFR files can contain sensitive data such as database passwords, API keys, and tokens passed via environment variables, system properties, or JVM arguments. These recordings are often shared across teams, creating a security risk.

How JFR Captures Secrets

Typical Spring Boot deployments inject secrets through environment variables or -D properties:

export SPRING_DATASOURCE_PASSWORD=order@2026
export REDIS_PASSWORD=redis@2026
export OPENAI_API_KEY=sk-xxxxxxxx
export PAYMENT_SECRET=xxxxxxxx
java -jar order-service.jar

Or via JVM arguments:

java \
  -Dspring.datasource.password=order@2026 \
  -Dpayment.token=abc123456 \
  -jar order-service.jar

JFR events like jdk.InitialEnvironmentVariable, jdk.InitialSystemProperty, and jdk.JVMInformation record these values verbatim.

Java 27 JFR Data Redaction (JEP 536)

Java 27 (released 2026-09-15) adds in-process redaction before JFR data is written. The feature is enabled by default and uses case-insensitive glob patterns to match sensitive keys:

*api*key*
*auth*
*client*secret*
*credential*
*passphrase*
*passwd*
*password*
*private*key*
*pwd*
*secret*
*token*

Matched values are replaced with [REDACTED] in the recording. For example, SPRING_DATASOURCE_PASSWORD = "mysql@2026" becomes SPRING_DATASOURCE_PASSWORD = "[REDACTED]".

Testing the Redaction

The author demonstrates with a minimal Spring Boot app and explicit secrets:

export SPRING_DATASOURCE_PASSWORD='mysql@2026'
export REDIS_PASSWORD='redis@2026'
export OPENAI_API_KEY='sk-test-123456'
export PAYMENT_TOKEN='pay-token-888888'
java \
  -Dmerchant.secret=merchant-123456 \
  -Dorder.debug=true \
  -XX:StartFlightRecording=filename=order.jfr,duration=60s,settings=profile \
  -jar order-service.jar

Then inspect using the jfr CLI:

jfr print --events jdk.InitialEnvironmentVariable order.jfr
jfr print --events jdk.InitialSystemProperty order.jfr
jfr print --events jdk.JVMInformation order.jfr

The output shows redacted values for keys matching default patterns.

Extending Redaction with Custom Patterns

Projects with custom naming conventions (e.g., PAYMENT_SIGN_KEY, MERCHANT_SIGN, INTERNAL_ACCESS) can add patterns via -XX:FlightRecorderOptions. The + prefix is critical: it appends to default rules; omitting it replaces them, potentially removing built-in protection.

# Correct: keep defaults, add custom
-XX:FlightRecorderOptions='redact-key=+*sign*;*internal*access*'

# Dangerous: replaces defaults
-XX:FlightRecorderOptions='redact-key=*sign*'

Rules can also be loaded from a file using @filename.

Redacting Command-Line Arguments

The redact-argument option protects JVM arguments recorded in jdk.JVMInformation. It also uses glob patterns and replaces matched values with [REDACTED]:

java \
  -XX:FlightRecorderOptions='redact-argument=+--merchant-secret=*' \
  --merchant-secret=abcdefg \
  -jar app.jar

Limitations and Boundaries

The author stresses that redaction is best-effort and has clear boundaries:

Only covers jdk.InitialSystemProperty, jdk.InitialEnvironmentVariable, and jdk.JVMInformation events. redact-argument does not protect jdk.ProcessStart (child processes). jdk.InitialSecurityProperty is not covered by redact-key.

Custom JFR events are not auto-redacted. If you define PaymentRequestEvent with fields apiKey and token, their values are recorded as-is. The principle: don't put secrets into custom events in the first place.

Operational Recommendations

Treat JFR files as sensitive diagnostic artifacts — do not share via chat, public drives, Git, or third-party analyzers.

Verify redaction in test environments: set known secrets, record a short JFR, and inspect with jfr print.

Check default patterns with java -XX:FlightRecorderOptions:help.

Remember that heap dumps, logs, and other diagnostic data still require separate handling.

The feature solves a systemic issue: as diagnostic data becomes more detailed for troubleshooting, it increasingly mirrors runtime internal state. Java 27's default redaction adds a safety net without requiring code changes, especially valuable for organizations running hundreds of Spring Boot services.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMSpring Bootsecuritydiagnosticssensitive dataJFRJava Flight RecorderJava 27JEP 536redaction
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.