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

fix: prototype poisoning (CWE-915) #3192

Closed
wants to merge 1 commit into from
Closed

Conversation

Marynk
Copy link

@Marynk Marynk commented Oct 11, 2021

NOTE from the project maintainer: Security Professionals: Please read the whole thread before accepting this at face value. This is not a real vulnerability! We're just trying to get the CVE folks to understand that (or even to respond to us. ☹️)


Added protection from prototype poisoning to mapObjIndexed().
For Proof of Concept exploit of the vulnerability visit https://jsfiddle.net/3pomzw5g/2/

Added protection from prototype poisoning to mapObjIndexed()
// Prevention of prototype poisoning
if (key !== "__proto__" && key !== "prototype" && key !== "constructor") {
acc[key] = fn(obj[key], key, obj);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me but I think we could have a test to make sure it doesn't happen again.
Basically what's in your JSFiddle could be the basis for a regression test.
What do you think?

@customcommander
Copy link
Member

I also wonder whether this would apply to other things? I'm thinking perhaps prop & path functions or lenses? I don't know I haven't checked yet.

Copy link
Member

@CrossEye CrossEye left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not only are there changes that need to be made, I'm not convinced this is actually what prototype poisoning is about.

I had to think it through a bit, and will leave a more detailed comment below.

@@ -26,7 +26,10 @@ import keys from './keys.js';
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would definitely need to update the documentation too.

@@ -26,7 +26,10 @@ import keys from './keys.js';
*/
var mapObjIndexed = _curry2(function mapObjIndexed(fn, obj) {
return _reduce(function(acc, key) {
acc[key] = fn(obj[key], key, obj);
// Prevention of prototype poisoning
if (key !== "__proto__" && key !== "prototype" && key !== "constructor") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand __proto__ and constructor. Is there an attack here that uses prototype directly?

@CrossEye
Copy link
Member

CrossEye commented Oct 12, 2021

I think "prototype poisoning" is about altering the prototype of core js elements such as Object. The idea is not that you could merge a prototype into a newly created object, but that by altering, say, Object .prototype, you can change the behavior of existing objects.

The canonical example seems to look like this:

const naiveMerge = (a, b) => {
  // Just to illustrate the problem.  But could happen with a real recursive merge
  Object .entries (b) .forEach (([k, v]) => 
    Object .keys (v) .forEach (inner => a[k][inner] = v[inner])
  )
  return a                      
}

// This user has no `isAdmin` field
const user = {name: 'fred'}
console.log(`Before: ${user.isAdmin}`); //=> undefined

// We get this from some perhaps-untrustworthy source
const maliciousUserInput = '{"__proto__": {"isAdmin": true}}'
// but we're smart enough to sanitize it with
const ourObject = naiveMerge ({}, JSON.parse(maliciousUserInput)) 
// However, naiveMerge adds `isAdmin` to `Object.prototype`, with value `true`

// And now that same user has `isAdmin` set
console.log(`After: ${user.isAdmin}`); //=> true !!!

// if we call naiveMerge again we get an error.
// But a less naive version might go undetected.

Both jQuery and lodash were caught by this. I don't think it's true for Ramda because of our immutable design. It doesn't happen if we use R.merge (or R.mapObjIndexed). But I'm far from certain that it could never happen. I think this suggests a cleanup where we make sure any place we add properties to a blank object starts with Object .create (null) rather than {}.

But I don't think we need this change just yet.

@customcommander
Copy link
Member

@CrossEye What about this though?

const isAdmin = o => o.admin == true;
const check = compose(isAdmin, mapObjIndexed(identity));

check(JSON.parse('{"__proto__":{"admin":true}}'));
//=> true

I think the concern is that with __proto__ an attacker could try to sneak in some extra properties.

@CrossEye
Copy link
Member

@customcommander:

But that's a very different attack surface. If you are creating your user account by JSON-parsing something from an untrustworthy source, then they could just as well pass you '{"admin": true}'. That they sneak it into the prototype is not a big deal. But if your sprawling web app uses some third-party API for a trivial bit of fluff and that API is compromised, a true prototype poisoning would mean that your previously secure user object (in JS: ha!) now suddenly can get admin privileges.

The problem is not with what happens with this object, but with what it allows on all other objects.

It's these sorts of things that I think people are worried about:

That's a real worry, and I'm far from certain Ramda doesn't have any such issues. I think we need to go through it to check.

But I'm less worried about isAdmin slipping into the object we're actually creating.

@Marynk
Copy link
Author

Marynk commented Oct 12, 2021

@CrossEye To continue the isAdmin example, the application developer could be using a check for prohibited properties, thus preventing direct injection of isAdmin: true. Since the initial object (hasOwn in the JSFiddle) doesn't in fact have that property, it would be able to bypass such checks.

Considering including "prototype" in the check - it is a common practice to account for all 3 properties, as they are known to be exploited in similar scenarios. I agree that in this case it is unnecessary, however I would suggest to keep it in case something changes in the implementation (e.g. recursive version of property assignment).

@CrossEye
Copy link
Member

@Marynk:

Do you have examples of CVEs for this problem, or prior art of prohibiting those properties?

What I'm worried about is suddenly having magical property names we can no longer support. Users might have legitimate needs for prototype or constructor. I am much less worried about __proto__. Someone who claims that name as a business requirement is probably not being honest.

I don't want to diminish the issue here. It's worth discussing. But now that you've brought up prototype poisoning, I think it's much more important to test whether this can happen in Ramda.

@yanruzhang
Copy link

@CrossEye :

We are a consumer of ramda, and got a VULN ticket to fix this Prototype Pollution vulnerability found in ramda. Just want to know if there are any tests set up to confirm if this issue can happen in Ramda? or if we can adopt the changes in this PR to fix this issue?

@CrossEye
Copy link
Member

CrossEye commented Nov 9, 2021

@yanruzhang: I know nothing about such VULN tickets. I don't have any sources for this. I would hope that whatever gave you such a ticket would be able to give you information as well. (And I hope you would share that with us!)

The code here is for a specific function and IMHO the test case does not actual demonstrate that vulnerability. But that does not mean there is not one around, in this or another function. But I'd like to see evidence of the problem before worrying about solutions.

@yanruzhang
Copy link

The VULN ticket is a kind of ticket we use to fix vulnerability issues. There's one about Ramda, and more specifically, _curry2 function 👇 , which this PR seems want to address.

image

Do you mean this _curry2 function doesn't actually have Prototype Pollution vulnerability?

@CrossEye
Copy link
Member

CrossEye commented Nov 9, 2021

@yanruzhang: This PR is not about _curry2; it's about mapObjIndexed.

But can you tell me the source of that report? I haven't seen any reports of Prototype Pollution in Ramda, except for this issue, which I think is invalid, and I've been looking around for references to it in various sources, but I don't know much about them. What generates that report for you? Does it have an online reference to the vulnerability?

_curry2 almost certainly does not have such a vulnerability, but it's commonly used to wrap other functions, and if there is a vulnerability, it's conceivable that the system simply wasn't sophisticated enough to find the true source of it. But without knowing where it's from, it's very hard to tell.

@yanruzhang
Copy link

@CrossEye
Copy link
Member

CrossEye commented Nov 9, 2021

@yanruzhang: I did find that one in further research, but I can't find anywhere it gives a demo of the supposed vulnerability. I'll keep looking, but that site seems pretty damned opaque. Do you know anything about it?

@yanruzhang
Copy link

@CrossEye
Sometime they don’t tell how to reproduce the vulnerability issue. Thanks for further looking into it, and we'd appreciate if you could let us know when you confirm if this can actually happen to ramda:
An attacker can inject properties into existing construct prototypes via the _curry2function and modify attributes such asproto, constructor, and prototype

@CrossEye
Copy link
Member

CrossEye commented Nov 11, 2021

@yanruzhang:

If that's all the information we can get, then I'm pretty sure I can simply say no, that cannot happen.

_curry2 depends on _isPlaceholder and _curry1. curry1 depends on isPlaceholder. Outside the calls to these internal functions, curry1 and curry2 only call the function supplied as a parameter. And isPlaceholder checks the typeof of the supplied object and tests whether a specific string property of that object is true. None of this can change the prototype of any object.

If you want to dig through every Ramda function to see if there's some possible prototype pollution, feel free. Otherwise, I feel it's incumbent upon the reporter to demonstrate the existence of a problem. But I can find no more information from veracode. I've reached out to them but not heard back.

The simplest thing I can think of to check is the sort of canonical prototype pollution; the Ramda equivalent does not share the issue. So my first thought is that no, this is not a real issue.

The code supplied in this PR also does not demonstrate prototype pollution either.

Without an actual demonstration, I'm not sure where to go. I don't want to close this. What I really want is to find out what veracode says in an actual problem. But I don't have any idea how to pursue it. Any ideas?

@CrossEye CrossEye mentioned this pull request Nov 11, 2021
@CrossEye
Copy link
Member

I've posted a question in StackOverflow about this: https://stackoverflow.com/q/69936667.

Perhaps someone there will have some information.

@CrossEye
Copy link
Member

CrossEye commented Nov 22, 2021

So I've heard back from Veracode, and their source for the issue is this PR.

I will need to spend some time to thoroughly write up my objection. But it's pretty clear to me that this does not do what's described as prototype pollution. That you can create an object with a prototype is not prototype pollution. Or if it is, then libraries are irrelevant, as a simple tweak to the original Fiddle shows that the same thing is true for Object.assign.

The snyk lodash report has a good test case for prototype pollution:

const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"a0": true}}}'

function check() {
    mergeFn({}, JSON.parse(payload));
    if (({})[`a0`] === true) {
        console.log(`Vulnerable to Prototype Pollution via ${payload}`);
    }
  }

check();

The closest Ramda equivalent is mergeDeepRight, and that does not share this problem. Nor does mapObjIndexed; I will try to write up a full explanation to share with the Veracode team, although that might be time-consuming.

@CrossEye
Copy link
Member

Below is a response I've drafted to send to Veracode. Does anyone have any suggested improvements?

@ramda/core

Overview

There seems to be an erroneous vulnerability report in Veracode, saying that Ramda is subject to prototype pollution.

While we certainly have not definitively demonstrated that nothing in Ramda has this vulnerability, the examples so far are not examples of prototype pollution, only of the ability to create objects that the user didn't know would contain custom prototypes.

It seems like this report should be withdrawn.

Prototype Pollution

Prototype pollution is the ability for crafted input supplied to a generic function to the alter the prototype of built-in JavaScript constructs, such as Object.

One example, from a WhiteSource blog, is:

const getObject = require('getobject');
var obj = {}; 
var obj2 = 1; 
console.log("Before Polluting : " + obj2.Check);  //~> 'Before Polluting : undefined'
getObject.set(obj, "__proto__.Check", "polluted");
console.log("After Polluting: " + obj2.Check);  //~> 'After Polluting: polluted'

Another one, closer to the case in question, from a snyk vulnerability report, looks like this:

const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"a0": true}}}'

