{"record":{"id":"cd8f4203363a7a45","repo":"denoland/deno","slug":"tags-are-not-supported-in-the-allowscripts-field","errorCode":null,"errorMessage":"Tags are not supported in the allowScripts field: {}","messagePattern":"Tags are not supported in the allowScripts field: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/tools/pm/approve_scripts.rs","lineNumber":344,"sourceCode":"      ..\n    }) => {\n      bail!(\"Only npm packages are supported: {}\", text);\n    }\n    Ok(\n      req @ JsrDepPackageReq {\n        kind: PackageKind::Npm,\n        ..\n      },\n    ) => req,\n    Err(JsrDepPackageReqParseError::NotExpectedScheme(_))\n      if !text.contains(':') =>\n    {\n      return parse_npm_package_req(&format!(\"npm:{text}\"));\n    }\n    Err(e) => return Err(e.into()),\n  };\n  if req.req.version_req.tag().is_some() {\n    bail!(\"Tags are not supported in the allowScripts field: {}\", text);\n  }\n  Ok(req.req)\n}\n\nfn package_req_matches_nv(req: &PackageReq, nv: &PackageNv) -> bool {\n  req.name == nv.name && req.version_req.matches(&nv.version)\n}\n\nfn render_candidate(\n  candidate: &ScriptCandidate,\n  is_selected: bool,\n  is_checked: bool,\n) -> Result<TextItem<'static>, AnyError> {\n  let mut line = String::new();\n  write!(\n    &mut line,\n    \"{} {} {}\",\n    if is_selected {","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/tools/pm/approve_scripts.rs#L326-L362","documentation":"After parsing an allowScripts entry, the code checks `req.req.version_req.tag()` and rejects dist-tags. `latest`, `next`, `canary` etc. are mutable pointers, so an allow-rule pinned to a tag would silently change meaning when the registry moves the tag.","triggerScenarios":"An allowScripts entry with a dist-tag version, e.g. `\"npm:esbuild@latest\"` or `\"cowsay@next\"`. Plain names, exact versions (`@1.2.3`) and ranges (`@^1`) are fine.","commonSituations":"Copying a dependency line from package.json that uses a tag;. Writing `@latest` out of habit from `npm install pkg@latest`.","solutions":["Replace the tag with a concrete version or range: `npm:esbuild@^0.25` or `npm:esbuild@0.25.0`.","Or omit the version entirely to match any version of that package.","Audit other entries for tags since the check applies per entry."],"exampleFix":"// deno.json (before)\n{\n  \"npmScripts\": { \"allow\": [\"npm:esbuild@latest\"] }\n}\n// deno.json (after)\n{\n  \"npmScripts\": { \"allow\": [\"npm:esbuild@^0.25.0\"] }\n}","handlingStrategy":"validation","validationCode":"const TAG = /@(latest|next|canary|beta|alpha|rc|dev)$/i;\nconst entries = [...(cfg.npmScripts?.allow ?? []), ...(cfg.npmScripts?.deny ?? [])];\nconst bad = entries.filter((s) => TAG.test(s));\nif (bad.length) {\n  console.error(`dist-tags not allowed in npmScripts: ${bad.join(\", \")}`);\n  process.exit(1);\n}","typeGuard":"const hasDistTag = (s: string): boolean =>\n  /@[^@\\s]+$/i.test(s) && !/\\d/.test(s.split(\"@\").pop() ?? \"\");","tryCatchPattern":null,"preventionTips":["Pin allowScripts entries to versions or ranges; security-relevant lists must be immutable.","Omit the version to match all versions instead of writing @latest.","Review allow/deny lists for tags whenever copying from package.json."],"tags":["npm","scripts","dist-tag","semver"],"backgroundTag":"npm-dist-tag-unsupported","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}