Recipe Name:
Info Leakage: Throwable.printStacktrace leaks valuable program structure information
Description:
Printing a stack trace gives valuable information about software internals, including library/framework names and versions, to an attacker
Level:
warning
Language:
  • java
Tags:
  • security
  • framework specific
  • logging
  • Logger
Documentation

Throwable.printStacktrace leaks valuable program structure information.

Printing a stack trace gives valuable information about the application's internals, including library/framework names and versions, to an attacker. The method printStaceTrace of java.lang.Throwable will result in valuable program information being printed on standard error. Instead, an appropriate logger, such as SLF4J, should be used.

Before
public void printMessages(Throwable e) {
    e.printStackTrace();
    e.printStackTrace(System.err);
    e.printStackTrace(System.out);
}
After
private final static org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(LoggingExample.class);

public void printMessages(Throwable e) {
    LOGGER.error("", e);
    LOGGER.error("", e);
    LOGGER.error("", e);
}
Recipe
id: scw:logging:Logger:printstacktrace
version: 10
metadata:
  name: 'Info Leakage: Throwable.printStacktrace leaks valuable program structure information'
  shortDescription: Printing a stack trace gives valuable information about software internals, including library/framework names and versions, to an attacker
  level: warning
  language: java
  scwCategory: infoexposure:debuginfo
  cweCategory: 200
  enabled: true
  comment: ""
  descriptionFile: Java/Logging/descriptions/ThrowablePrintStacktraceLeaksInfo.html
  tags: security;framework specific;logging;Logger
search:
  methodcall:
    in:
      typeDeclaration:
        without:
          child:
            field:
              name: logger
              type:
                reference:
                  not: java.util.logging.Logger
                checkInheritance: true
    name: printStackTrace
    declaration:
      type: java.lang.Throwable
availableFixes:
- name: Use Logger class
  actions:
  - addField:
      field: private static final java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name }}}.class.getName())
      target: parentClass
  - rewrite:
      to: logger.info({{{ qualifier }}}.getMessage())