{"record":{"id":"211a0870d7e3eff5","repo":"jdx/mise","slug":"invalid-python-entry-point-name","errorCode":null,"errorMessage":"invalid Python entry point name","messagePattern":"invalid Python entry point name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/pipx/lock.rs","lineNumber":500,"sourceCode":"        } else {\n            \"python\"\n        });\n        let packages = self.locked_entry_point_packages(tv, lock)?;\n        let packages = serde_json::to_string(&packages)?;\n        let names = CmdLineRunner::new(python)\n            .args([\"-I\", \"-c\", DISCOVER_SCRIPTS, &packages])\n            .arg(&scripts)\n            .read()\n            .await?;\n        let names: Vec<String> = serde_json::from_str(names.trim())?;\n        if names.is_empty() {\n            bail!(\"{} exposes no executable scripts\", self.ba.short);\n        }\n        let bin = tv.install_path().join(\"bin\");\n        crate::file::create_dir_all(&bin)?;\n        for name in names {\n            if !crate::file::is_plain_file_name(&name) {\n                bail!(\"invalid Python entry point name\");\n            }\n            crate::file::make_symlink_or_copy(&scripts.join(&name), &bin.join(&name))?;\n        }\n        Ok(())\n    }\n\n    fn locked_entry_point_packages(&self, tv: &ToolVersion, lock: &UvLock) -> Result<Vec<String>> {\n        let root_requirement = lock\n            .project\n            .get(\"project\")\n            .and_then(toml::Value::as_table)\n            .and_then(|project| project.get(\"dependencies\"))\n            .and_then(toml::Value::as_array)\n            .and_then(|dependencies| dependencies.first())\n            .and_then(toml::Value::as_str)\n            .ok_or_else(|| eyre!(\"missing locked Python root requirement\"))?;\n        let root = PipxOptions::requirement_package_name(root_requirement)\n            .ok_or_else(|| eyre!(\"invalid locked Python root requirement\"))?;","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/pipx/lock.rs#L482-L518","documentation":"Each discovered executable name from the installed environment is validated with is_plain_file_name before being symlinked into the install's bin/ directory. Names that are not plain file names (e.g. containing path separators, `..`, or other traversal-capable characters) are rejected to prevent a malicious or malformed package metadata from writing outside the install path.","triggerScenarios":"Thrown from install_uv_lock when a name in the DISCOVER_SCRIPTS JSON output fails crate::file::is_plain_file_name — e.g. an entry point name containing `/`, `\\\\`, or other non-plain-file characters, typically from a crafted or corrupted distribution's entry_points metadata.","commonSituations":"A compromised or malicious PyPI package declares entry points with path-like names; corrupted metadata inside an installed wheel; unusual distributions with exotic entry point names.","solutions":["Remove the offending package from your dependency set and re-lock: `mise lock --bump <tool>`.","Inspect the installed distribution's entry_points.txt / RECORD to find the malformed entry point name.","Report the package to PyPI/maintainers if the entry point name is genuinely malicious; treat the package as untrusted.","Install a known-good version of the package that does not declare pathological entry point names."],"exampleFix":"// before (entry_points.txt from malicious wheel)\n[console_scripts]\n../../evil = pkg:main\n\n// after: pin a clean version and re-lock\n$ mise lock --bump <tool>  # against a vetted version","handlingStrategy":"validation","validationCode":"const names = discoverScripts();\nif (names.some(n => /[\\/\\\\]/.test(n) || n === '..' || n === '.')) throw new Error('suspicious entry point name');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only lock packages from trusted maintainers/registries","Review entry point names when adopting new tools","Treat path-like entry point names in any wheel metadata as a red flag"],"tags":["python","uv","security","path-traversal"],"backgroundTag":"path-traversal-blocked","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}