Skip to content

fix: strip trailing slash from registry URL - #14

Merged
elrrrrrrr merged 1 commit into
mainfrom
fix/registry-trailing-slash
Jun 18, 2026
Merged

elrrrrrrr merged 1 commit into
mainfrom
fix/registry-trailing-slash

Conversation

@elrrrrrrr

Copy link
Copy Markdown
Contributor

Problem

The default registry input is https://registry.npmjs.org/ (trailing slash). The action passes it verbatim to ut config set registry, so utoo's global config stores the trailing slash. utoo builds metadata URLs as {registry}/{pkg}, which then yields a double slash:

https://registry.npmjs.org//@svgr/babel-plugin-remove-jsx-empty-expression

npm's registry returns HTTP 406 Not Acceptable for the //<pkg> path, so dependency resolution fails. Seen in ant-design CI:

ERROR Dependency resolution failed: Registry error: Failed to fetch
@svgr/babel-plugin-remove-jsx-empty-expression: HTTP 406 Not Acceptable:
https://registry.npmjs.org//@svgr/babel-plugin-remove-jsx-empty-expression

Fix

  • Drop the trailing slash from the default registry (action.yml, src/index.ts).
  • Defensively strip any trailing slash(es) from a caller-supplied registry in src/action.ts before it's used (config write, install, manifest fetch), so a user-provided .../ can't reintroduce the bug.
  • Rebuild dist/setup/index.js.

🤖 Generated with Claude Code

The default registry input was `https://registry.npmjs.org/` (trailing
slash) and was passed verbatim to `ut config set registry`. utoo joins
URLs as `{registry}/{pkg}`, producing `//<pkg>`, which npm's registry
rejects with HTTP 406 Not Acceptable — breaking dependency resolution.

Drop the trailing slash from the default and normalize any caller-supplied
trailing slashes in the action before use.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@elrrrrrrr
elrrrrrrr merged commit e63ce40 into main Jun 18, 2026
8 checks passed
@elrrrrrrr
elrrrrrrr deleted the fix/registry-trailing-slash branch June 18, 2026 06:29

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the default npm registry URL to remove the trailing slash and adds logic to strip trailing slashes from the registry option in src/action.ts. A critical command injection vulnerability was identified in how the registry variable is used in shell execution, and it is recommended to validate the URL input and use safe execution methods.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/action.ts
Comment on lines +39 to +42
const registry = (options.registry || "https://registry.npmjs.org").replace(
/\/+$/,
"",
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

Security Vulnerability: Command Injection

The registry variable is constructed from user input (options.registry) and later passed directly to execSync with shell: true in setRegistry (line 207):

execSync(`ut config set registry ${registry} --global`, { ... })

Because shell: true is used, this creates a Command Injection vulnerability if a malicious or malformed registry URL is provided (e.g., containing shell metacharacters like ;, &, or |).

Recommendations:

  1. Input Validation (Defense-in-Depth): Validate that the registry is a valid URL before using it. This can be done by parsing it with new URL() which will throw an error for invalid URLs.
  2. Safe Execution (Primary Fix): Refactor setRegistry to use @actions/exec's getExecOutput (which is already imported) instead of child_process.execSync with shell: true. This avoids spawning a shell and safely passes arguments as an array.

For example, refactor setRegistry as follows:

async function setRegistry(registry: string): Promise<void> {
  try {
    await getExecOutput("ut", ["config", "set", "registry", registry, "--global"]);
  } catch (error) {
    warning(`Failed to set npm registry: ${error}`);
  }
}
Suggested change
const registry = (options.registry || "https://registry.npmjs.org").replace(
/\/+$/,
"",
);
const registryInput = options.registry || "https://registry.npmjs.org";
try {
new URL(registryInput);
} catch {
throw new Error(`Invalid registry URL: ${registryInput}`);
}
const registry = registryInput.replace(/\/+$/, "");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant