{"record":{"id":"cf54a4fb38bb5fef","repo":"denoland/deno","slug":"package-name-contains-a-url-path-or-delimiter-char","errorCode":null,"errorMessage":"package name contains a URL path or delimiter character","messagePattern":"package name contains a URL path or delimiter character","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/registry.rs","lineNumber":252,"sourceCode":"    })?;\n  if reference.sub_path().is_some() {\n    bail!(\"package name must not contain additional path segments\");\n  }\n\n  let Some((scope, package)) =\n    name.strip_prefix('@').and_then(|name| name.split_once('/'))\n  else {\n    bail!(\"package name must use the '@<scope>/<package>' format\");\n  };\n  for component in [scope, package] {\n    if component == \".\" || component == \"..\" {\n      bail!(\"package name must not contain dot path segments\");\n    }\n    if component\n      .chars()\n      .any(|c| matches!(c, '/' | '\\\\' | '?' | '#' | '%'))\n    {\n      bail!(\"package name contains a URL path or delimiter character\");\n    }\n  }\n  Ok((scope, package))\n}\n\n/// Returns `true` if the given package version is already published to the\n/// registry.\n///\n/// Only a `200 OK` response is treated as \"already published\". A `404` (and any\n/// other non-success status) is treated as \"not published\" so that this\n/// up-front optimization never blocks a legitimate publish because of a\n/// transient registry error.\npub async fn check_version_exists(\n  client: &HttpClient,\n  registry_api_url: &Url,\n  scope: &str,\n  package: &str,\n  version: &str,","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/cli/registry.rs#L234-L270","documentation":"`parse_package_name` rejects scope or package components containing URL path or delimiter characters — `/`, `\\`, `?`, `#`, `%` — because these characters would change how the name is embedded into registry URLs (path separators, query, fragment, percent-encoding) and enable name smuggling. If either component contains any of them, this error is raised.","triggerScenarios":"Passing a name such as `@scope/pkg?x=1`, `@scope/sub/pkg`, `@scope/pkg%20x`, or `@scope/pkg#frag` into `parse_package_name`; also names that survived URL decoding/encoding rounds and still carry reserved characters.","commonSituations":"Passing a full URL or URL fragment instead of a bare package name; double-splitting a name so a second `/` lands inside the package component; names read from query strings or configs without URL-decoding; Windows paths leaking backslashes.","solutions":["Strip the URL/query/fragment portion and pass only the bare `@<scope>/<package>` identifier","Percent-decode the string first if it may be URL-encoded, then re-validate","Sanitize the name to remove `/`, `\\`, `?`, `#`, `%` or reject it before calling"],"exampleFix":"// before\nparse_package_name(\"@my-scope/my-pkg?version=1\")?;\n// after\nparse_package_name(\"@my-scope/my-pkg\")?;","handlingStrategy":"validation","validationCode":"const RESERVED = /[\\/\\\\?#%]/;\nfunction is_clean_jsr_name(name) {\n  if (!name.startsWith(\"@\")) return false;\n  const [, rest] = [name.slice(1), name.slice(1)];\n  const [scope, pkg] = rest.split(\"/\");\n  if (!scope || !pkg || pkg.includes(\"/\")) return false;\n  return !RESERVED.test(scope) && !RESERVED.test(pkg);\n}\nif (!is_clean_jsr_name(name)) throw new Error(\"strip URL delimiters from the package name\");","typeGuard":"fn has_no_url_delimiters(name: &str) -> bool {\n  !name.chars().any(|c| matches!(c, '/' | '\\\\' | '?' | '#' | '%'))\n}","tryCatchPattern":"match parse_package_name(name) {\n  Ok((scope, package)) => /* use scope/package */,\n  Err(e) if e.to_string().contains(\"URL path or delimiter\") => {\n    eprintln!(\"pass the bare name, not a URL: got {name:?}\");\n  }\n  Err(e) => return Err(e),\n}","preventionTips":["Pass identifiers, never URLs or query strings, into package-name parameters","Percent-decode user input before validating, then re-validate for reserved characters","On Windows, normalize backslashes to forward slashes and re-split rather than letting `\\` leak into components","Add a regex validator (reject `[\\/\\\\?#%]`) at every boundary where a package name enters your tooling"],"tags":["jsr","package-name","validation","url"],"backgroundTag":"invalid-package-name","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-29T08:55:39.519Z","contentChangedAt":"2026-08-29T08:55:39.519Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}