sonatype / nexus-public

Sonatype Nexus Repository Open-source codebase mirror
https://www.sonatype.com/products/repository-oss-download
Eclipse Public License 1.0
1.94k stars 572 forks source link

NPM hosted repository rejects upload of package with unicode directory in tarball #263

Open jsommer1738 opened 1 year ago

jsommer1738 commented 1 year ago
.
└── package
    ├── benchmarks
    ├── examples
    ├── lib
    ├── test
    │   └── fixtures
    │       ├── images
    │       ├── name.d
    │       ├── name.dir
    │       ├── pets
    │       └── snow ☃
    └── types

The log from Nexus3 are at the end.

** Nexus3 logs:

2023-10-06 11:15:01,771+0000 INFO  [qtp1882347405-7117] admin org.sonatype.nexus.repository.manager.internal.RepositoryManagerImpl - Creating repository: npm-hosted -> OrientConfiguration{repositoryName='npm-hosted', recipeName='npm-hosted', attributes={storage={blobStoreName=default, strictContentTypeValidation=true, writePolicy=ALLOW_ONCE}, component={proprietaryComponents=false}}}
2023-10-06 11:15:01,904+0000 INFO  [elasticsearch[4CA02C4F-8816DF79-BF8AD37D-436D90FE-C710A566][clusterService#updateTask][T#1]] *SYSTEM org.elasticsearch.cluster.metadata - [4CA02C4F-8816DF79-BF8AD37D-436D90FE-C710A566] [ba89da3cdfc6ecb9f3ce29cd6dc00b899d6c688d] creating index, cause [api], templates [], shards [1]/[0], mappings [component]
2023-10-06 11:15:02,937+0000 INFO  [elasticsearch[4CA02C4F-8816DF79-BF8AD37D-436D90FE-C710A566][clusterService#updateTask][T#1]] *SYSTEM org.elasticsearch.cluster.routing.allocation - [4CA02C4F-8816DF79-BF8AD37D-436D90FE-C710A566] Cluster health status changed from [RED] to [GREEN] (reason: [shards started [[ba89da3cdfc6ecb9f3ce29cd6dc00b899d6c688d][0]] ...]).
2023-10-06 11:19:13,857+0000 INFO  [qtp1882347405-7017] admin org.sonatype.nexus.repository.upload.internal.OrientUploadManagerImpl - Uploading component with parameters: repository="npm-hosted" format="npm" 
2023-10-06 11:19:13,857+0000 INFO  [qtp1882347405-7017] admin org.sonatype.nexus.repository.upload.internal.OrientUploadManagerImpl - Asset with parameters: file="@fastify-send-2.0.0.tgz" 
2023-10-06 11:19:13,886+0000 WARN  [qtp1882347405-7017] admin org.sonatype.nexus.siesta.internal.UnexpectedExceptionMapper - (ID 215e5b5b-75ee-47fa-a4e9-70b06df78d6c) Unexpected exception: java.lang.NullPointerException
java.lang.NullPointerException: null
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:880)
    at com.sonatype.nexus.repository.npm.internal.NpmPackageId.parse(NpmPackageId.java:126)
    at com.sonatype.nexus.repository.npm.internal.NpmMetadataUtils.createRepositoryPath(NpmMetadataUtils.java:193)
    at com.sonatype.nexus.repository.npm.NpmUploadHandler.ensureNpmPermitted(NpmUploadHandler.java:38)
    at com.sonatype.nexus.repository.npm.orient.OrientNpmUploadHandler.handle(OrientNpmUploadHandler.java:108)
    at org.sonatype.nexus.repository.upload.internal.OrientUploadManagerImpl.handle(OrientUploadManagerImpl.java:110)
    at org.sonatype.nexus.repository.rest.internal.resources.ComponentsResource.uploadComponent(ComponentsResource.java:261)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:138)
    at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:546)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:435)
    at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:396)
    at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:398)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:365)
    at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:338)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:440)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135)
    at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:358)
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215)
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:245)
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:61)
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
    at org.sonatype.nexus.siesta.internal.resteasy.ComponentContainerImpl.service(ComponentContainerImpl.java:111)
    at org.sonatype.nexus.siesta.SiestaServlet.service(SiestaServlet.java:137)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:290)
    at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:280)
    at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:184)
    at com.google.inject.servlet.DynamicServletPipeline.service(DynamicServletPipeline.java:71)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:458)
    at org.sonatype.nexus.security.SecurityFilter.executeChain(SecurityFilter.java:96)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:373)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:370)
    at org.sonatype.nexus.security.SecurityFilter.doFilterInternal(SecurityFilter.java:112)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:112)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:458)
    at org.sonatype.nexus.security.SecurityFilter.executeChain(SecurityFilter.java:96)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:373)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:370)
    at org.sonatype.nexus.security.SecurityFilter.doFilterInternal(SecurityFilter.java:112)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.sonatype.nexus.licensing.internal.LicensingRedirectFilter.doFilter(LicensingRedirectFilter.java:116)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:112)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.sonatype.nexus.internal.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:79)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.sonatype.nexus.internal.web.EnvironmentFilter.doFilter(EnvironmentFilter.java:101)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at org.sonatype.nexus.internal.web.HeaderPatternFilter.doFilter(HeaderPatternFilter.java:98)
    at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
    at com.google.inject.servlet.DynamicFilterPipeline.dispatch(DynamicFilterPipeline.java:104)
    at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:133)
    at org.sonatype.nexus.bootstrap.osgi.DelegatingFilter.doFilter(DelegatingFilter.java:73)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:201)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:239)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:516)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
    at java.lang.Thread.run(Thread.java:750)

**Docker image details:

