{"record":{"id":"b6765212456b6c98","repo":"elastic/elasticsearch","slug":"relative-path-must-be-relative","errorCode":null,"errorMessage":"'relative_path' [{}] must be relative","messagePattern":"'relative_path' \\[(.+?)\\] must be relative","errorType":"validation","errorClass":"PolicyValidationException","httpStatus":null,"severity":"error","filePath":"libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java","lineNumber":283,"sourceCode":"            }\n\n            if (relativeTo != null && relativePathAsString == null) {\n                throw new PolicyValidationException(\"'relative_to' may only be used with 'relative_path'\");\n            }\n\n            if (settingBaseDirAsString != null && pathSetting == null) {\n                throw new PolicyValidationException(\"'basedir_if_relative' may only be used with 'path_setting'\");\n            }\n\n            final FileData fileData;\n            if (relativePathAsString != null) {\n                if (relativeTo == null) {\n                    throw new PolicyValidationException(\"files entitlement with a 'relative_path' must specify 'relative_to'\");\n                }\n                BaseDir baseDir = parseBaseDir(relativeTo);\n                Path relativePath = Path.of(relativePathAsString);\n                if (FileUtils.isAbsolutePath(relativePathAsString)) {\n                    throw new PolicyValidationException(\"'relative_path' [\" + relativePathAsString + \"] must be relative\");\n                }\n                fileData = FileData.ofRelativePath(relativePath, baseDir, mode);\n            } else if (pathAsString != null) {\n                Path path = Path.of(pathAsString);\n                if (FileUtils.isAbsolutePath(pathAsString) == false) {\n                    throw new PolicyValidationException(\"'path' [\" + pathAsString + \"] must be absolute\");\n                }\n                fileData = FileData.ofPath(path, mode);\n            } else if (pathSetting != null) {\n                if (settingBaseDirAsString == null) {\n                    throw new PolicyValidationException(\"files entitlement with a 'path_setting' must specify 'basedir_if_relative'\");\n                }\n                BaseDir baseDir = parseBaseDir(settingBaseDirAsString);\n                fileData = FileData.ofPathSetting(pathSetting, baseDir, mode);\n            } else {\n                throw new AssertionError(\"File entry validation error\");\n            }\n            filesData.add(fileData.withPlatform(platform).withExclusive(exclusive));","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/entitlements/FilesEntitlement.java#L265-L301","documentation":"Thrown when `relative_path` resolves to an absolute path on the running filesystem. The relative_path branch is reserved for paths expressed relative to the `relative_to` base dir; an absolute value would double-anchor and is rejected — absolute paths must use the `path` field instead.","triggerScenarios":"An entry sets `relative_path` to a value that FileUtils.isAbsolutePath reports as absolute on the host OS (leading slash on Unix, drive letter or backslash on Windows).","commonSituations":"Author copies an absolute path into `relative_path` thinking the field is generic; cross-platform policy where a Windows-style path is treated as absolute; mixing up `path` and `relative_path` semantics; leftover absolute path after refactoring from `path` to `relative_path`.","solutions":["If the path is meant to be absolute, move it into the `path` field and drop `relative_to`.","If the path is meant to be relative, strip the leading separator (and any drive letter on Windows) so it is genuinely relative."],"exampleFix":"// before\n{ \"relative_path\": \"/var/log/es\", \"relative_to\": \"home\", \"mode\": \"read\" }\n\n// after (option A: absolute)\n{ \"path\": \"/var/log/es\", \"mode\": \"read\" }\n// after (option B: relative)\n{ \"relative_path\": \"log/es\", \"relative_to\": \"home\", \"mode\": \"read\" }","handlingStrategy":"validation","validationCode":"public static void validateRelativePathIsRelative(String relativePath) {\n    if (Path.of(relativePath).isAbsolute()) {\n        throw new IllegalArgumentException(\"relative_path must not be absolute: \" + relativePath);\n    }\n}","typeGuard":"public static boolean isRelative(String p) {\n    return !Path.of(p).isAbsolute();\n}","tryCatchPattern":null,"preventionTips":["Strip leading separators before putting a value into relative_path.","If the path is absolute, move it to the `path` field.","Cross-platform: avoid drive letters and leading backslashes in relative_path."],"tags":["entitlements","files","policy","validation","paths","platform"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}