apple/pkl · error · SecurityManagerException

resourcePastRootDir|modulePastRootDir

resourcePastRootDir|modulePastRootDir

Error message

resourcePastRootDir|modulePastRootDir

What it means

When resolving file/resource URIs, the security manager canonicalizes the target path with toRealPath (following symlinks) and rejects it if it escapes the configured root directory. The error key is `resourcePastRootDir` for resources and `modulePastRootDir` for modules, guarding against path-traversal outside the sandbox root.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/SecurityManagers.java:189

        throw new SecurityManagerException(message);
      }
    }

    @Override
    public @Nullable Path resolveSecurePath(URI uri, boolean isResource)
        throws SecurityManagerException, IOException {
      if (rootDir == null
          || !uri.isAbsolute()
          || !uri.getScheme().equals("file")
          || (uri.getAuthority() != null && !uri.getAuthority().isEmpty())) {
        return null;
      }
      var path = Path.of(uri);
      var realPath = path.toRealPath();
      if (!realPath.startsWith(rootDir)) {
        var errorMessageKey = isResource ? "resourcePastRootDir" : "modulePastRootDir";
        var message = ErrorMessages.create(errorMessageKey, uri, rootDir);
        throw new SecurityManagerException(message);
      }
      return realPath;
    }

    private @Nullable Path normalizePath(@Nullable Path path) {
      if (path == null) {
        return null;
      }
      try {
        if (Files.exists(path)) {
          return path.toRealPath();
        }
        return path.toAbsolutePath();
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
    }

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Keep modules/resources physically inside the configured root directory (copy or move them in)
  2. Remove or re-point symlinks that escape the root
  3. Correct the URI to a path within rootDir instead of using traversal segments

Example fix

// before
import "../shared/config.pkl"
// after (within root)
import "shared/config.pkl"
Defensive patterns

Strategy: validation

Validate before calling

java.nio.file.Path target = java.nio.file.Path.of(uri).toRealPath();
if (!target.startsWith(rootDir)) throw new IllegalArgumentException("path escapes root: " + uri);

Try / catch

try {
  Path real = resolveSecurePath(uri, isResource);
} catch (SecurityManagerException e) {
  // remap the URI to a path inside rootDir or copy the file into root
}

Prevention

When it happens

Trigger: Calling resolveSecurePath with a URI whose real path does not start with rootDir — e.g. `../` traversal in a path, or a symlink pointing outside the root — during module or resource loading.

Common situations: Symlinked module files pointing to locations outside the project root; paths containing `..` segments that resolve outside root; moving/renaming the root directory so previously valid paths now resolve elsewhere.

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 apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/378c8d9923a08a61. Report an issue: GitHub.