Summary
ProcessDiagramLayoutFactory.parseXml(InputStream) builds a DocumentBuilderFactory with no XXE
protections and parses the BPMN XML of a process definition. Unlike BpmnXMLConverter, this parser
is not covered by any "safe XML" flag, so a DOCTYPE with an external entity in a deployed BPMN
resource is resolved when the process diagram layout is computed. A user able to deploy a process
definition can read arbitrary local files and perform server-side requests (SSRF) from the engine
host, even when the rest of the engine is configured for safe XML handling.
Details
The diagram-layout parser in
modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/diagram/ProcessDiagramLayoutFactory.java
creates a default DocumentBuilderFactory and immediately parses the input stream:
protected Document parseXml(InputStream bpmnXmlStream) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder;
Document bpmnModel;
try {
builder = factory.newDocumentBuilder();
bpmnModel = builder.parse(bpmnXmlStream); // <-- DTD + external entities enabled by default
} catch (Exception e) {
throw new FlowableException("Error while parsing BPMN model.", e);
}
return bpmnModel;
}
None of disallow-doctype-decl, external-general-entities, external-parameter-entities,
load-external-dtd, setExpandEntityReferences(false), or XMLConstants.ACCESS_EXTERNAL_DTD are set.
The JAXP defaults resolve external entities, so a SYSTEM entity reference in the parsed XML is
fetched and inlined into the DOM.
The entry point is RepositoryService.getProcessDiagramLayout(processDefinitionId):
// GetDeploymentProcessDiagramLayoutCmd.execute
InputStream processModelStream = new GetDeploymentProcessModelCmd(processDefinitionId).execute(commandContext);
InputStream processDiagramStream = new GetDeploymentProcessDiagramCmd(processDefinitionId).execute(commandContext);
return new ProcessDiagramLayoutFactory().getProcessDiagramLayout(processModelStream, processDiagramStream);
processModelStream is the raw BPMN resource that was stored at deployment time. Deployment stores
the original bytes, so a <!DOCTYPE ... > block survives in the deployed resource even though the
primary BpmnXMLConverter parse path hardens its own XMLInputFactory. When the layout is later
computed, parseXml re-parses those stored bytes with the unhardened factory and the external entity
fires.
The same unhardened pattern is present in the Flowable 5 compatibility engine at
modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/diagram/ProcessDiagramLayoutFactory.java.
PoC
(available upon request)
Impact
Any principal permitted to deploy a process definition (a modeler/deployer role, not only a full
engine administrator) can embed an external entity that is resolved by the diagram-layout parser. This
yields arbitrary local file disclosure (engine configuration, credentials, key material) and
server-side request forgery against internal network endpoints from the engine host. The parser is not
protected by the enableSafeBpmnXml flag, so safe-XML deployments are still affected. Scope is changed
because the leaked data and outbound requests target resources outside the deploying principal's
authority.
Summary
ProcessDiagramLayoutFactory.parseXml(InputStream)builds aDocumentBuilderFactorywith no XXEprotections and parses the BPMN XML of a process definition. Unlike
BpmnXMLConverter, this parseris not covered by any "safe XML" flag, so a DOCTYPE with an external entity in a deployed BPMN
resource is resolved when the process diagram layout is computed. A user able to deploy a process
definition can read arbitrary local files and perform server-side requests (SSRF) from the engine
host, even when the rest of the engine is configured for safe XML handling.
Details
The diagram-layout parser in
modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/diagram/ProcessDiagramLayoutFactory.javacreates a default
DocumentBuilderFactoryand immediately parses the input stream:None of
disallow-doctype-decl,external-general-entities,external-parameter-entities,load-external-dtd,setExpandEntityReferences(false), orXMLConstants.ACCESS_EXTERNAL_DTDare set.The JAXP defaults resolve external entities, so a
SYSTEMentity reference in the parsed XML isfetched and inlined into the DOM.
The entry point is
RepositoryService.getProcessDiagramLayout(processDefinitionId):processModelStreamis the raw BPMN resource that was stored at deployment time. Deployment storesthe original bytes, so a
<!DOCTYPE ... >block survives in the deployed resource even though theprimary
BpmnXMLConverterparse path hardens its ownXMLInputFactory. When the layout is latercomputed,
parseXmlre-parses those stored bytes with the unhardened factory and the external entityfires.
The same unhardened pattern is present in the Flowable 5 compatibility engine at
modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/diagram/ProcessDiagramLayoutFactory.java.PoC
(available upon request)
Impact
Any principal permitted to deploy a process definition (a modeler/deployer role, not only a full
engine administrator) can embed an external entity that is resolved by the diagram-layout parser. This
yields arbitrary local file disclosure (engine configuration, credentials, key material) and
server-side request forgery against internal network endpoints from the engine host. The parser is not
protected by the
enableSafeBpmnXmlflag, so safe-XML deployments are still affected. Scope is changedbecause the leaked data and outbound requests target resources outside the deploying principal's
authority.