npm-package-arg
npm-package-arg copied to clipboard
[BUG] Failed to decode path name with valid symbols
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
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?
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>)
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.
Looks like this issue is handled in node via fileURLToPath
(URL isn't in ecmascript, it's in WHATWG and WinterCG)
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.