JFR: In-Process Data Redaction

XMLWordPrintable

    • Type: JEP
    • Resolution: Unresolved
    • Priority: P4
    • None
    • Component/s: hotspot
    • None
    • Erik Gahlin
    • Feature
    • Open
    • jfr
    • JDK
    • S
    • S

      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

      • Provide secure by default redaction to reduce the risk of sensitive data leaving the process.
      • Allow users to opt out of redaction or provide organization specific configurations.

      Non-Goals

      • Redact event data beyond what is available in the jdk.InitialSystemProperty, jdk.InitialEnvironmentVariable, jdk.JVMInformation, and jdk.StringFlag events.

      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.

      • redact-argument applies to command line arguments recorded by:

        • jdk.JVMInformation (fields jvmArguments, jvmFlags, and javaArguments)
        • jdk.StringFlag (the value field when it contains FlightRecorderOptions)
        • the value of the sun.java.command property recorded by jdk.InitialSystemProperty

        The option value is a semicolon-separated list of filters. Each filter is matched against the full field value. If it matches, the field value is replaced with "[REDACTED]".

      • redact-key applies to values recorded by jdk.InitialEnvironmentVariable and jdk.InitialSystemProperty.

        The option value is a semicolon-separated list of filters. Each filter is matched against the key. If it matches, the corresponding value is replaced with "[REDACTED]".

      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

      • Use the jfr scrub command to remove events that contain sensitive data. This is repetitive and error prone. Unredacted artifacts exist until scrubbing completes. Extra copies may also be left in temporary locations if the JVM crashes. If recording data is streamed using FlightRecorderMXBean or jdk.jfr.consumer.RemoteRecordingStream, the events can also leave the host unredacted.

      • Disable events using an option such as -XX:StartFlightRecording:jdk.InitialEnvironmentVariable#enabled=false to prevent sensitive data from being captured. This is cumbersome and it can remove diagnostic context needed for troubleshooting. Built in redaction requires no advance configuration and uses explicit, case insensitive glob matching to remove sensitive data while preserving non sensitive information.

      • Filter data using regular expressions.. In C++, <regex> may throw exceptions, which are not permitted in HotSpot. In Java, regex filtering adds startup cost and allocation, and it complicates extending filtering to new fields or event types in the JVM.

      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
      

            Assignee:
            Erik Gahlin
            Reporter:
            Erik Gahlin
            Erik Gahlin Erik Gahlin
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: