Version: 2.1.0
This page describes the security measures built into FreeXmlToolkit to protect you from XML-based attacks.
When working with XML files, there are several potential security risks - especially when processing untrusted documents or stylesheets. FreeXmlToolkit includes built-in protections against these common attack vectors:
| Protection | What It Prevents |
|---|---|
| XXE Protection | Malicious files reading data from your computer |
| XSLT/XQuery Extension Security | Untrusted stylesheets running code on your system |
| SSRF Protection | Documents accessing your internal network |
| Path Traversal Protection | Files accessing restricted system directories |
| XPath Injection Protection | Malicious input breaking XPath queries |
| Update Integrity Verification | Tampered or man-in-the-middle update downloads |
These protections work automatically in the background - you do not need to configure them for normal use.
XXE is a type of attack where a malicious XML document tries to read files from your computer or access network resources. This happens through special "entity" declarations in the XML that reference external files.
This is what a dangerous XML file might look like (FreeXmlToolkit blocks this):
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY steal SYSTEM "file:///etc/passwd">
]>
<data>&steal;</data>If processed without protection, this could expose sensitive files from your computer.
| Attack Type | Description | Status |
|---|---|---|
| External file access | Reading local files via file:// URIs |
Blocked |
| External DTD loading | Loading DTD definitions from remote servers | Blocked |
| Parameter entities | Using %entity; to include external content |
Blocked |
| Entity expansion bombs | "Billion laughs" denial-of-service attacks | Limited |
All XML parsing in FreeXmlToolkit uses secure configurations that:
- Disable external general entities
- Disable external parameter entities
- Disable external DTD loading
- Limit entity expansion
Normal XML files work without issues. You can:
- Open and edit any XML file
- Validate against XSD schemas
- Transform with XSLT stylesheets
- Work with XML that contains internal (non-external) entities
DTDs with external references are not resolved. If you have an XML file that relies on an external DTD for entity definitions, those entities will appear as empty or cause parsing to fail. This is intentional for security.
XSLT 3.0 and XQuery can include "extension functions" that call Java code directly from your stylesheet. While this is powerful for advanced users, it can be dangerous if you process untrusted stylesheets.
This XSLT tries to execute system commands (FreeXmlToolkit blocks this by default):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="java:java.lang.Runtime">
<xsl:template match="/">
<xsl:variable name="runtime" select="rt:getRuntime()"/>
<xsl:variable name="proc" select="rt:exec($runtime, 'whoami')"/>
</xsl:template>
</xsl:stylesheet>| Extension Type | Description | Default Status |
|---|---|---|
Java namespace (java:) |
Direct calls to Java classes | Blocked |
| Reflexive extensions | Runtime method invocation | Blocked |
| External functions | Custom extension functions | Blocked |
FreeXmlToolkit uses Saxon for XSLT/XQuery processing. By default, the ALLOW_EXTERNAL_FUNCTIONS feature is disabled, preventing stylesheets from executing arbitrary Java code.
If you need to use Java extensions in your XSLT transformations:
- Open Settings (gear icon at the bottom of the activity bar)
- Find the PARSER card
- Enable Allow XSLT extension functions and click Save
Warning: Only enable this if you trust all XSLT stylesheets you will process. Malicious stylesheets could:
- Read files from your computer
- Execute system commands
- Access network resources
- Modify or delete files
The setting is stored as:
security.xslt.allow.extensions=true
When extensions are enabled, you will see a warning message in the application log.
SSRF attacks trick an application into making requests to internal network resources. In XML processing, this can happen when schemas or stylesheets reference URLs.
When loading remote schemas (via xs:import or xs:include with HTTP URLs), FreeXmlToolkit blocks access to:
| Address Type | Examples | Why Blocked |
|---|---|---|
| Localhost | 127.0.0.1, localhost, ::1 |
Prevents access to local services |
| Private networks (Class A) | 10.0.0.0 - 10.255.255.255 |
Blocks internal network access |
| Private networks (Class B) | 172.16.0.0 - 172.31.255.255 |
Blocks internal network access |
| Private networks (Class C) | 192.168.0.0 - 192.168.255.255 |
Blocks internal network access |
| Link-local addresses | 169.254.0.0 - 169.254.255.255 |
Blocks auto-configured addresses |
| Cloud metadata endpoints | 169.254.169.254 |
Blocks AWS/Azure/GCP metadata |
| Multicast addresses | Various | Blocks broadcast addresses |
| Address Type | Examples | Status |
|---|---|---|
| Public internet URLs | https://www.w3.org/2001/XMLSchema.xsd |
Allowed |
| Local file URLs | file:///path/to/schema.xsd |
Allowed |
| Only HTTP/HTTPS | http://, https:// |
Other protocols blocked |
Public schemas work normally. You can reference standard schemas from W3C and other public sources.
Internal network schemas are blocked. If you need to load schemas from:
- Your company's internal server (e.g.,
http://192.168.1.100/schemas/) - Localhost development servers (e.g.,
http://localhost:8080/)
You should:
- Download the schema files to your local machine
- Reference them using file paths or
file://URLs - Place them in the same directory as your XML files for relative references
When an imported schema file cannot be found locally or through the Schema Library and
XML catalogs, the toolkit can download it from the import's schemaLocation URL or its
namespace URL (see
Automatic Resolution of Imported Schemas).
These downloads go through the same SSRF protection: only public http/https addresses are
contacted, and the downloaded content is verified to be a real XML Schema before it is used.
Downloaded schemas are cached in ~/.freeXmlToolkit/cache/schemas/ only - nothing is ever
written into your schema's folder, and your schema file is never rewritten. To disable
remote downloads entirely, start the application with the system property
-Dfxt.schema.namespaceFallback=false.
Path traversal attacks use special characters like ../ to access files outside the intended directory. This could allow a malicious document to read or write to sensitive system locations.
| Protection | Description |
|---|---|
| Excessive parent traversals | More than 5 levels of ../ are flagged |
| System directory access | Writes to /etc, /bin, C:\Windows, etc. |
| Encoded sequences | URL-encoded traversals like %2e%2e/ |
| Double-encoded sequences | %252e and similar bypass attempts |
| Null byte injection | Paths containing \0 characters |
| Symbolic link escapes | Following symlinks outside base directories |
Windows:
C:\Windows\C:\Program Files\C:\ProgramData\
Linux/macOS:
/etc//bin/,/sbin//usr/bin/,/usr/sbin//var//root//boot/
Path validation applies to:
- Schema includes (
xs:include,xs:importwith relative paths) - Linked file detection (auto-linking in the unified editor)
- Export paths (saving output files)
- Any relative file references in XML documents
Normal file operations work fine. You can:
- Open files anywhere on your computer
- Save files to your documents folder
- Use relative paths within your project directories
Suspicious paths are blocked. If you see a path traversal warning, check that your schema or stylesheet references do not contain unusual ../ sequences or try to access system directories.
XPath injection is similar to SQL injection - it happens when user input is inserted directly into XPath queries without proper escaping. This could allow malicious input to modify the query's behavior.
When you use the XPath/XQuery snippet system with parameters, all parameter values are automatically escaped before being inserted into queries.
| Input Contains | Escape Method |
|---|---|
| No quotes | Wrapped in single quotes: 'value' |
| Single quotes only | Wrapped in double quotes: "value" |
| Double quotes only | Wrapped in single quotes: 'value' |
| Both quote types | Uses concat() function for safe combination |
If you have a snippet with parameter ${searchTerm} and the user enters:
O'Brien "Bob"
The system generates:
concat('O', "'", 'Brien "Bob"')
This prevents the user input from breaking out of the string literal and modifying the query structure.
This protection is automatic and transparent. You do not need to do anything special - just use the parameter syntax ${paramName} in your snippets, and values will be properly escaped.
When FreeXmlToolkit downloads an application update, it verifies that the downloaded file is exactly the one published by the official release - and was not tampered with in transit (for example by a man-in-the-middle on an untrusted network) or swapped on the download server.
- The update package (a ZIP) is downloaded from the official GitHub release over HTTPS.
- Before the package is extracted or launched, its SHA-256 checksum is computed locally.
- That checksum is compared against the SHA-256 digest that GitHub publishes for the release asset, fetched over a separate TLS-protected connection to the GitHub API.
- If the checksums do not match, the update is aborted and the downloaded file is deleted. Nothing is installed.
This means that even if an attacker could intercept or replace the download, the mismatch would be detected and the update refused.
Note: The certificate-validation bypass setting (
ssl.trustAllCerts, used only for connection testing) never applies to update downloads. Update traffic always validates TLS certificates.
GitHub only began publishing per-asset digests in 2025, so some older releases may not have one. By default, when no trustworthy digest is available, the update proceeds with a warning written to the application log (preserving compatibility with those releases).
If you prefer a stricter policy, you can require a verified checksum for every update - any update without one will be refused:
update.requireChecksum=true
| Behavior | update.requireChecksum=false (default) |
update.requireChecksum=true |
|---|---|---|
| Checksum present and matches | Update proceeds | Update proceeds |
| Checksum present but mismatches | Update aborted | Update aborted |
| No checksum published | Update proceeds (logged warning) | Update aborted |
For normal use you do not need to change anything - integrity verification runs automatically. Set update.requireChecksum=true only if your environment requires that no update is ever installed without a cryptographically verified checksum.
- Open FreeXmlToolkit
- Open Settings (gear icon at the bottom of the activity bar)
- The relevant options are spread over two cards: PARSER and SECURITY
| Card | Setting | Description | Default |
|---|---|---|---|
| PARSER | Allow XSLT extension functions | Enable Java extension functions in XSLT | Off (secure) |
| SECURITY | Trust all certificates | Accept any TLS certificate for HTTPS downloads (schemas, updates). Leave off unless a corporate proxy re-signs traffic | Off (secure) |
For advanced users, security settings are stored in the application properties file (~/.freeXmlToolkit/FreeXmlToolkit.properties; earlier versions kept it in the working directory; it is copied over automatically on the first start):
| Property | Values | Description |
|---|---|---|
security.xslt.allow.extensions |
true / false |
Enable/disable Java extensions in XSLT |
update.requireChecksum |
true / false |
Require a verified SHA-256 checksum for every update; refuse updates that have no published checksum (default false) |
- Keep extensions disabled unless you specifically need them
- Only process trusted stylesheets if you enable extensions
- Download remote schemas to local files when working with internal network resources
- Review XML files before processing if they come from untrusted sources
- Check validation errors - they may indicate blocked security threats
Cause: Your XML references an external DTD or entity that was blocked for security.
Solution: If you need the entity definitions, manually include them in your XML file or convert the external DTD to a local file.
Cause: You tried to load a schema from a localhost or private network address.
Solution: Download the schema file to your local machine and reference it as a local file.
Cause: Your stylesheet uses Java extension functions, which are disabled by default.
Solution: If you trust the stylesheet, enable XSLT extensions in settings. Otherwise, modify the stylesheet to not use extensions.
Cause: A file reference contains suspicious ../ sequences that would access files outside the expected directory.
Solution: Check your schema imports and includes for unusual paths. Use absolute paths or properly relative paths that stay within your project directory.
Cause: The downloaded update did not match the checksum published for the release. This usually indicates a corrupted download or interference on the network, and the update was refused.
Solution: Retry the update on a trusted network connection. If it keeps failing, download the latest release manually from the official GitHub releases page.
Cause: You set update.requireChecksum=true, and the target release does not have a published checksum.
Solution: Either update manually from the official release page, or set update.requireChecksum=false to allow updates that have no published checksum (the default behavior).
For developers and security professionals, here are the specific protections implemented:
All XML parsers use these security features:
http://apache.org/xml/features/disallow-doctype-decl= false (DOCTYPE allowed, but entities disabled)http://xml.org/sax/features/external-general-entities= falsehttp://xml.org/sax/features/external-parameter-entities= falsehttp://apache.org/xml/features/nonvalidating/load-external-dtd= falsejavax.xml.XMLConstants.FEATURE_SECURE_PROCESSING= true- Entity reference expansion = disabled
Feature.ALLOW_EXTERNAL_FUNCTIONS= false (by default)- Configurable via application settings
- Downloaded update artifact is hashed with
SHA-256and compared against the digest GitHub publishes for the release asset (retrieved over TLS from the Releases API). - Mismatch aborts the update and deletes the artifact before any extraction or launch.
- The
ssl.trustAllCertsconnection-test bypass is never applied to update downloads, which always perform standard certificate validation. update.requireChecksum=trueadditionally refuses any update that has no published digest.
Uses Java's InetAddress class to check:
isLoopbackAddress()- blocks localhostisLinkLocalAddress()- blocks 169.254.x.xisSiteLocalAddress()- blocks private networks- Special check for 169.254.169.254 (cloud metadata)
- Canonical path comparison for traversal detection
- Regex patterns for encoded sequences
- Blocklist of system directories
- Symbolic link resolution for escape detection
| Previous | Home | Next |
|---|---|---|
| Technology Stack | Home | Licenses |
All Pages: Unified Shell | XML Editor | XML Features | JSON Editor | XSD Tools | Profiled XML Generation | XSD Validation | XSLT Viewer | XSLT Developer | FOP/PDF | Signatures | IntelliSense | Schematron | FundsXML Extensions | Favorites | Templates | Tech Stack | Security | Licenses