Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] npm config set unpacks _auth into username/password #4763

Open
2 tasks done
maikelvl opened this issue Apr 15, 2022 · 14 comments
Open
2 tasks done

[BUG] npm config set unpacks _auth into username/password #4763

maikelvl opened this issue Apr 15, 2022 · 14 comments
Labels
Bug thing that needs fixing Priority 2 secondary priority issue Release 8.x work is associated with a specific npm 8 release

Comments

@maikelvl
Copy link

maikelvl commented Apr 15, 2022

Is there an existing issue for this?

This issue exists in the latest npm version

  • I am using the latest npm

Current Behavior

npm config set registry <url> messed up pre-existing ~/.npmrc containing _auth

$ cat ~/.npmrc
//registry.npmjs.org/:username=user
//registry.npmjs.org/:_password="cGFzcw=="
registry=https://npm.example.com/

Expected Behavior

$ cat ~/.npmrc
_auth=dXNlcjpwYXNz
registry=https://npm.example.com/

Steps To Reproduce

  1. Using the latest official node container image:
    docker run -it --rm docker.io/library/node:17.9.0-alpine ash
  2. Update to the latest npm
    npm install -g npm@8.7.0
    
  3. Having a existing ~/.npmrc containing _auth:
    cat << EOF > ~/.npmrc
    _auth=$(echo -n 'user:pass' | base64)
    EOF
  4. Set the container registry:
    npm config set registry https://npm.example.com
  5. Now the .npmrc is messed up cat ~/.npmrc:
    //registry.npmjs.org/:username=user
    //registry.npmjs.org/:_password="cGFzcw=="
    registry=https://npm.example.com/
    

Environment

  • npm: v8.5.0 v8.7.0
  • Node.js: v16.14.2 v17.9.0
  • OS Name: Alpine Linux v3.11 v3.15
  • System Model Name: Linux (in VM)
  • npm config: (empty before reproduction)
@maikelvl maikelvl added Bug thing that needs fixing Needs Triage needs review for next steps Release 8.x work is associated with a specific npm 8 release labels Apr 15, 2022
@ljharb
Copy link
Collaborator

ljharb commented Apr 15, 2022

That looks conceptually the same even if the contents are different. Does it authenticate properly with the registry?

also have you tried with npm v8.7?

@maikelvl
Copy link
Author

No, it does not authenticate properly since the _auth is removed. I opened this issue because #2300 seemed to be marked as 'fixed'.

I expected running the latest node also using the latest npm, but that was not the case. Version 8.7.0 has the same issue.

@ljharb
Copy link
Collaborator

ljharb commented Apr 15, 2022

The latest node is node 17, not 16, but also npm publishes more frequently than node releases :-)

@fritzy
Copy link
Contributor

fritzy commented Apr 15, 2022

I was able to reproduce, thank you for the reproduction steps.

@fritzy fritzy added Priority 2 secondary priority issue and removed Needs Triage needs review for next steps labels Apr 15, 2022
@maikelvl
Copy link
Author

That's right. I picked the latest LTS.
The issue also occurs on node v17.

@fritzy fritzy changed the title [BUG] npm config set messes up ~/.npmrc [BUG] npm config set registry removes _auth Apr 15, 2022
@wraithgar
Copy link
Member

This is the correct behavior. the _auth token only ever works on the npm registry, it won't be sent to other registries. When you log in npm cleans up the old _auth entry and adds a registry specifier to it. The fact that it transforms it to username/password is because the _auth entry is just a base64 encoded username and password.

It's a little jarring I'm sure to see it change from _auth to its constituent parts and we should keep this on the backlog to eventually see if it's possible to keep _auth as _auth. But this is not going to break your install, it's going to make your config more specific.

@wraithgar wraithgar changed the title [BUG] npm config set registry removes _auth [BUG] npm config set unpacks _auth into username/password Apr 21, 2022
@maikelvl
Copy link
Author

Thanks for your explanation.


only ever works on the npm registry, it won't be sent to other registries.

I don't think that's correct since an .npmrc like below authenticates just fine against our self-hosted Jfrog npm registry.

_auth=dXNlcjpwYXNz
registry=https://npm.example.com/

But this is not going to break your install,

It is breaking because it now sets authentication explicit to registry.npmjs.com where before it was using _auth to npm.example.com before

//registry.npmjs.org/:username=user
//registry.npmjs.org/:_password="cGFzcw=="
registry=https://npm.example.com/

As a workaround I just have the contents of .npmrc defined instead of generating it.

I'm fine accepting this change since it's a regression between major versions v14 and v15/v16/v17.

@wraithgar
Copy link
Member

Ok so this is very helpful. I just added tests yesterday that I thought clarified this behavior but there is a difference between setting a registry via scope and setting the registry config item. _auth will go to whatever is specified in registry. I'll have to add a test to show that.

The reason it's doing what it's doing here is because the "config cleanup" code happens before the config set is applied. So the default registry is what is still in that value when it "nerf darts" (as we call it) the auth to the configured registry. The nerf darting of _auth to the configured registry is behavior that is not changing, it's a security issue and is intentional.

It's still weird because it's unpacking it to username/password but functionally those are the same.

@wraithgar
Copy link
Member

wraithgar commented Apr 21, 2022

It's a little goofy but I think if you did npm config set registry http://other.registry.com --registry=http://other.registry.com it would nerf dart your auth to the right registry.

@ljharb
Copy link
Collaborator

ljharb commented Apr 21, 2022

Why is that intentional? It seems pretty bad to do something the user didn’t ask for.

@wraithgar
Copy link
Member

The nerf darting is what the config actually is, having it as the legacy bare _auth is misleading and confusing. Unpacking it to username/password is unintentional and odd, even though that too is functionally the same thing.

@ljharb
Copy link
Collaborator

ljharb commented Apr 21, 2022

What i mean is, if i have something in npmrc, and i npm config set something else, the something should never change, because that’s not what i asked npm to do. Whether it’s misleading or not is none of npm’s business because i didn’t ask npm to touch it.

@mrdezzods
Copy link

mrdezzods commented Apr 29, 2022

This worked for us

@isaacs
Copy link
Contributor

isaacs commented May 25, 2023

What i mean is, if i have something in npmrc, and i npm config set something else, the something should never change, because that’s not what i asked npm to do. Whether it’s misleading or not is none of npm’s business because i didn’t ask npm to touch it.

Historically, a bare _auth will be sent to the current default registry, which might not be the registry you authed against. This is a serious security hole if left unchecked, because it means possibly sending your credentials to some random third party, and anyone would be able to steal your npm token with "dependencies": {"evil": "https://something-evil.com/package.tgz"}, which would be even harder to detect if it's in optionalDependencies, and doesn't resolve.

npm has no way of knowing what you intended your registry for that auth token to be, other than what's in the config at the time it encounters the _auth value. So if it sees that _auth field, it immediately scopes it to the current registry before proceeding to do anything else, so that it can't be sent anywhere it shouldn't be.

The only workaround is to ensure that the registry config is present the first time that npm encounters the bare _auth field. That's what @wraithgar's suggested command does, but you can also npm config set registry=whatever before appending the _auth field into the .npmrc, or write it in its registry-scoped form initially.

This is 100% working as designed, and the confusion is an unfortunate byproduct of a very old mistake. Changing this behavior would be a very bad idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Priority 2 secondary priority issue Release 8.x work is associated with a specific npm 8 release
Projects
None yet
Development

No branches or pull requests

6 participants