JEP draft: JFR: In-Process Data Redaction

OwnerErik Gahlin
TypeFeature
ScopeJDK
StatusDraft
Componenthotspot / jfr
EffortS
DurationS
Created2025/11/30 02:51
Updated2026/02/16 12:57
Issue8372760

Summary

Add in process redaction to JDK Flight Recorder (JFR) to keep sensitive data out of recordings. The feature covers command line arguments and the values of environment variables and system properties specified at startup.

Goals

Non-Goals

Motivation

JFR is a low overhead diagnostics framework integrated into the JVM. It captures information about the runtime and the application and can be used with tools such as jfr and JDK Mission Control. Recordings typically include environment variables, system properties, and command line arguments so users can see how the process was started and configured.

These sources can contain sensitive data. Examples include passwords and tokens in properties, secrets in environment variables, and keys passed as application arguments. Today, such data can appear verbatim in recordings. That creates risk when recordings are shared, archived, or attached to support cases. Built in redaction addresses this while keeping the surrounding context needed for diagnosis.

Description

This feature adds two sub options to -XX:FlightRecorderOptions. They control how arguments and properties are filtered so sensitive content is not stored in recorded events.

Matching is case insensitive. Filters use glob patterns where * and ? are wildcards.

Example

To redact any environment variable or system property named confidential, plus any startup argument that looks like an HTTP URL containing username:password@host, use:

$ export confidential=secret
$ java '-XX:FlightRecorderOptions:redact-key=confidential,redact-argument=http://*:*@*' \
    -XX:StartFlightRecording:filename=recording.jfr \
    -Dconfidential=sensitive \
    -jar application.jar http://john:@smith@example.com/login --verbose

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

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

jdk.JVMInformation {
  startTime = 17:39:02.196 (2026-02-15)
  jvmVersion = "Java HotSpot(TM) 64-Bit Server VM (build 25.0.1+8-LTS-27, mixed mode, sharing)"
  jvmArguments = "-XX:FlightRecorderOptions:redact-key=confidential,redact-argument=[REDACTED]
   -XX:StartFlightRecording:filename=recording.jfr -Dconfidential=[REDACTED]"
  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]"
}

Multiple filters

Multiple filters for a sub option are separated with ;. In the following example, both system properties and environment variables named confidential and sensitive are redacted.

$ java '-XX:FlightRecorderOptions:redact-key=confidential;sensitive' ...

Matching a following argument

Some secrets are passed as a value after an option. To match multiple tokens, use <DELIMITER>. The first pattern matches the option token, and the second pattern matches the following tokens.

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

Loading filters from a file

Filters can be stored in a file with one filter per line. To reference a file, prefix the filename with @.

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

Filter files are read at startup. If a file cannot be read, the JVM fails to start and prints a warning that names the unreadable file. To log that a redaction file is properly loaded, use -Xlog:jfr+redact=debug

Defaults, adding to defaults, and disabling

By default, JFR applies a built in set of filters when redact-key or redact-argument are not specified. To add filters on top of the defaults, prefix the first filter with +. To disable redaction for an option, use none.

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

Default filters (the list may be extended over time):

redact-key defaults:

*auth*;*jaas*config*;*password*;*passwd*;
*pwd*;*passphrase*;*token*;*secret*;
*credential*;*api-key*;*api_key*;*apikey*;
*client-secret*;*client_secret*;*clientsecret*;*private-key*;
*private_key*;*privatekey*

redact-argument defaults:

(all redact-key defaults except *auth*, plus)
--*jaas*config<DELIMITER>*;--*password<DELIMITER>*;
--*passwd<DELIMITER>*;--*pwd<DELIMITER>*;
--*passphrase<DELIMITER>*;--*token<DELIMITER>*;
--*secret<DELIMITER>*;--*credential<DELIMITER>*;
--*api-key<DELIMITER>*;--*api_key<DELIMITER>*;
--*apikey<DELIMITER>*;--*client-secret<DELIMITER>*;
--*client_secret<DELIMITER>*;--*clientsecret<DELIMITER>*;
--*private-key<DELIMITER>*;--*private_key<DELIMITER>*;
--*privatekey<DELIMITER>*

Syntax

Both options accept a semicolon-separated list of filters.

option-value ::= 'none' | filters
 filters      ::= ['+'] filter (';' filter)*
 filter       ::= expression | '@' filename
 glob-pattern ::= character-sequence-with '*' and '?' wildcards (case insensitive)

For redact-key:

expression ::= glob-pattern

For redact-argument:

expression ::= glob-pattern ('<DELIMITER>' glob-pattern)

Alternatives

Risks and Assumptions

With defaults enabled, recordings may differ from earlier releases by showing "[REDACTED]" in affected fields. To preserve prior behavior, users can specify:

-XX:FlightRecorderOptions:redact-argument=none,redact-key=none