java.lang.security.audit.xxe.saxparserfactory-disallow-doctype-decl-missing.saxparserfactory-disallow-doctype-decl-missing

profile photo of semgrepsemgrep
Author
unknown
Download Count*

DOCTYPE declarations are enabled for this SAXParserFactory. This is vulnerable to XML external entity attacks. Disable this by setting the feature http://apache.org/xml/features/disallow-doctype-decl to true. Alternatively, allow DOCTYPE declarations and only prohibit external entities declarations. This can be done by setting the features http://xml.org/sax/features/external-general-entities and http://xml.org/sax/features/external-parameter-entities to false. NOTE - The previous links are not meant to be clicked. They are the literal config key values that are supposed to be used to disable these features. For more information, see https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory.

Run Locally

Run in CI

Defintion

rules:
  - id: saxparserfactory-disallow-doctype-decl-missing
    severity: ERROR
    metadata:
      cwe:
        - "CWE-611: Improper Restriction of XML External Entity Reference"
      owasp:
        - A04:2017 - XML External Entities (XXE)
        - A05:2021 - Security Misconfiguration
      asvs:
        section: V5 Validation, Sanitization and Encoding
        control_id: 5.5.2 Insecue XML Deserialization
        control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention
        version: "4"
      references:
        - https://semgrep.dev/blog/2022/xml-security-in-java
        - https://semgrep.dev/docs/cheat-sheets/java-xxe/
        - https://blog.sonarsource.com/secure-xml-processor
        - https://xerces.apache.org/xerces2-j/features.html
      category: security
      technology:
        - java
        - xml
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: LOW
      impact: HIGH
      confidence: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - XML Injection
    message: DOCTYPE declarations are enabled for this SAXParserFactory. This is
      vulnerable to XML external entity attacks. Disable this by setting the
      feature `http://apache.org/xml/features/disallow-doctype-decl` to true.
      Alternatively, allow DOCTYPE declarations and only prohibit external
      entities declarations. This can be done by setting the features
      `http://xml.org/sax/features/external-general-entities` and
      `http://xml.org/sax/features/external-parameter-entities` to false. NOTE -
      The previous links are not meant to be clicked. They are the literal
      config key values that are supposed to be used to disable these features.
      For more information, see
      https://semgrep.dev/docs/cheat-sheets/java-xxe/#3a-documentbuilderfactory.
    mode: taint
    pattern-sources:
      - by-side-effect: true
        patterns:
          - pattern-either:
              - pattern: |
                  $FACTORY = SAXParserFactory.newInstance();
              - patterns:
                  - pattern: $FACTORY
                  - pattern-inside: |
                      class $C {
                        ...
                        $V $FACTORY = SAXParserFactory.newInstance();
                        ...
                      }
                  - pattern-not-inside: >
                      class $C {
                        ...
                        $V $FACTORY = SAXParserFactory.newInstance();
                        static {
                          ...
                          $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
                          ...
                        }
                        ...
                      }
                  - pattern-not-inside: >
                      class $C {
                        ...
                        $V $FACTORY = SAXParserFactory.newInstance();
                        static {
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false);
                          ...
                        }
                        ...
                      }
                  - pattern-not-inside: >
                      class $C {
                        ...
                        $V $FACTORY = SAXParserFactory.newInstance();
                        static {
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false);
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
                          ...
                        }
                        ...
                      }
    pattern-sinks:
      - patterns:
          - pattern: $FACTORY.newSAXParser();
    pattern-sanitizers:
      - by-side-effect: true
        pattern-either:
          - patterns:
              - pattern-either:
                  - pattern: >
                      $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl",
                      true);
                  - pattern: >
                      $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities",
                      false);

                      ...

                      $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
                  - pattern: >
                      $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities",
                      false);

                      ...

                      $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false);
              - focus-metavariable: $FACTORY
          - patterns:
              - pattern-either:
                  - pattern-inside: >
                      class $C {
                        ...
                        $T $M(...) {
                          ...
                          $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl",
                          true);
                          ...
                        }
                        ...
                      }
                  - pattern-inside: >
                      class $C {
                        ...
                        $T $M(...) {
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false);
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
                          ...
                        }
                        ...
                      }
                  - pattern-inside: >
                      class $C {
                        ...
                        $T $M(...) {
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
                          ...
                          $FACTORY.setFeature("http://xml.org/sax/features/external-general-entities",false);
                          ...
                        }
                        ...
                      }
              - pattern: $M($X)
              - focus-metavariable: $X
    fix: >
      $FACTORY.setFeature("http://apache.org/xml/features/disallow-doctype-decl",
      true);

      $FACTORY.newSAXParser();
    languages:
      - java

Examples

saxparserfactory-disallow-doctype-decl-missing.java

package example;

import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;


class GoodSAXParserFactory {
    public void GoodSAXParserFactory() throws  ParserConfigurationException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    public void GoodSAXParserFactory2() throws  ParserConfigurationException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    public void GoodSAXParserFactory3() throws  ParserConfigurationException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
        spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    public void GoodSAXParserFactory4() throws  ParserConfigurationException {
        SAXParserFactory factory = XmlUtils.getSecureSAXParserFactory();
        //Deep semgrep could find issues like this
        //ok:saxparserfactory-disallow-doctype-decl-missing
        saxparser = factory.newSAXParser();
    }
}

class BadSAXParserFactory{
    public void BadSAXParserFactory() throws  ParserConfigurationException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        //ruleid:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    public void BadSAXParserFactory2() throws  ParserConfigurationException {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("somethingElse", true);
        //ruleid:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }
}

class GoodSAXParserFactoryStatic {

    private static SAXParserFactory spf = SAXParserFactory.newInstance();

    static {
        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

}

class BadSAXParserFactoryStatic {

    private static SAXParserFactory spf = SAXParserFactory.newInstance();

    static {
        spf.setFeature("not-a-secure-feature", true);
    }

    public void doSomething(){
        //ruleid:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

}

class OneMoreGoodSAXParserFactory {

    public void GoodSAXParserFactory(boolean condition) throws  ParserConfigurationException {
        SAXParserFactory spf = null;
        
        if ( condition ) {
            spf = SAXParserFactor.newInstance();
        } else {
            spf = newFactory();
        }
        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    private SAXParserFactory newFactory(){
        return SAXParserFactory.newInstance();
    }

}

class OneMoreBadSAXParserFactory {

    public void GoodSAXParserFactory(boolean condition) throws  ParserConfigurationException {
        SAXParserFactory spf = null;
        
        if ( condition ) {
            spf = SAXParserFactory.newInstance();
        } else {
            spf = newFactory();
        }
        //ruleid:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    private SAXParserFactory newFactory(){
        return SAXParserFactory.newInstance();
    }


}


class GoodSAXParserFactoryCtr {

    private final SAXParserFactory spf;

    public GoodSAXParserFactoryCtr() throws Exception {
        spf = SAXParserFactory.newInstance();
        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }
}


class GoodSAXParserFactoryCtr2 {
    public void somemethod() throws Exception {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        setFeatures(spf);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    private void setFeatures(SAXParserFactory spf) throws Exception {
        spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    }

}

class GoodSAXParserFactoryCtr3 {
    public void somemethod() throws Exception {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        setFeatures(spf);
        //ok:saxparserfactory-disallow-doctype-decl-missing
        spf.newSAXParser();
    }

    private void setFeatures(SAXParserFactory spf) throws Exception {
        spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
        spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    }

}