{"record":{"id":"a10c1c9b918a5ef8","repo":"apache/pulsar","slug":"invalid-filename","errorCode":null,"errorMessage":"Invalid filename: ","messagePattern":"Invalid filename: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java","lineNumber":895,"sourceCode":"        }\n        if (functionConfig.getRetainKeyOrdering() != null\n                && functionConfig.getRetainKeyOrdering()\n                && functionConfig.getProcessingGuarantees() != null\n                && functionConfig.getProcessingGuarantees() == FunctionConfig.ProcessingGuarantees.EFFECTIVELY_ONCE) {\n            throw new IllegalArgumentException(\n                    \"When effectively once processing guarantee is specified, retain Key ordering cannot be set\");\n        }\n        if (functionConfig.getRetainKeyOrdering() != null && functionConfig.getRetainKeyOrdering()\n                && functionConfig.getRetainOrdering() != null && functionConfig.getRetainOrdering()) {\n            throw new IllegalArgumentException(\"Only one of retain ordering or retain key ordering can be set\");\n        }\n\n        if (!isEmpty(functionConfig.getPy()) && !org.apache.pulsar.common.functions.Utils\n                .isFunctionPackageUrlSupported(functionConfig.getPy())\n                && functionConfig.getPy().startsWith(BUILTIN)) {\n            String filename = functionConfig.getPy();\n            if (filename.contains(\"..\")) {\n                throw new IllegalArgumentException(\"Invalid filename: \" + filename);\n            }\n\n            if (!new File(filename).exists()) {\n                throw new IllegalArgumentException(\"The supplied python file does not exist\");\n            }\n        }\n        if (!isEmpty(functionConfig.getGo()) && !org.apache.pulsar.common.functions.Utils\n                .isFunctionPackageUrlSupported(functionConfig.getGo())\n                && functionConfig.getGo().startsWith(BUILTIN)) {\n            String filename = functionConfig.getGo();\n            if (filename.contains(\"..\")) {\n                throw new IllegalArgumentException(\"Invalid filename: \" + filename);\n            }\n\n            if (!new File(filename).exists()) {\n                throw new IllegalArgumentException(\"The supplied go file does not exist\");\n            }\n        }","sourceCodeStart":877,"sourceCodeEnd":913,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L877-L913","documentation":"When a Python function is registered as a built-in function (the .py path starts with the 'builtin://' prefix) and the package URL type is not a supported remote URL, the filename must be a simple local name. If it contains '..' (path traversal), validation rejects it with IllegalArgumentException to prevent the function from referencing files outside the expected built-in directory.","triggerScenarios":"Setting FunctionConfig.setPy() to something like 'builtin://../../etc/passwd' or any builtin reference whose filename component contains '..' while Utils.isFunctionPackageUrlSupported returns false for the value, then calling validateNonJavaFunction/validateJavaFunction (createFunction/updateFunction).","commonSituations":"Hand-assembling a builtin:// URL with relative path segments; attempting path traversal (intentionally or by string concatenation); typos like 'builtin://my/../func.py'; config generated by scripts that join paths with '../'.","solutions":["Remove any '..' segments from the .py value so the builtin filename is a bare name, e.g. 'builtin://myfunc.py'","Use a fully qualified package URL (http(s)://, file://) supported by isFunctionPackageUrlSupported instead of a builtin reference","Reference a built-in function by its exact registered name (list built-ins with the pulsar-admin functions builtins list)","If this value comes from user input, sanitize/reject inputs containing '..' before building the config"],"exampleFix":"// before\nconf.setPy(\"builtin://../functions/excerpt.py\");\n// after\nconf.setPy(\"builtin://excerpt.py\");","handlingStrategy":"validation","validationCode":"String py = conf.getPy();\nif (py != null && py.startsWith(\"builtin://\")\n        && !org.apache.pulsar.common.functions.Utils.isFunctionPackageUrlSupported(py)\n        && py.substring(\"builtin://\".length()).contains(\"..\")) {\n    throw new IllegalStateException(\"builtin python name must not contain '..'\");\n}","typeGuard":"boolean isSafeBuiltinName(String s) {\n    return s != null && s.startsWith(\"builtin://\") && !s.contains(\"..\");\n}","tryCatchPattern":"try {\n    admin.functions().createFunction(conf);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Invalid filename:\")) {\n        conf.setPy(\"builtin://\" + Paths.get(conf.getPy().replace(\"builtin://\", \"\")).getFileName());\n        admin.functions().createFunction(conf);\n    } else throw e;\n}","preventionTips":["Never concatenate user input into builtin:// URLs","Normalize file paths with Paths.get(...).getFileName() before building the config","Whitelist allowed built-in function names in your deployment tooling"],"tags":["pulsar-functions","config-validation","path-traversal","security"],"backgroundTag":"invalid-function-package-path","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}