{"record":{"id":"b56d535cb346d37d","repo":"apple/pkl","slug":"invalidrelativepathinpackageuri","errorCode":"invalidRelativePathInPackageUri","errorMessage":"invalidRelativePathInPackageUri","messagePattern":"invalidRelativePathInPackageUri","errorType":"error_code","errorClass":"URISyntaxException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/packages/PackageUri.java","lineNumber":67,"sourceCode":"    var scheme = uri.getScheme();\n    if (scheme == null || !(scheme.equals(\"package\") || scheme.equals(\"projectpackage\"))) {\n      throw new URISyntaxException(\n          uri.toString(), ErrorMessages.create(\"invalidSchemeInPackageUri\", scheme));\n    }\n    var authority = uri.getAuthority();\n    if (authority == null || authority.isEmpty()) {\n      throw new URISyntaxException(\n          uri.toString(), ErrorMessages.create(\"missingAuthorityInPackageUri\", uri));\n    }\n    var path = uri.getPath();\n    if (path == null || path.isEmpty()) {\n      throw new URISyntaxException(\n          uri.toString(), ErrorMessages.create(\"missingPathInPackageUri\", uri));\n    }\n    // reject `..` segments, percent-encoded or not\n    for (var segment : path.split(\"/\", -1)) {\n      if (segment.equals(\"..\")) {\n        throw new URISyntaxException(\n            uri.toString(), ErrorMessages.create(\"invalidRelativePathInPackageUri\"));\n      }\n    }\n    var versionIdx = path.lastIndexOf('@');\n    if (versionIdx == -1) {\n      throw new URISyntaxException(\n          uri.toString(), ErrorMessages.create(\"missingVersionInPackageUri\", path));\n    }\n    this.uri = IoUtils.stripFragment(uri);\n    this.pathWithoutVersion = path.substring(0, versionIdx);\n    var checksumIdx = path.indexOf(\"::\");\n    var versionPart = path.substring(versionIdx + 1);\n    if (checksumIdx > versionIdx) {\n      var checksumPart = path.substring(checksumIdx + 2);\n      versionPart = path.substring(versionIdx + 1, checksumIdx);\n      this.checksums = parseChecksumPart(checksumPart);\n    }\n    try {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/packages/PackageUri.java#L49-L85","documentation":"Thrown by the PackageUri constructor when the package URI path contains a '..' segment (literally or percent-encoded). Parent-directory segments are rejected to keep package URIs canonical and prevent path traversal within package identifiers.","triggerScenarios":"new PackageUri(uri) where any path segment split on '/' equals '..', e.g. 'package://example.com/../other@1.0.0' or with %2E%2E encoded segments.","commonSituations":"Programmatically resolving relative paths and forgetting normalization before building the URI; template/concatenation bugs injecting '..'; attempting to smuggle traversal segments into a dependency URI (caught by design).","solutions":["Remove all '..' segments and use a canonical absolute package path","Normalize the path (or reject the input) before constructing the PackageUri","Use the package name exactly as published instead of a computed relative path"],"exampleFix":"// before\nvar uri = URI.create(\"package://example.com/a/../my-pkg@1.2.3\");\nvar pkg = new PackageUri(uri);\n// after\nvar uri = URI.create(\"package://example.com/my-pkg@1.2.3\");\nvar pkg = new PackageUri(uri);","handlingStrategy":"validation","validationCode":"boolean hasNoDotDotSegments(String path) {\n  for (var segment : path.split(\"/\", -1)) {\n    if (segment.equals(\"..\")) return false;\n  }\n  return true;\n}","typeGuard":"static boolean isCanonicalPackagePath(URI uri) {\n  var path = uri.getPath();\n  if (path == null) return false;\n  for (var segment : path.split(\"/\", -1)) {\n    if (segment.equals(\"..\")) return false;\n  }\n  return true;\n}","tryCatchPattern":"try {\n  var pkg = new PackageUri(uri);\n} catch (URISyntaxException e) {\n  throw new IllegalArgumentException(\"Package URI must not contain '..' segments: \" + uri, e);\n}","preventionTips":["Normalize relative paths before embedding them in a URI","Never build package URIs from unnormalized user paths","Reject '..' (including percent-encoded) early in input validation"],"tags":["pkl","package-uri","path-traversal","uri-validation"],"backgroundTag":"path-traversal-blocked","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}