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
- Find and fix the request/link that references paths outside the external folder.
- Ensure all served content physically resides under the configured external location (no symlinks escaping it).
- 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
- Serve only files physically located under the external folder.
- Normalize incoming paths client-side; reject absolute or upward-relative paths.
- Add WAF rules for encoded traversal sequences (%2e%2e, ..%2f).
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
- classpath
- Bad request
- WebSocket handler must implement 'WebSocketListener' or be…
- path cannot be null or blank
- httpMethod cannot be null or blank
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)