Comments (10)
this approach would concern me a bit. considering a worm like was attempted with eslint, the environment variables could be stolen just as easily as the token. while this is a creative way to make this work, i'd really hesitate to expose the 2fa secret to anything other than my 2fa app, such as google authenticator or authy because of opening up the account to further risk.
imho, i think a better approach would be to have the ability to require 2fa for auth-and-writes
, but exclude very specific tokens, such as the ones used by semantic-release
. since semantic-release
is intended to be run from CI, limiting the CIDR ranges allowed for that token should be enough to make up for that exception. obviously, npm does not support 2fa enforcement exceptions, but i've mentioned the idea to the team. maybe a few more voices around that topic would help reinforce the importance of the automated use case.
from npm.
Getting back to this - there is now a PoC server for remote OTP requests: https://github.com/nearform/optic
How it works:
- It's a web app which allows you to store a local OTP secret to generate OTP codes (the easy bit)
- There's an API which allows you to "request" a specific OTP
- The client receives a notification and can approve/reject
All secrets always stay on the client (i.e. your phone).
You can try it out, I've deployed it here (no SLA): https://optic.goodnight.to
- Use Chrome/Chrome for Android
- Sign-in - only Google for now, mostly due to lack of time - it's a PoC after all
- Allow notifications (that's the whole point, right)
- Add a secret (go for manual, if you're just playing, enter whatever you like in Issuer/Secret)
- Click the
+
to generate a token - You should now be able to
curl -s https://optic.goodnight.to/api/generate/[your token]
- When you hit the URL, a notification should appear in your browser
- Hit "Approve" - the
curl
will now receive a response with the currently active OTP
I'm more than happy to answer any questions or jump on a call to give a quick demo and build a PR to support the concept. This brings a true 2FA for fully automated semantic-release
s.
There's gotchas and caveats and more work to be done, but I figure it's a start?
from npm.
not suggesting that this is a problem for all use cases, but i would still find this a step backward
I very much agree with your suggestion to have tokens which are non-2FA (or rather to limit their use to a CIDR range)!
However, that is not always enough. There's different levels of security required for different contexts. There's also different ways to implement this (e.g. you could have a 2FA service which automatically responds with an OTP without a user interaction).
from npm.
i'm actually interested in thoughts that the npm security team might have in this area. @evilpacket, would you or someone from you team be willing to discuss this use case in more detail? i think it would be a big help those of use that publish automatically from a non-interactive CI service to make sure we are considering what your team might already have in mind. (is there a better place for that conversation than this issue thread?)
from npm.
I didn't know you could limit the source IP with --cidr
. That's a great point and we should at least mention it in the documentation.
However anyone can run anything on a Travis image. So if your token is compromised that won't help you much, as the person having your token can just create a Travis job to publish with the token.
In the proposal above nothing would change if you don't enable 2FA auth-and-writes
for the user associated with your token. semantic-release would look for NPM_2FA_SECRET
only if the npm account associated with the token has 2FA enabled with auth-and-writes
.
So you could continue to use semantic-release with npm the way you do now.
Finally the point of enabling 2FA with auth-and-writes
is to prevent letting a hacker to publish a package when your password (not your token) is compromised.
Having NPM_TOKEN
in a Travis variable is the same as having NPM_TOKEN
+ NPM_2FA_SECRET
. If your Travis variables are compromised then in both case your account is compromised. There is no way around that as we want Travis to be able to publish.
As a recap:
- With
NPM_TOKEN
on Travis and 2FAauth-only
:- If your Travis variables are compromised, then the hacker can publish a new version of your package
- If your password is compromised, then the hacker can publish a new version of your package
- With
NPM_TOKEN
andNPM_2FA_SECRET
on Travis and 2FAauth-and-writes
:- If your Travis variables are compromised, then the hacker can publish a new version of your package
- If your password is compromised, then the hacker cannot do anything
So the solution 2 is still a lot better as it protect you if your password is compromised. This is what happened to the ESLint contributor. And this is a lot more likely to happens than having Travis variables compromised as users tends to have weak passwords and re-use the same one everywhere.
from npm.
However anyone can run anything on a Travis image. So if your token is compromised that won't help you much, as the person having your token can just create a Travis job to publish with the token.
agreed, but the difficulty of using the token is significantly reduced. while it is not difficult to run on a travis instance, it does take more work than just using the token on the attacker's machine. it also puts the attacker at more risk of being discovered using the stolen token. even beyond all of that though, the attacker needs to somehow know what the cidr restriction of the token is, which would require them to have tracked where they stole the token from (i just verified that npm token ls
responds with a 403
if used a cidr restricted token is used outside of the IPs defined in the restriction).
So you could continue to use semantic-release with npm the way you do now.
this would be what I would probably do due to the risk of possibly exposing the 2fa secret. however, the reason i raised the question was that it seems to me like a severe enough risk, even if unlikely (though the eslint worm could have easily grabbed this info if it was looking for it), that we may not want to enable/encourage the potential of the leak.
If your Travis variables are compromised then in both case your account is compromised.
yes and no. as mentioned above, the attacker would somehow have to know what CIDRs are allowed for the token (hard), have access to run on an instance within the restriction (simple for travis, but maybe impossible in other cases), and actually run on said instance (more work and potentially higher risk for the attacker).
If your password is compromised, then the hacker can publish a new version of your package
So the solution 2 is still a lot better as it protect you if your password is compromised.
2fa for auth
only still provides much of the same protection, at least if the token used by semantic-release
is CIDR restricted. even if you have someone's password and can log into their account, you cannot create a new token for the account without entering the one-time token (this must have been changed after the eslint incident). unless an attacker gets access to an existing token and that token is not CIDR restricted or the attacker can figure out how to use it within the restriction, the password alone does not give them the ability to publish.
this gets better if we can convince npm to allow enabling 2fa for auth-and-writes
, but exclude certain tokens (maybe only if they are CIDR restricted). even better than that, i'd love to only enable our bot user to even be able to get publish tokens, only allowing read-only tokens for everyone else. pre-releases are the only reason we publish anything outside of semantic-release
today, and you are already working on supporting those use cases.
from npm.
i've started an RFC related to the token 2fa rules i mentioned above. still needs work, but wanted to add visibility here. feel free to provide thoughts there if it will help here.
from npm.
Would you accept a PR to add an option for otpUrl
? The implementation would fire a GET
request to the URL, and use the response as the OTP.
The implementation of the server can, e.g., send a push notification to a mobile phone, and the phone can then respond with the OTP if the user permits that. I know a sample server is in the works, I don't know when it's going public, but I'd like to start testing it :)
A more flexible approach could be an option for otpCommand
(which would exec a command, e.g. curl
or whatever floats your boat). A less flexible approach would be to rely on an env var (which means another plugin could set it; setting it before calling semantic-release
is probably a bad idea, as things may take long enough for the OTP to expire).
from npm.
The client receives a notification and can approve/reject
not suggesting that this is a problem for all use cases, but i would still find this a step backward. a big part of the value of semantic-release for me is that it can publish new versions while i'm sleeping, etc. needing to interact even to approve/reject removes the ability to automate to that level.
from npm.
Opened a PR for otpUrl
option: #176, tested using https://github.com/nearform/optic on one of my own packages.
Still not sure how to assert in tests that --otp
was passed through - possibly need to add a proxy around the couch app - ideas welcome.
from npm.
Related Issues (20)
- `package.json` version not updated, despite correct plugin ordering HOT 1
- Set --no-workspaces with npm version HOT 2
- Command failed with exit code 1: npm version 0.22.2 --userconfig HOT 2
- error on publishing HOT 1
- Publishing failed since update from [email protected] to [email protected] with files mentioned in .gitignore HOT 6
- Update a package.json in a sub folder
- CVE-2023-42282 HOT 1
- Support for custom package.json properties to write changelist entries
- NPM Audit Signatures issue on 11.0.3 HOT 2
- Failed step "prepare" of plugin "@semantic-release/npm" due to reading malformed path HOT 13
- ERR_INVALID_AUTH triggered by semantic-release npm despite not having this field set in checkout directory HOT 11
- semantic-release seems publishing twice and causing error. HOT 1
- Security Issue with out of date [email protected] found with SNYK HOT 3
- Array format/style is being changed HOT 3
- improve auth token resolution
- align approach for concatenating `.npmrc` files to better align with default npm behavior
- account for deprecation of `_auth` in existing `.npmrc` files
- Cannot set properties of null (setting 'peer') HOT 4
- npm ERR! log.http is not a function HOT 4
- [Question] monorepo project HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from npm.