CVE-2020-11071 (published 2020-05-12T01:15Z)

SLPJS (npm package slpjs) before version 0.27.2, has a vulnerability where users could experience false-negative validation outcomes for MINT transaction operations. A poorly implemented SLP wallet could allow spending of the affected tokens which would result in the destruction of a user's minting baton. This is fixed in version 0.27.2.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 8.6, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-697
cwe_name: Incorrect Comparison
description: The product compares two entities in a security-relevant context, but the comparison is incorrect, which may lead to resultant weaknesses.
extended_description: 
            This Pillar covers several possibilities:
               
                  the comparison checks one factor incorrectly;
                  the comparison should consider multiple factors, but it does not check at least one of those factors at all;
                  the comparison checks the wrong factor.
               
         
         

Fix information:
repo_url: https://github.com/simpleledger/slpjs
commit_details: repo_url: https://github.com/simpleledger/slpjs
author: James Cramer
author_date: 2020-04-29 12:48:21-04:00
msg: fix false negative case for MINT transactions

See the newly added unit test case for this issue.
Currently there are 151 unit tests.
repository: repo_url: https://github.com/simpleledger/slpjs
repo_name: simpleledger/slpjs
description: JavaScript library for Simple Ledger Protocol
repo_language: TypeScript
owner: simpleledger
file_changes: filename: localvalidator.ts
change_type: ModificationType.MODIFY
diff: @@ -282,10 +282,10 @@ export class LocalValidator implements SlpValidator {
                     }
                 } catch (_) {}
             }
-            if (this.cachedValidations[txid].parents.length !== 1) {
+            if (this.cachedValidations[txid].parents.length < 1) {
                 this.cachedValidations[txid].validity = false;
                 this.cachedValidations[txid].waiting = false;
-                this.cachedValidations[txid].invalidReason = "MINT transaction must have 1 valid baton parent.";
+                this.cachedValidations[txid].invalidReason = "MINT transaction must have at least 1 candidate baton parent input.";
                 return this.cachedValidations[txid].validity!;
             }
         }
@@ -342,10 +342,14 @@ export class LocalValidator implements SlpValidator {
         // Set validity validation-cache for parents, and handle MINT condition with no valid input
         // we don't need to check proper token id since we only added parents with same ID in above steps.
         const parentTxids = [...new Set(this.cachedValidations[txid].parents.map(p => p.txid))];
-        for (let i = 0; i < parentTxids.length; i++) {
-            const valid = await this.isValidSlpTxid(parentTxids[i]);
-            this.cachedValidations[txid].parents.filter(p => p.txid === parentTxids[i]).map(p => p.valid = valid);
-            if (this.cachedValidations[txid].details!.transactionType === SlpTransactionType.MINT && !valid) {
+        for (const id of parentTxids) {
+            const valid = await this.isValidSlpTxid(id);
+            this.cachedValidations[txid].parents.filter(p => p.txid === id).map(p => p.valid = valid);
+        }
+
+        // Check MINT for exactly 1 valid MINT baton
+        if (this.cachedValidations[txid].details!.transactionType === SlpTransactionType.MINT) {
+            if (this.cachedValidations[txid].parents.filter(p => p.valid && p.inputQty === null).length !== 1) {
                 this.cachedValidations[txid].validity = false;
                 this.cachedValidations[txid].waiting = false;
                 this.cachedValidations[txid].invalidReason = "MINT transaction with invalid baton parent.";

programming_language: TypeScript