npm-package-arg icon indicating copy to clipboard operation
npm-package-arg copied to clipboard

[BUG] Failed to decode path name with valid symbols

Open andrew-aladjev opened this issue 1 year ago • 1 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current Behavior

Parent issue: https://github.com/npm/cli/issues/7779

cd /tmp
mkdir ' !"$%&'\''()*+,-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
cd ' !"$%&'\''()*+,-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
npm pack
4 silly config load:file:/tmp/ !"$%&'()*+,-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~/.npmrc
5 silly config load:file:/home/puchuu/.npmrc
6 silly config load:file:/home/puchuu/.local/share/fnm/node-versions/v20.16.0/installation/etc/npmrc
7 verbose title npm pack
8 verbose argv "pack"
9 verbose logfile logs-max:10 dir:/home/puchuu/.npm/_logs/2024-09-12T12_18_03_676Z-
10 verbose logfile /home/puchuu/.npm/_logs/2024-09-12T12_18_03_676Z-debug-0.log
11 silly logfile start cleaning logs, removing 1 files
12 verbose stack URIError: URI malformed
12 verbose stack     at decodeURIComponent (<anonymous>)
12 verbose stack     at fromFile (/home/puchuu/.local/share/fnm/node-versions/v20.16.0/installation/lib/node_modules/npm/node_modules/npm-package-arg/lib/npa.js:279:22)

It is not possible to work with symbols available in path with URI. I don't know why you are trying to use URI encode and decode.

Expected Behavior

No response

Steps To Reproduce

No response

Environment

  • npm: 10.8.1
  • Node: v20.16.0
  • OS: Ubuntu 24.04.1 LTS

andrew-aladjev avatar Sep 12 '24 12:09 andrew-aladjev

Can you please describe what does let resolvedPath = decodeURIComponent(resolvedUrl.pathname) mean? pathname can include any ascii symbol except / and it can't be decoded using decodeURIComponent. Why are you using decodeURIComponent here?

andrew-aladjev avatar Sep 12 '24 12:09 andrew-aladjev

The reason is because this is parsing a URL object

    resolvedUrl = new URL(rawWithPrefix, `file://${path.resolve(where)}/`)

Normally pathname is URI encoded

> new URL('file:///test dir')
URL {
  href: 'file:///test%20dir',
  origin: 'null',
  protocol: 'file:',
  username: '',
  password: '',
  host: '',
  hostname: '',
  port: '',
  pathname: '/test%20dir',
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
}
> new URL('file:test dir')
URL {
  href: 'file:///test%20dir',
  origin: 'null',
  protocol: 'file:',
  username: '',
  password: '',
  host: '',
  hostname: '',
  port: '',
  pathname: '/test%20dir',
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
}

This actually looks like it could be a node bug. (new URL).pathname is supposed to be URI encoded, and able to be URI decoded.

> new URL(`file:///tmp/ !"$%&'()*+,-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~`)
URL {
  href: "file:///tmp/%20!%22$%&'()*+,-.0123456789:;%3C=%3E@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_%60abcdefghijklmnopqrstuvwxyz%7B|%7D~",
  origin: 'null',
  protocol: 'file:',
  username: '',
  password: '',
  host: '',
  hostname: '',
  port: '',
  pathname: "/tmp/%20!%22$%&'()*+,-.0123456789:;%3C=%3E@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_%60abcdefghijklmnopqrstuvwxyz%7B|%7D~",
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
}
> decodeURIComponent("/tmp/%20!%22$%&'()*+,-.0123456789:;%3C=%3E@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_%60abcdefghijklmnopqrstuvwxyz%7B|%7D~")
Uncaught URIError: URI malformed
    at decodeURIComponent (<anonymous>)
> decodeURIComponent((new URL(`file:///tmp/ !"$%&'()*+,-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~`)).pathname)
Uncaught URIError: URI malformed
    at decodeURIComponent (<anonymous>)

wraithgar avatar Dec 10 '24 16:12 wraithgar

This would be an issue w/ ecmascript itself, since this error also exists in browsers. The issue here is that % is not encoded in the pathname, and since it doesn't have a pair and is not a legitimate escape we get this error.

wraithgar avatar Dec 10 '24 17:12 wraithgar

Looks like this issue is handled in node via fileURLToPath

wraithgar avatar Dec 10 '24 17:12 wraithgar

(URL isn't in ecmascript, it's in WHATWG and WinterCG)

ljharb avatar Dec 10 '24 17:12 ljharb

The root cause here is that new URL doesn't actually uri encode. It looks like it does cause it encodes some things. But the new URL will happily parse a string whose components will fail URI decoding.

> new URL('http://foo.bar/path%name space')
URL {
  href: 'http://foo.bar/path%name%20space',
> encodeURI('http://foo.bar/path%name space')
'http://foo.bar/path%25name%20space'

new URL is not sufficient here.

wraithgar avatar Dec 10 '24 17:12 wraithgar