Skip to content

Commit

Permalink
feat(lbsa-20201130): update references, vendor, notes
Browse files Browse the repository at this point in the history
CSAF 2.0:
- Updated references
- Updated vendor to "LoopBack"
- Reorganised notes

OSV:
- Updated references

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
  • Loading branch information
achrinza committed Mar 7, 2022
1 parent 06f2805 commit 52a5d78
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 55 deletions.
68 changes: 33 additions & 35 deletions advisories/lbsa-20201130.csaf.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,34 @@
}
},
"lang": "en",
"notes": [
{
"audience": "all",
"category": "description",
"text": "It's a similar issue as https://snyk.io/vuln/SNYK-JS-LODASH-73638, where the following description is quoted from.\n\n> Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as `_proto_`, `constructor` and `prototype`. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.\n>\n> There are two main ways in which the pollution of prototypes occurs:\n>\n> - Unsafe Object recursive merge\n> - Property definition by path"
},
{
"audience": "all",
"category": "summary",
"text": "`@loopback/rest` allows REST APIs to have `constructor` in the JSON payload, which is vulnerable to prototype pollution."
}
],
"publisher": {
"category": "vendor",
"name": "The LoopBack Maintainers",
"name": "LoopBack",
"namespace": "https://loopback.io"
},
"references": [
{
"category": "self",
"summary": "Security Advisory 11-30-2020 CSAF document",
"summary": "LoopBack Security Advisory 11-30-2020 CSAF document",
"url": "https://loopback.io/doc/en/sec/lbsa-2020-11-30.csaf.json"
},
{
"category": "self",
"summary": "Security Advisory 11-30-2020 HTML document",
"summary": "LoopBack Security Advisory 11-30-2020 HTML document",
"url": "https://loopback.io/doc/en/sec/Security-advisory-11-30-2020.html"
},
{
"summary": "NVD - CVE-2020-4988 Detail",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4988"
},
{
"summary": "CVE-2020-4988 CVE Record",
"url": "https://www.cve.org/CVERecord?id=CVE-2020-4988"
},
{
"summary": "NPM",
"url": "https://www.npmjs.com/package/@loopback/rest"
},
{
"summary": "X-Force Vulnerability Report",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/192706"
}
],
"title": "Security Advisory 11-30-2020",
"title": "LoopBack Security Advisory 11-30-2020",
"tracking": {
"current_release_date": "2022-03-07T03:42:00.000Z",
"current_release_date": "2022-03-07T13:53:00.000Z",
"id": "LBSA-20201130",
"initial_release_date": "2022-01-18T00:00:00.000Z",
"revision_history": [
{
"date": "2022-03-07T13:53:00.000Z",
"number": "2.1.0",
"summary": "Updated vendor; Updated references; Reorganised notes."
},
{
"date": "2022-03-07T03:42:00.000Z",
"number": "2.0.0",
Expand All @@ -87,7 +64,7 @@
}
],
"status": "final",
"version": "2.0.0"
"version": "2.1.0"
}
},
"product_tree": {
Expand Down Expand Up @@ -2106,7 +2083,7 @@
}
],
"category": "vendor",
"name": "The LoopBack Maintainers"
"name": "LoopBack"
}
]
},
Expand Down Expand Up @@ -2308,10 +2285,31 @@
},
"references": [
{
"category": "self",
"summary": "GitHub Pull Request",
"url": "https://github.com/loopbackio/loopback-next/pull/6676"
},
{
"category": "self",
"summary": "GitHub Commit",
"url": "https://github.com/loopbackio/loopback-next/tree/ae0b9936e7eadbf6f0ee7c72e1a04b87dda7c2c5"
},
{
"category": "self",
"summary": "NVD CVE Detail",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4988"
},
{
"category": "self",
"summary": "CVE Record",
"url": "https://www.cve.org/CVERecord?id=CVE-2020-4988"
},
{
"summary": "NPM",
"url": "https://www.npmjs.com/package/@loopback/rest"
},
{
"category": "self",
"summary": "X-Force Vulnerability Report",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/192706"
}
Expand Down
28 changes: 20 additions & 8 deletions advisories/lbsa-20201130.osv.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
},
"details": "It's a similar issue as https://snyk.io/vuln/SNYK-JS-LODASH-73638, where the following description is quoted from.\n\n> Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as `_proto_`, `constructor` and `prototype`. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.\n>\n> There are two main ways in which the pollution of prototypes occurs:\n>\n> - Unsafe Object recursive merge\n> - Property definition by path",
"id": "LBSA-20201130",
"modified": "2022-03-06T00:13:54.000Z",
"modified": "2022-03-07T13:53:00.000Z",
"references": [
{
"type": "ADVISORY",
Expand All @@ -225,20 +225,32 @@
"url": "https://loopback.io/doc/en/sec/Security-advisory-11-30-2020.html"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4988"
},
{
"type": "ADVISORY",
"url": "https://www.cve.org/CVERecord?id=CVE-2020-4988"
"type": "PACKAGE",
"url": "https://loopback.io"
},
{
"type": "PACKAGE",
"url": "https://www.npmjs.com/package/@loopback/rest"
},
{
"type": "REPORT",
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/192706"
},
{
"type": "WEB",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4988"
},
{
"type": "WEB",
"url": "https://github.com/loopbackio/loopback-next/pull/6676"
},
{
"type": "WEB",
"url": "https://github.com/loopbackio/loopback-next/tree/ae0b9936e7eadbf6f0ee7c72e1a04b87dda7c2c5"
},
{
"type": "WEB",
"url": "https://www.cve.org/CVERecord?id=CVE-2020-4988"
}
],
"schema_version": "1.2.0",
Expand Down
92 changes: 86 additions & 6 deletions scripts/advisories/validate-csaf20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ glob(path.resolve(__dirname, csaf20DocumentGlob), async (err, matches) => {
distribution: validateDistribution(fileContents),
productTree: validateProductTree(fileContents),
publisher: validatePublisher(fileContents),
references: validateReferences(fileContents),
};

const validationResultsValues = Object.values(validationResults);
Expand Down Expand Up @@ -160,22 +161,21 @@ function validateProductTree(fileContents: any): ValidationResult {
const productTree = fileContents.product_tree.branches;
const errors: ValidationResult['errors'] = [];
const lbRootBranchIndex = (productTree as any[])?.findIndex(
v => v.name === 'The LoopBack Maintainers',
v => v.name === 'LoopBack',
);

if (lbRootBranchIndex > -1) {
const lbRootBranch = productTree[lbRootBranchIndex];
if (lbRootBranch.category !== 'vendor') {
errors.push({
instancePath: `/product_tree/branches/${lbRootBranchIndex}/category`,
message:
'category must be `vendor` for `The LoopBack Maintainers` vendor root branch.',
message: 'category must be `vendor` for `LoopBack` vendor root branch.',
});
}
} else {
errors.push({
instancePath: '/product_tree/branches',
message: '`The LoopBack Maintainers` vendor root branch must exist.',
message: '`LoopBack` vendor root branch must exist.',
});
}

Expand All @@ -196,10 +196,10 @@ function validatePublisher(fileContents: any): ValidationResult {
});
}