function check() {
    mergeFn({}, JSON.parse(payload));
    if (({})[`a0`] === true) {
        console.log(`Vulnerable to Prototype Pollution via ${payload}`);
    }
  }

check(); //~> 'Vulnerable to Prototype Pollution via {"constructor": {"prototype": {"a0": true}}}'

What these have in common is that calling getObject.set or lodash.defaultsDeep modifies the prototype of the built-in Object, and thus they affect the behavior not just of the resulting object they return but also of any existing JavaScript objects and any newly created ones. This would allow a malicious user to perform denial-of-service attacks and even perform actions without proper permissions, such as modifying or deleting data in a Node.js application.

History

A Veracode vulnerability report said:

ramda is vulnerable to prototype pollution. An attacker can inject properties into existing construct prototypes via the _curry2 function and modify attributes such as __proto__, constructor, and prototype.

It has recently been updated to say this instead:

ramda is vulnerable to prototype pollution. An attacker is able to inject and modify attributes of an object through the mapObjIndexed function via the __proto__ property.

(It seems that this update was only in the last day or so, but that's not entirely clear.)

This was brought to our attention by a comment on an open issue in Ramda. That issue, as discussed below, does not demonstrate prototype pollution, although it's an understandable mistake. The commenter was able to point us to that report, but there was no other information available.

I am one of the founder of Ramda and currently its chief maintainer. I reached out through Veracode's contact form online asking for more details. When I didn't hear back in a few days, I dug a bit deeper and found contact emails online as well. I emailed them, and a few days later got a response from a salesperson who thought I was in the market to buy their product. I explained the problem and was told that this would be forwarded to someone who might know more. Today, I heard back from someone else, a sales manager who had spoken to the technical team, who explained

We have based this artifact from the information available in #3192. In the Pull Request, there is a POC (https://jsfiddle.net/3pomzw5g/2/) clearly demonstrating the prototype pollution vulnerability in the mapObjIndexed function. In the demo, the user object is modified via the __proto__ property and is considered a violation to the Integrity of the CIA triad. This has been reflected in our CVSS scoring for this vulnerability in our vuln db.

There is also an unmerged fix for the vulnerability which has also been included in our artifact ( 774f767 )

In other words, the issue that was used to comment on Veracode's vulnerability report was earlier the issue which triggered the report. Oh my aching head! 😄

That response continued:

Please let me know if there is a dispute against the POC, and we can look further into this.

This document is my attempt to explain the issue and thoroughly explore the reported vulnerability.

Reported Vulnerability

The reported issue was demonstrated with the code on a Fiddle. It looks like this:

const hasOwn = JSON.parse('{"__proto__": {"isAdmin": true}}');
console.log(hasOwn.isAdmin); //~> undefined
const mapped = R.mapObjIndexed((val) => val, hasOwn);
console.log(mapped.isAdmin); //~> true

Note that hasOwn does not have isAdmin in its prototype, but mapped does have it.

The suggestion is that because of this Ramda's mapObjIndexed can cause prototype pollution.

Dispute

All the top answers on a search for "prototype pollution" have variants of the description on codeburst:

Prototype Pollution, as the name suggests, is about polluting the prototype of a base object which can sometimes lead to arbitrary code execution.

The above code does not do so. It does not pollute the base objects. It simply offers a surprising way to adjust the prototype of one specific object. And this behavior has little to do with Ramda; it's part of the base language as well. If we replaced the call to Ramda's mapObjIndexed with one to JavaScript's Object.assign, we get the exact same behavior. As far as I can tell, there is no report out against Object.assign for prototype pollution.

Another way to look at it is to view some slight variants of the snyk demonstration above for mergeDeepRight and mapObjIndexed. In each of these cases, the vulnerability is not found.

There's a reason these exploits are usually mentioned in combination of path-setting or deep merging and that they usually involve JSON.parse: The usage of JSON.parse allows the code to create the __proto__ node without actually updating the prototype directly. And then many deep-merge and path-setting functions work by mutating their input parameter with the values supplied. In combination, that means that these tools will eventually do a deep set of someObject .__proto__ .isAdmin, and since a plain object supplied, someObject .__proto__ will be Object .prototype, which is then mutated to include isAdmin.

Ramda's design is different. One of its guarantees is that it never mutates input data. Ramda's equivalent of a deep set, assocPath, does not add properties to your object. Instead it returns a new object, with all properties copied over from the old one and with your new property added or altered on this clone. The various merge functions operate similarly.

That means there is a wall between the data you're trying to insert and the underlying Object prototype. It's not clear if this wall is unbreachable, but it's more difficult than in the jQuery or lodash cases, where immutability is not the default. While avoiding such an exploit was not a reason for Ramda's immutable design, it is a good demonstration of the advantages it offers.

So this vulnerability report was based on an invalid GitHub issue. The Ramda team will close that issue soon. In fact, it was only because of this report that it's been left open.

Can the Veracode team remove this entry from its database?

Follow-up

The history above was a dry recital of the order of events, but it has been a very frustrating process. Would it be possible for Veracode's online reports to either directly include or offer a link to supporting evidence? Here if the report linked back to the GitHub issue or supplied a proof-of-concept of the vulnerability, the Ramda team could have responded to this much more effectively. Or, if that's not appropriate because they are reported before the team has a chance to work on the issue, could the report offer a "Challenge this finding" link with a way for tool maintainers to do what I've done?

@customcommander
Copy link
Member

@CrossEye So the GH issue was opened to fix an alleged vulnerability which VeraCode illustrated with my own example which wasn't even close to describing an actual prototype pollution? Bit confused right now.

Thanks for looking into this! LGTM

@CrossEye CrossEye closed this Nov 23, 2021
@CrossEye
Copy link
Member

I've had no response yet, but now they've changed the description to:

ramda allows object prototype manipulation. An attacker is able to inject and modify attributes of an object through the mapObjIndexed function via the __proto__ property. However, due to ramda's design where object immutability is the default, the impact of this vulnerability is limited to the scope of the object instead of the underlying object prototype. Nonetheless, the possibility of object prototype manipulation as demonstrated in the proof-of-concept under References can potentially cause unexpected behaviors in the application. There are currently no known exploits.

(Of course References is not a link, and appears nowhere else on that page.)

I'm trying to decide if I want to get snarky and ask if they've filed the same issue against Object .assign. Probably not at least until they respond.

For now, though, the only response seems to be that I've been added to their marketing email list. 😦

@Dr1Ku
Copy link

Dr1Ku commented Nov 24, 2021

Hey Scott, really appreciate you looking into this. Longtime fan and user of Ramda here!

Through my enterprise employer's account with VeraCode itself I was able to see the References tab/section,
here's what's in it:

image

Thus, their proof-of-concept is: https://jsfiddle.net/3pomzw5g/2/
(added below for completeness):

// when objects are parsed, all properties are created as own (the objects can come from outside sources 
// (http requests/ file))
const hasOwn = JSON.parse('{"__proto__": {"isAdmin": true}}');

// does not have the property,  because it's inside object's own "__proto__"
console.log(hasOwn.isAdmin);

const mapped = R.mapObjIndexed((val) => val, hasOwn);

// after the method executes, hasOwn.__proto__ value (isAdmin: true) replaces the prototype of 
// the newly created object, leading to potential exploits.
console.log(mapped.isAdmin);

The other links merely reference this PR and the mitigation commit.

And yes, quite wacky that one has to be logged in to be able to see a public vuln.. Hope this helps!

@CrossEye
Copy link
Member

@Dr1Ku:

Thank you very much. That helps a lot. It confirms what I suspected from their email.

I feel as though they've changed only their description in response to my dispute. But at least I believe it's progress.

Also, "wacky" is a much more polite word than most of the ones I had in mind! 😄

@Dr1Ku
Copy link

Dr1Ku commented Nov 25, 2021

Hey Scott, sure no worries. Yes I think they reacted to your email at least :D And apparently it's a been classified as a "SourceClear Premium (No CVE)" 'disclosure' (more like 'opinion piece'!) which renders the details and -worst of it all- the PoC viewable for logged-in customers only.. what a way to treat FOSS! Within my sphere of influence (read: project) we're going to go for bandaids like using more ramda-adjunct and temporarily ousting ramda just to jump through some compliance hoops, oh well.

@CrossEye
Copy link
Member

After no response for a week, I've sent the following to Veracode:

Hi Folks,

I'm wondering if there is any response to this.

I see that the vulnerability report has been updated but not removed. I still dispute the altered version of it. If this behavior is a true vulnerability, could you point me to the equivalent report on JavaScript's Object.assign, which, as demonstrated earlier, has the exact same issue as the function in question.

My immediate goal is to see this report retracted. But I also want to point out the pain involved in this process, pain that I think Veracode could fix:

I am not a customer, but your customers are coming to me as Ramda's maintainer to fix a problem you've reported. That report really should have enough information in it to allow me to confirm the vulnerability reported. I've learned that such information is available to a logged-in customer. That doesn't help me or others in my position to find the information. Resorting to email and filtering it through your sales department, is a pretty horrible process. Could you alter your public reports to contain or point to a proof of concept of the vulnerability? And could you further offer in the report some hint at a dispute process?

Thank you,

-- Scott

I've got to say this is extremely frustrating.

@CrossEye
Copy link
Member

CrossEye commented Dec 6, 2021

I added an answer to the StackOverflow question, summing up the experience with this issue and Veracode.

@assaf-benjosef
Copy link

assaf-benjosef commented May 10, 2022

@CrossEye @customcommander hey folks, seems like someone assigned CVE-2021-42581 for this? assuming it should be disputed?

@CrossEye
Copy link
Member

@assaf-benjosef: Oh no, it's back!! I have several evenings free this week and I'll try to take a look. Do you know anything about the dispute resolution procedure. I'm hoping it's easier than my Veracode experience.

@assaf-benjosef
Copy link

@CrossEye I believe this form would be the best bet: https://cveform.mitre.org/
Should make a rejection change request there, they usually respond back in a couple days :)

