perwendel/spark · error · DirectoryTraversalDetection

external

Error message

external

What it means

DirectoryTraversal.protectAgainstForExternal guards Spark's external static-file folder: after unixifying both the requested path and the external folder to absolute paths, it checks the path stays within the folder. If it does not, Spark throws DirectoryTraversalDetection with the message "external", signaling a blocked attempt to escape the external directory.

Solutions

  1. Find and fix the request/link that references paths outside the external folder.
  2. Ensure all served content physically resides under the configured external location (no symlinks escaping it).
  3. Treat repeated occurrences as attack traffic: add rate limiting or WAF rules for traversal patterns.
Defensive patterns

Strategy: try-catch

Validate before calling

Path root = Paths.get(externalFolder).toAbsolutePath().normalize();
Path candidate = Paths.get(path).toAbsolutePath().normalize();
boolean safe = candidate.startsWith(root);

Try / catch

try {
    DirectoryTraversal.protectAgainstForExternal(path, externalFolder);
} catch (DirectoryTraversalDetection e) {
    respond(403, "Forbidden");
}

Prevention

When it happens

Trigger: A request for an external static file whose resolved path (after normalization via Paths.get(...).toAbsolutePath()) lies outside the configured external static files folder, e.g. ../ traversal sequences against staticFiles.externalLocation("/var/www/static").

Common situations: Attackers or scanners probing external static endpoints with ../../ sequences; misconfigured client links using absolute or upward-relative paths; platform-specific separators (\\) that resolve unexpectedly.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of perwendel/spark@1973e402f5 (2026-09-10). Data as JSON: /api/errors/e45bf5d8e4863a03. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/spark/staticfiles/DirectoryTraversal.java:22

import static spark.utils.StringUtils.removeLeadingAndTrailingSlashesFrom;

/**
 * Protecting against Directory traversal
 */
public class DirectoryTraversal {

    public static void protectAgainstInClassPath(String path, String localFolder) {
        if (!isPathWithinFolder(path, localFolder)) {
            throw new DirectoryTraversalDetection("classpath");
        }
    }

    public static void protectAgainstForExternal(String path, String externalFolder) {
    	String unixLikeFolder = unixifyPath(externalFolder);
        String nixLikePath = unixifyPath(path);
        if (!isPathWithinFolder(nixLikePath, unixLikeFolder)) {
            throw new DirectoryTraversalDetection("external");
        }
    }
    
    private static String unixifyPath(String path) {
    	return Paths.get(path).toAbsolutePath().toString().replace("\\", "/");
    }
    
    private static boolean isPathWithinFolder(String path, String folder) {
    	String rlatsPath = removeLeadingAndTrailingSlashesFrom(path);
    	String rlatsFolder = removeLeadingAndTrailingSlashesFrom(folder);
    	return rlatsPath.startsWith(rlatsFolder);
    }

    public static final class DirectoryTraversalDetection extends RuntimeException {
        private static final long serialVersionUID = 1L;

        public DirectoryTraversalDetection(String msg) {
            super(msg);

View on GitHub (pinned to 1973e402f5)