[
    {
        "Id": "sha256:1f113e66d38149f39e69de1e246af48d8b6ffb272e384d1589d2ad275fad2b64",
        "RepoTags": [
            "sonatype/nexus3:latest"
        ],
        "RepoDigests": [
            "sonatype/nexus3@sha256:935c2ef24392cd446c9670d935378d0824ec7d7dc0d3a38902e958f400457808"
        ],
        "Parent": "",
        "Comment": "buildkit.dockerfile.v0",
        "Created": "2023-10-04T14:58:54.315617104Z",
        "Container": "",
        "ContainerConfig": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": null,
            "Cmd": null,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "DockerVersion": "",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "nexus",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "8081/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "container=oci",
                "SONATYPE_DIR=/opt/sonatype",
                "NEXUS_HOME=/opt/sonatype/nexus",
                "NEXUS_DATA=/nexus-data",
                "NEXUS_CONTEXT=",
                "SONATYPE_WORK=/opt/sonatype/sonatype-work",
                "DOCKER_TYPE=rh-docker",
                "INSTALL4J_ADD_VM_PARAMS=-Xms2703m -Xmx2703m -XX:MaxDirectMemorySize=2703m -Djava.util.prefs.userRoot=/nexus-data/javaprefs"
            ],
            "Cmd": [
                "/opt/sonatype/nexus/bin/nexus",
                "run"
            ],
            "ArgsEscaped": true,
            "Image": "",
            "Volumes": {
                "/nexus-data": {}
            },
            "WorkingDir": "/opt/sonatype",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "architecture": "x86_64",
                "build-date": "2023-09-13T02:08:28",
                "com.redhat.component": "ubi8-minimal-container",
                "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
                "com.sonatype.license": "Apache License, Version 2.0",
                "com.sonatype.name": "Nexus Repository Manager base image",
                "description": "The Nexus Repository Manager server           with universal support for popular component formats.",
                "distribution-scope": "public",
                "io.buildah.version": "1.29.0",
                "io.k8s.description": "The Nexus Repository Manager server           with universal support for popular component formats.",
                "io.k8s.display-name": "Nexus Repository Manager",
                "io.openshift.expose-services": "8081:8081",
                "io.openshift.tags": "Sonatype,Nexus,Repository Manager",
                "maintainer": "Sonatype <support@sonatype.com>",
                "name": "Nexus Repository Manager",
                "release": "3.61.0",
                "run": "docker run -d --name NAME           -p 8081:8081           IMAGE",
                "stop": "docker stop NAME",
                "summary": "The Nexus Repository Manager server           with universal support for popular component formats.",
                "url": "https://sonatype.com",
                "vcs-ref": "dee8029ddcc7ecbfbebb0905d2b15e134338616c",
                "vcs-type": "git",
                "vendor": "Sonatype",
                "version": "3.61.0-02"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 554770463,
        "VirtualSize": 554770463,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/45f96316b60cf0fba32dbf4139245d215615c0da83597d40b3d032934fa8b3e4/diff:/var/lib/docker/overlay2/238ef383fdbcc0ca47b03c6d0abb0e5f1838193a3ea4437bad9f5a4f3b3ba3c9/diff:/var/lib/docker/overlay2/d5d4384f755ca0c94bc86c7d64452a608f0ba75b88ba4b0d293a7d84e3aac0c7/diff:/var/lib/docker/overlay2/c6e0e9bdd964e0dd4a2c800c2ec6d52ec3748ba993a2355aca86fbb97a51a8d3/diff:/var/lib/docker/overlay2/723ece687359c4c8ca77d70a243052e783a5d5c945ce4f9eb7c4d34d8dc760f2/diff:/var/lib/docker/overlay2/35c18ebab69b8c34431bbc058c8ec39882a5ee1bdaa6754832c74d2e9ca3fa4b/diff",
                "MergedDir": "/var/lib/docker/overlay2/4c46ac162f675e7ba1250d976a8b662243855040d64b821ecfb98b549ebf62fc/merged",
                "UpperDir": "/var/lib/docker/overlay2/4c46ac162f675e7ba1250d976a8b662243855040d64b821ecfb98b549ebf62fc/diff",
                "WorkDir": "/var/lib/docker/overlay2/4c46ac162f675e7ba1250d976a8b662243855040d64b821ecfb98b549ebf62fc/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:3d1ae2a77d10b23a93e66fdcc48c16bd9db8518e5b5c0d44ac14d9b3d0849203",
                "sha256:899b5e38b7dc22a09a662485f54c3aafbd362f47a4af702c071f9e6f083fb29e",
                "sha256:461e9db1ea180ada05f43ef235673c36f9be1b51d216b9b0a66c0973b1b9f270",
                "sha256:b0ec63a29e4a009217dedc9b96b5abc3b6db696cfc4710dd4bcf7c81d1c03f02",
                "sha256:16e9cf22612b36d507353aac288da46bf629982a56c21dbaf06930e7f43db593",
                "sha256:a21f66a319f3ed92d93427ae3c362fe5c0ad68153470f571c0b9cab45bcf2ff1",
                "sha256:7c4c620f4f2c917b1ade01f2cf0957e83b334fbbeb691b8d84041484404114ed"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]
nblair commented 1 year ago

Thanks for this suggestion, @jsommer1738. That's certainly an odd case. I can't seem to find any official literature on what NPM supports for filenames within packages, we'll leave this open to gauge demand for this specific change.

jsommer1738 commented 1 year ago

Thanks for this suggestion, @jsommer1738. That's certainly an odd case. I can't seem to find any official literature on what NPM supports for filenames within packages, we'll leave this open to gauge demand for this specific change.

Thanks. I find this odd, because when operating in npm proxy mode, the NPM proxy is able to store the file in question. Unfortunately, I'm unable to utilize the proxy feature because I'm hosting this particular server in an air gapped network.