@CrossEye
Copy link
Member

@assaf-benjosef:

Thank you. I made this request:

I would like to see this vulnerability rejected.

The behavior mentioned in the original GitHub Pull Request that started this process is not prototype pollution. While it can be used to create and alter the prototype of a specific object, it can not modify preexisting objects' prototypes.

The github link supplied is where this started. The requested change was rejected, because this was not prototype pollution. Veracode, though, reported it as an error to their users, and the stackoverflow link explains the arduous process it took to get them to reject this vulnerability.

The other two links are to the Ramda REPL. One shows an example of how a library might be subject to prototype pollution. The second shows the equivalent Ramda code, which does not exhibit the same behavior.

Feel free to email me with follow-up questions: scott@sauyet.com.

#3192
https://stackoverflow.com/a/70239612
http://link.fourwindssoft.com/52
http://link.fourwindssoft.com/53

We'll see what happens now.

@dbolkensteyn
Copy link

dbolkensteyn commented May 20, 2022

Interestingly Snyk.io has also added CVE-2021-42581 to their database, but only for Grafana packages, which I suppose depend on this library.

@dbolkensteyn
Copy link

Well this appears to be a "malicious CVE"... the description mentions 0.27.0 as affected version, even when 0.27.1 was already released. That kind of implies that 0.27.1 was released as a fix for the reported vulnerability, increasing its credibility.