if (publisher.name !== 'The LoopBack Maintainers') {
if (publisher.name !== 'LoopBack') {
errors.push({
instancePath: '/document/publisher/name',
message: 'name must equal `The LoopBack Maintainers`',
message: 'name must equal `LoopBack`',
});
}

Expand All @@ -215,3 +215,83 @@ function validatePublisher(fileContents: any): ValidationResult {
errors,
};
}

function validateReferences(fileContents: any): ValidationResult {
const errors: ValidationResult['errors'] = [];
const documentReferences = fileContents.document.references;
const vulnerabilityReferences = fileContents.vulnerabilities.flatMap(
x => x.references,
);

// Ensure references with standardised summary uses a consistent URL.

// Do not re-order this array.
const allReferences = [...documentReferences, ...vulnerabilityReferences];

const refRegexMapping: Record<string, RegExp> = {
'CVE Record':
/^https:\/\/www\.cve\.org\/CVERecord\?id=CVE-[1-9][0-9]{3}-\d{4}$/,
NPM: /^https:\/\/www\.npmjs\.com\/package\/([a-z0-9-]|(@[a-z0-9._-]+\/))[a-z0-9._-]+$/,
'NVD CVE Detail':
/^https:\/\/nvd\.nist\.gov\/vuln\/detail\/CVE-[1-9][0-9]{3}-\d{4}$/,
'GitHub Commit':
/^(https:\/\/github\.com\/loopbackio\/[A-Za-z0-9._-]+\/tree\/[a-z0-9]+)$/,
'GitHub Pull Request':
/^(https:\/\/github\.com\/loopbackio\/[A-Za-z0-9._-]+\/pull\/[1-9]\d*)$/,
'X-Force Vulnerability Report':
/^https:\/\/exchange\.xforce\.ibmcloud\.com\/vulnerabilities\/[1-9]\d*$/,
};

for (let i = 0; i < allReferences.length; i++) {
const ref = allReferences[i];
const matchedRegex = refRegexMapping[ref.summary];

if (matchedRegex) {
if (!matchedRegex.test(ref.url)) {
// Hacky way of paritally reconstructing the instance path.
const baseInstancePath =
i < documentReferences.length
? '/document/references/'
: '/vulnerabilities/?/';
const refIndex =
i < documentReferences.length ? i : i - documentReferences.length;

errors.push({
instancePath: baseInstancePath + refIndex + '/url',
message: `url must match \`${matchedRegex}\`.`,
});
}
}
}

// Ensure no duplicate URLs between document-level and vulnerability-level
// references
const documentReferenceUrls = documentReferences.map(x => x.url);
const vulnerabilityReferenceUrls = vulnerabilityReferences.map(x => x.url);

if (documentReferenceUrls.length >= vulnerabilityReferenceUrls) {
for (let i = 0; i < documentReferenceUrls.length; i++) {
if (vulnerabilityReferenceUrls.includes(documentReferenceUrls[i])) {
errors.push({
instancePath: `/document/references/${i}/url`,
message:
'url must not be duplicate in `/vulnerabilities/*/references/*/url`.',
});
}
}
} else {
for (let i = 0; i < vulnerabilityReferenceUrls.length; i++) {
if (documentReferenceUrls.includes(vulnerabilityReferenceUrls[i])) {
errors.push({
instancePath: `/vulnerabilities/?/references/${i}/url`,
message: 'url not must be duplicate in `/document/references/*/url',
});
}
}
}

return {
isValid: errors.length < 1,
errors,
};
}
17 changes: 11 additions & 6 deletions scripts/advisories/validate-osv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ function validateAffectedVersions(fileContents: any): ValidationResult {
' <' +
semverEvents.find(x => x.fixed).fixed;

console.log(semverRange);

for (let i = 0; i < versions.length; i++) {
const version = versions[i];

Expand Down Expand Up @@ -161,7 +159,7 @@ function validateCSAF20Sync(
}

// Summary sync
const csaf20Summary = csaf20Document.document.notes.find(
const csaf20Summary = csaf20Document.vulnerabilities[0].notes?.find(
x => x.category === 'summary',
).text;
const osvSummary = osvDocument.summary;
Expand All @@ -174,7 +172,7 @@ function validateCSAF20Sync(
}

// Description / Details sync
const csaf2SDescription = csaf20Document.document.notes.find(
const csaf2SDescription = csaf20Document.vulnerabilities[0].notes.find(
x => x.category === 'description',
).text;
const osvDetails = osvDocument.details;
Expand Down Expand Up @@ -226,8 +224,15 @@ function validateCSAF20Sync(
}

// References sync
const csaf20References = csaf20Document.document.references.map(x => x.url);
const osvReferences = osvDocument.references.map(x => x.url);
const csaf20References = [
...csaf20Document.document.references.map(x => x.url),
...csaf20Document.vulnerabilities
.flatMap(x => x.references)
.map(x => x.url),
];
const osvReferences = osvDocument.references
.map(x => x.url)
.filter(x => x !== 'https://loopback.io');

if (osvReferences.length >= csaf20References.length) {
for (let i = 0; i < osvReferences.length; i++) {
Expand Down

0 comments on commit 52a5d78

Please sign in to comment.