Visitar URL original
JEP 536: JFR In-Process Data Redaction

JEP 536: JFR In-Process Data Redaction

OwnerErik Gahlin
TypeFeature
ScopeJDK
StatusClosed / Delivered
Release27
Componenthotspot / jfr
Discussionhotspot dash jfr dash dev at openjdk dot org
EffortM
DurationM
Reviewed byMarkus Grönlund, Vladimir Kozlov
Endorsed byMikael Vidstedt
Created2025/11/30 02:51
Updated2026/08/18 21:08
Issue8372760

Summary

Enhance JDK Flight Recorder (JFR) to redact command-line arguments and the initial values of environment variables and system properties in recordings. Redact this data before it leaves the process, so that sensitive information does not leak.

Motivation

JFR is a low-overhead diagnostics framework integrated into the HotSpot JVM. It writes information about the runtime and the application into timestamped events in a recording file, for later analysis by tools such as the jfr command and JDK Mission Control.

JFR recording files typically include events that report command-line arguments and the values of environment variables and system properties, so that you can see how the process was started and configured. These events can therefore contain sensitive data, such as secrets in command-line arguments, access tokens in environment variables, and passwords in system properties. Today, this data appears verbatim in recording files, which risks leaking sensitive information when recordings are shared, archived, or included in support cases.

For example, you might start an application with JFR enabled like so:

$ export ACCESS_TOKEN=SECRET_TOKEN
$ java -XX:StartFlightRecording:filename=dump.jfr \
       -Xmx2G \
       -Djavax.net.ssl.keyStorePassword=SECRET_PASSWORD \
       -jar application.jar \
      --dbpassword ANOTHER_SECRET_PASSWORD

The resulting recording file dump.jfr contains events that reveal all three of the secret values:

In-process data redaction would prevent this leakage while preserving non-sensitive information needed for troubleshooting, such as the maximum heap size (-Xmx2G).

Description

JFR will now redact many kinds of sensitive information by default, without any additional configuration.

You can explicitly select the information that JFR should redact via new sub-options of the existing command-line option -XX:FlightRecorderOptions. Each sub-option specifies one or more filters that select the command-line arguments, environment variables, and system properties to be redacted.

Matching is case-insensitive. Filters use glob patterns, where * and ? are wildcards. If a filter matches an argument or a key, the argument or the key’s value is recorded in the event as [REDACTED]. Multiple filters are separated with semicolons (;), and are evaluated in the given order. When a filter matches an argument, the matched argument is redacted and evaluation continues with the next argument. Multiple sub-options of -XX:FlightRecorderOptions are separated by commas.

For example, to redact any environment variable or system property named confidential or CONFIDENTIAL, plus any command-line argument that looks like a URL containing a username and password (i.e., username:password@host), use:

$ export CONFIDENTIAL=SOME_SECRET
$ java -XX:FlightRecorderOptions:'redact-key=confidential,redact-argument=https://*:*@*' \
       -XX:StartFlightRecording:filename=dump.jfr \
       -Dconfidential=ANOTHER_SECRET \
       -jar application.jar https://john:YET_ANOTHER_SECRET@example.com/login --verbose

To verify that sensitive information has been redacted, use jfr print:

$ jfr print \
      --events InitialSystemProperty,JVMInformation,StringFlag,InitialEnvironmentVariable \
      dump.jfr

jdk.JVMInformation {
  startTime = 17:39:02.196 (2026-02-15)
  jvmVersion = "Java HotSpot(TM) 64-Bit Server VM"
  jvmArguments = "-Dconfidential=[REDACTED]
   -XX:FlightRecorderOptions:redact-key=confidential,redact-argument=[REDACTED]
   -XX:StartFlightRecording:filename=dump.jfr"
  jvmFlags = "N/A"
  javaArguments = "-jar application.jar [REDACTED] --verbose"
  jvmStartTime = 17:39:02.050 (2026-02-15)
  pid = 43671
}

jdk.InitialSystemProperty {
  startTime = 17:39:02.196 (2026-02-15)
  key = "confidential"
  value = "[REDACTED]"
}

jdk.InitialSystemProperty {
  startTime = 17:39:02.196 (2026-02-15)
  key = "sun.java.command"
  value = "-jar application.jar [REDACTED] --verbose"
}

jdk.StringFlag {
  startTime = 17:39:02.196 (2026-02-15)
  name = "FlightRecorderOptions"
  value = "redact-key=confidential,redact-argument=[REDACTED]"
  origin = "Command line"
}

jdk.InitialEnvironmentVariable {
  startTime = 17:39:02.244 (2026-02-15)
  key = "CONFIDENTIAL"
  value = "[REDACTED]"
}

To debug redact-argument and redact-key filter matching, start the JVM with the command-line option -Xlog:jfr+redact=debug to identify which command-line arguments, environment variables, and system properties are redacted.

Matching multiple command-line arguments

Sometimes, a command-line argument names an option whose value is expressed in the next argument; for example, --password SENSITIVE. Redacting --password alone would not be sufficient, and matching against SENSITIVE itself would require revealing something about SENSITIVE in the filter, thereby weakening its confidentiality.

To handle this, a filter can match a sequence of command-line arguments, separated by whitespace. For example, this filter redacts any argument named --password, together with the next argument:

$ java -XX:FlightRecorderOptions:'redact-argument=--password *' ...

To match three arguments, add another space and another asterisk:

$ java -XX:FlightRecorderOptions:'redact-argument=--password * *' ...

Loading filters from a file

To avoid overly long command lines, JFR can load redaction filters from a file. This enables filter lists to be reused across deployments, and allows filters to be updated without changing JVM startup options. Filter files contain one filter per line; trailing whitespace is ignored.

To specify a filter file on the command line, prefix the filename with @:

$ java '-XX:FlightRecorderOptions:redact-argument=@args.txt,redact-key=@keys.txt' ...

JFR reads filter files at JVM startup. If a file cannot be read, the JVM prints an error message identifying the file and then exits. To check that a filter file is loaded successfully, use -Xlog:jfr+redact=debug.

The same filter file may be used for both the redact-argument and redact-key sub-options, if appropriate.

Default filters

If the redact-key sub-option is not specified, JFR uses this default filter list for key-value pairs:

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

If the redact-argument sub-option is not specified, JFR uses this default filter list for command-line arguments:

-*api*key *
-*client*secret *
-*credential *
-*jaas*config *
-*passphrase *
-*passwd *
-*password *
-*private*key *
-*pwd *
-*secret *
-*token *
*api*key*
*client*secret*
*credential*
*jaas*config*
*passphrase*
*passwd*
*password*
*private*key*
*pwd*
*secret*
*token*

The default filter list for redact-argument is similar to that for redact-key, except that

Returning to our initial example:

$ export ACCESS_TOKEN=SECRET_TOKEN
$ java -XX:StartFlightRecording:filename=dump.jfr \
       -Xmx2G \
       -Djavax.net.ssl.keyStorePassword=SECRET_PASSWORD \
       -jar application.jar \
      --dbpassword ANOTHER_SECRET_PASSWORD

JFR redacts:

Adding to the default filters

To include the default filters when you specify your own filters, prefix the first filter with +:

$ java -XX:FlightRecorderOptions:'redact-key=+confidential;secret;@keys.txt' ...

Disabling redaction

To disable all redaction, specify none:

$ java -XX:FlightRecorderOptions:'redact-argument=none' ...

Syntax

The syntax of filter lists is:

filter-list  ::= 'none' | filters
 filters      ::= ['+'] filter (';' filter)*
 filter       ::= expression | '@' filename
 glob-pattern ::= characters (including '*' and '?' wildcards), matched case-insensitively

For redact-key:

expression ::= glob-pattern

For redact-argument:

expression ::= glob-pattern (' ' glob-pattern)*

Alternatives

Risks and Assumptions

In the default redaction mode, JFR recordings may differ from those created with previous releases since they will contain [REDACTED] in affected fields. To revert to the past behavior, specify:

$ java -XX:FlightRecorderOptions:'redact-argument=none,redact-key=none' ...