From 8e6d1b7447d48bc4d5efe63a7a1eb31ffd22c3eb Mon Sep 17 00:00:00 2001
From: Thomas Reggi <reggi@github.com>
Date: Wed, 1 May 2024 15:15:10 -0400
Subject: [PATCH 1/2] validates the tag on publish

---
 lib/commands/publish.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/commands/publish.js b/lib/commands/publish.js
index 6bb2dcc6614bb..f4072074898d3 100644
--- a/lib/commands/publish.js
+++ b/lib/commands/publish.js
@@ -96,6 +96,10 @@ class Publish extends BaseCommand {
     }
 
     const resolved = npa.resolve(manifest.name, manifest.version)
+
+    // make sure tag is valid, this will throw if invalid
+    npa(`${manifest.name}@${defaultTag}`)
+
     const registry = npmFetch.pickRegistry(resolved, opts)
     const creds = this.npm.config.getCredentialsByURI(registry)
     const noCreds = !(creds.token || creds.username || creds.certfile && creds.keyfile)

From 8f7fd4f2ec37956780c9f3b1cd748bfebdfb863c Mon Sep 17 00:00:00 2001
From: Thomas Reggi <reggi@github.com>
Date: Wed, 1 May 2024 15:29:43 -0400
Subject: [PATCH 2/2] add unit test

---
 test/lib/commands/publish.js | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/test/lib/commands/publish.js b/test/lib/commands/publish.js
index 85a66d88b8b34..9e7ba6b070583 100644
--- a/test/lib/commands/publish.js
+++ b/test/lib/commands/publish.js
@@ -291,7 +291,7 @@ t.test('shows usage with wrong set of arguments', async t => {
   await t.rejects(publish.exec(['a', 'b', 'c']), publish.usage)
 })
 
-t.test('throws when invalid tag', async t => {
+t.test('throws when invalid tag is semver', async t => {
   const { npm } = await loadMockNpm(t, {
     config: {
       tag: '0.0.13',
@@ -306,6 +306,24 @@ t.test('throws when invalid tag', async t => {
   )
 })
 
+t.test('throws when invalid tag when not url encodable', async t => {
+  const { npm } = await loadMockNpm(t, {
+    config: {
+      tag: '@test',
+    },
+    prefixDir: {
+      'package.json': JSON.stringify(pkgJson, null, 2),
+    },
+  })
+  await t.rejects(
+    npm.exec('publish', []),
+    {
+      /* eslint-disable-next-line max-len */
+      message: 'Invalid tag name "@test" of package "test-package@@test": Tags may not have any characters that encodeURIComponent encodes.',
+    }
+  )
+})
+
 t.test('tarball', async t => {
   const { npm, joinedOutput, logs, home } = await loadMockNpm(t, {
     config: {