{"record":{"id":"9dc0837bba640118","repo":"quarkusio/quarkus","slug":"path-leaves-the-application-root-file","errorCode":null,"errorMessage":"Path leaves the application root: <file>","messagePattern":"Path leaves the application root: <file>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java","lineNumber":487,"sourceCode":"    }\n\n    private static void validateExistingPathComponents(Path normalizedRoot, Path resolved, String file) {\n        final Path realRoot;\n        try {\n            realRoot = normalizedRoot.toRealPath();\n        } catch (IOException e) {\n            throw new IllegalArgumentException(\"Unable to validate the application root for remote-dev path: \" + file, e);\n        }\n        Path current = normalizedRoot;\n        for (Path element : normalizedRoot.relativize(resolved)) {\n            current = current.resolve(element);\n            if (Files.isSymbolicLink(current)) {\n                throw new IllegalArgumentException(\"Symbolic links are not allowed in remote-dev paths: \" + file);\n            }\n            if (Files.exists(current, LinkOption.NOFOLLOW_LINKS)) {\n                try {\n                    if (!current.toRealPath().startsWith(realRoot)) {\n                        throw new IllegalArgumentException(\"Path leaves the application root: \" + file);\n                    }\n                } catch (IOException e) {\n                    throw new IllegalArgumentException(\"Unable to validate remote-dev path: \" + file, e);\n                }\n            } else {\n                break;\n            }\n        }\n    }\n\n    private static String normalizeFile(String file) {\n        requireNonNull(file, \"file\");\n        file = file.replace('\\\\', '/');\n        if (file.startsWith(\"/\")) {\n            file = file.substring(1);\n        }\n        return file;\n    }","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java#L469-L505","documentation":"During validation, if a path component exists and its real path does not start with the real application root, the resolved path is judged to escape the root via a real-path alias (e.g. a bind mount or hard link to outside), and this IllegalArgumentException is thrown. It complements the lexical .. check by catching physical escapes.","triggerScenarios":"updateFile or resolveApplicationPath where an existing component of the path resolves (via toRealPath) outside the real application root — bind mounts, mounts overlapping the root, or links resolved by the OS.","commonSituations":"Application root contains an overlay/bind-mounted subdirectory; Docker volume mounts nested inside the project dir; network mounts aliased under a different canonical path.","solutions":["Ensure all paths under the application root are physically inside it (no nested bind mounts for the sync path).","Use consistent canonical paths when mounting volumes into dev containers.","Move the synced output directory so its real path is within the root.","Run remote-dev server and client against the same canonical filesystem layout."],"exampleFix":"# before: docker -v /elsewhere/classes:/app/target/classes (real path leaves root)\n# after: build into a directory physically under the app root, no nested bind mount","handlingStrategy":"validation","validationCode":"Path root = Path.of(\".\").toAbsolutePath().normalize().toRealPath();\nPath target = root.resolve(relPath).normalize();\nif (Files.exists(target, LinkOption.NOFOLLOW_LINKS) && !target.toRealPath().startsWith(root))\n    throw new IllegalStateException(\"target real path escapes root: \" + target);","typeGuard":null,"tryCatchPattern":"try {\n    client.sync(path);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Path leaves the application root\")) {\n        log.errorf(\"%s resolves outside the app root (bind mount or link) — fix mounts\", path);\n    } else throw e;\n}","preventionTips":["Avoid nested bind mounts inside the project root","Use canonical paths for container volume mounts","Verify with `realpath` that all synced paths stay under the root"],"tags":["path-traversal","security","remote-dev","filesystem"],"backgroundTag":"path-escapes-application-root","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}