@CrossEye MITRE is the CNA who issues. I'm curious if they can tell you who asked them to submit this 10 days ago. @Marynk Was that you?

@assaf-benjosef
Copy link

Interestingly Snyk.io has also added CVE-2021-42581 to their database, but only for Grafana packages, which I suppose depend on this library.

ahh seems like it was automatically created as a linux vulnerability due to a few distros adding this to their advisory database. It will be automatically revoked from snyk.io once the CVE is revoked. What we had control over was the decision of publishing an advisory against the independent ramda NPM package, which we did not do.

Did MITRE not reply to your request yet @CrossEye ?

@CrossEye
Copy link
Member

@assaf-benjosef:

Nothing from MITRE. This is starting to feel like Veracode all over again.

@dbolkensteyn:

I won't have time this evening, but will try to get more out of MITRE tomorrow. After the dead silence on my previous message, I'm not really hopeful, however.

@CrossEye
Copy link
Member

Just sent another request to Mitre. The first one was never even acknowledged. Trying a different email address just in case.

I would like to see this vulnerability rejected. This is the second time I submit this. I heard nothing, not even an automated reply, the first time: 2022-05-10. I've supplied a different email address in case that was the issue.

The behavior mentioned in the original GitHub Pull Request that started this process is not prototype pollution. While it can be used to create and alter the prototype of a specific object, it can not modify preexisting objects' prototypes, and especially cannot modify built-in prototypes such as Object.prototype.

The github link supplied is where this started. The requested change was rejected, because this was not prototype pollution. Veracode, though, reported it as an error to their users, and the stackoverflow link explains the arduous process it took to get them to reject this vulnerability.

The other two links are to the Ramda REPL. One shows an example of how a library might be subject to prototype pollution. The second shows the equivalent Ramda code, which does not exhibit the same behavior.

Feel free to email me with follow-up questions: scott.sauyet@gmail.com (originally I used scott@sauyet.com, and either is fine.)

#3192
https://stackoverflow.com/a/70239612
http://link.fourwindssoft.com/52
http://link.fourwindssoft.com/53

Let's see if we have any better luck this time.

@CrossEye
Copy link
Member

CrossEye commented Jun 1, 2022

Dug up a direct email for Mitre, meant for reporting vulnerabilities, hoping they can at least route this to the appropriate group. Something has to work, eventually.

@CrossEye
Copy link
Member

CrossEye commented Jun 2, 2022

I got a response from my email to Mitre, which told me that they had already updated the CVE database. It now lists the claim as "disputed", which is progress. I really don't know the resolution process from there.

But I have confirmed that this is updated at https://www.cve.org/CVERecord?id=CVE-2021-42581 and at https://nvd.nist.gov/vuln/detail/CVE-2021-42581, which I think are the key central sites.

@dbolkensteyn
Copy link

👍 https://github.com/CVEProject/cvelist/blame/master/2021/42xxx/CVE-2021-42581.json#L37

@CrossEye
Copy link
Member

CrossEye commented Sep 29, 2023

So, at long last, an update. This whole business had chased me from doing OSS for the past year. I was just too frustrated. While I'm hoping I'm back. But we'll have to find out.

You see, the answer is not good.

I had opened an email thread with Mitre, but they stopped responding, and didn't respond to pings, until today, fifteen months after I first started speaking with them. I had pinged again this morning, and this afternoon, I got this reply:

I just spoke with our team and we are going to keep the record in the PUBLISHED state and note that it is disputed. It is very rare that we reject published records. We keep records that are in dispute in the PUBLISHED state so that CVE consumers can reach their own conclusions about whether the CVE Record has any value.

Should you choose, you can appeal the MITRE Top-Level Root’s decision. The program dispute policy is located here: https://www.cve.org/Resources/General/Policies/CVE-Record-Dispute-Policy.pdf

Regards

C

As far as I can tell, this means that Mitre takes no responsibility for fixing the problem they've caused. The reason I ended up pinging them was that a coworker who was facing an issue from BlackDuck for another false vulnerability knew that I had been through this before and asked for advice. (And if I become the go-to guy at my company for dealing with this, it will be a hard choice between retirement and suicide!) He was right; it was a false report. And I checked in with a third false report I knew about and found none of them had any response from Mitre. So this does not seem to be an isolated incident.

Here's my response, sent at the local end of the work-week. I hope I do hear back soon.

Chris,

Thank you for letting me know.

This has been extremely frustrating. I feel that there's something wrong at Mitre that it has taken this long to resolve.

But I feel even more strongly that there's something broken in the whole process. There are companies offering bounties for reporting vulnerabilities, which gives an incentive to report them without due diligence.

And yet there is no reasonable process for challenging these reports. As I read your message, there is little chance of a CVE being withdrawn, so it is now my job as an unpaid open-source maintainer to try to convince the various security-related vendors to remove the CVE from their own databases. I doubt there is a comprehensive list. Can you suggest who else I need to get in touch with? Here's a small start:

  • Aikido
  • Blackduck
  • Checkmarx
  • Contrast Scan
  • Coverity
  • Fortify
  • GitHub
  • GitLab
  • HCL AppScan
  • Invicti
  • JFrog
  • Mend.io
  • Kiuwan
  • Klocwork
  • Snyck
  • SonarQube
  • SonarSource
  • Sonatype
  • Synopsys
  • Veracode

Is this really the process? It already has driven me from performing open-source work for a year. After an extremely frustrating experience with Veracode (described at https://stackoverflow.com/q/69936667/), when this started again, I mostly gave up in exasperation.

Or is there some mechanism I don't know about that would make this easier?

Thanks,

-- Scott Sauyet

We'll see what next week brings.


One thing I'm not sure I ever mentioned above, Veracode, to their credit, did eventually write a blog post demonstrating my point. (Not that they told me about it, but someone posted a link on the StackOverflow answer.) So one security company down, one zillion left to go.


I've got to say, there is a real temptation to find a way to post bounties for people reporting vulnerabilities within Mitre itself! I'd love to see how well they enjoy the process.

@CrossEye
Copy link
Member

Shockingly, Mitre responded in just 67 minutes! I assume this guy has been instructed to mollify me after Mitre ignored me for well over a year.

I’m sorry that your experience has been frustrating.

This was resolved from our perspective when we published the CVE record and indicated that it was disputed. This is the process for records that we publish. I apologize for our lack of timely communication regarding this outcome. We deal with many hundreds of requests and inquiries on a weekly basis so sometimes it takes us longer to reply then we like.

The quality and accuracy of vulnerability reporting is a known problem that is decades old and is not unique to the CVE program. Ecosystem-wide solutions for bad vulnerability reporting have proven elusive at scale.

I have no way of knowing what the outcome of the dispute and escalation process would be should you choose to engage it. MITRE does not control that process if the dispute is related to one of our records. If the result indicated that the record was invalid we would reject the record at the direction of the Root organizations that would decide the matter.

Chris

Politely phrased, but it seems to be "Yeah, good luck, buddy!"

I'm polite in my response too:

Again thank you for the reply.

This was the first project on which I had such an issue. A few months ago a second on arose on another project. Today there was a third. I had seen important vulnerabilities exposed through CVEs, but today's was the third false vulnerability that I was dealing with. It was what made me try again to see what you could do.

As to the decades-old problem, it sounds like it's time to find as way of addressing it. I don't know who sponsors bounties for finding vulnerabilities, but shutting those down sounds like a good start. Or at least modifying them so that there has to be substantive confirmation and chance for rebuttal before a bounty is awarded.

I might actually try the escalation procedure. We'll see if I can stomach it.

Thank you for your timely response (this time 😄).

-- Scott

Okay, so maybe a little zing in the last line. Who can blame me?

@CrossEye
Copy link
Member

I had another exchange just before my bedtime last night:

If you have a way to do this at scale, I’m willing to listen.

We have to do this at scale. It’s a highly imperfect process.

I’m willing to talk though. If there is a better way, I’ll follow it.

to which I responded:

I'm going to have to give this some serious thought. I don't really understand the CVE process; I've only paid attention insofar as it's affected me personally.

It may be that it's a fantastic process with only a small glitch. But from where I stand, it looks like a gaping hole. As a developer of open-source software, I want to be able to report that my software is secure. But when a (possibly bad faith) actor comes along and reports a spurious vulnerability, even after I've demonstrated that this is false, there seems little recourse for me to repair the damage.

As a user of open-source software, I want to be secure in the knowledge that my security tools are properly reporting vulnerabilities, with extremely few false negative or false positives sneaking through; if we have to rework some code to remove reported vulnerabilities, then I need to know that this work is actually justified by real problems, and not pure nonsense
.

Those two requirements should not be in conflict. But it feels like they are at the moment.

(And then a follow-up from me apologizing for typos; I really shouldn't type anything larger than a text message on my phone!)

It sounds like they might actually be willing to discuss fixes to this issue. As I said, though, this is going to take some real thinking.

@RustyButtons
Copy link

RustyButtons commented Dec 5, 2023

Hey @CrossEye,

I work as a security analyst at BlackDuck by Synopsys. I have been made aware of this issue and have looked into the "vulnerability". After playing about with the fiddlejs PoC we can confirm that we too believe you are correct and this is not a security vulnerability in the ramda library and is in fact the normal behaviour of JavaScript. The PoC can be recreated using just Object.assign . Additional Objects created do not inherit polluted properties as is the dangers of Prototype Pollution.

Issues such as false positive vulnerability reports cause issues for all parties involved and especially OSS maintainers. The BlackDuck Security Advisory associated with the CVE will be updated to state that this is not a vulnerability.

Since I have no control over the CVE listing, I can only update our advisory to state that this is not a security issue. By updating it hopefully it will deflect from the claims that this is a security vulnerability.

Hopefully Mitre will follow suit and remove the CVE as it is digested by so many security tools.

TLDR: ramda is not vulnerable to Prototype Pollution as claimed in CVE-2021-42581.
mapObjIndexed is copying content from proto to a new object (same as assign) it is not setting global Object.prototype.

Also, heres a modified jsfiddle of the "PoC" that shows no global prototypes are manipulated.
https://jsfiddle.net/pd04r7j8/

@CrossEye
Copy link
Member

CrossEye commented Dec 6, 2023

@RustyButtons: Thank you. That is fantastic news! I'm booked pretty solid for the next two days, but I will write a note detailed response as soon as I can.

@CrossEye
Copy link
Member

CrossEye commented Dec 8, 2023

@RustyButtons:

Again, thank you. If you've actually read this whole thread, you will know that dealing with these issues has been enough of a headache that it's mostly chased me from doing open source for more than a year. After fighting it out with Veracode for weeks, a few months later, we got the same problems with Mitre, who were even less responsive. Basically crickets for over a year, until ten weeks ago, when I got a "sorry, but that's just the way it is" answer.

I'm really glad to hear that Black Duck will be addressing this. Doubly so as BD is the tool used at my day job.

If you have a little time, I would love advice on how on how Ramda might proceed. When Veracode did recognize that this wasn't a real issue and pulled their report, they were kind enough to write a blog post debunking the CVE. While I can point people to that post, I don't know who to point to it. Any insights you can offer would be much appreciated. (And if you don't want to do it in a public forum, you can reach me at scott.sauyet@gmail.com.)

Again, thank you very much. This is so refreshing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants