Vulnerabilities in pkg:npm/@liquity/contracts

PACKAGE
Advisory Summary

GHSA-xh2p-7p87-fhgh is a LOW (CVSS 3.1) incorrect tcr calculation vulnerability (CWE-682: Incorrect Calculation) affecting @liquity/contracts libraries in the npm ecosystem. The issue involves incorrect tcr calculation in batchliquidatetroves() during recovery mode. Remediation is available in the latest vendor maintenance releases.

1 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:npm/@liquity/contracts

1 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:npm/@liquity/contracts. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-xh2p-7p87-fhgh - LOW Incorrect TCR calculation in batchLiquidateTroves() during Recovery Mode

GHSA-xh2p-7p87-fhgh at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-xh2p-7p87-fhgh
Severity LOW
CVSS v3.1 Base Score 3.1
CWE Classification CWE-682: Incorrect Calculation
Affected Product @liquity/contracts
Package Ecosystem npm
Published Date
Last Updated

Security Impact

CVSS: 3.1

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N).

Attack Vector Network (AV:N)
Attack Complexity High (AC:H)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity Low (I:L)
Availability None (A:N)

How to Fix GHSA-xh2p-7p87-fhgh

To remediate this vulnerability, upgrade all affected @liquity/contracts dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@liquity/contracts fixed: Latest secure release
npm install @liquity/contracts@Latest secure release
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @liquity/contracts

How to Check if You Are Affected

To determine whether your Node.js application is affected by GHSA-xh2p-7p87-fhgh, inspect your project dependencies using npm:

npm ls @liquity/contracts

Analyze the terminal output to locate any version of @liquity/contracts in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than the patched release), your application is affected.

Note: The npm ls @liquity/contracts command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-682: Incorrect Calculation, where the product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management. In @liquity/contracts, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

TCR is temporarily miscalculated in the `batchLiquidateTroves` function during Recovery Mode. The bug lies in [`batchLiquidateTroves` of `TroveManager`](https://github.com/liquity/dev/blob/7c83ea11378454629618b3808b16fbfda69ee3e5/packages/contracts/contracts/TroveManager.sol#L722). When calculating system's entire collateral, we should also exclude the liquidated trove's surplus collateral, since liquidation closes the trove and makes the surplus collateral claimable by the trove owner. This means, this line of code should look like this: ``` vars.entireSystemColl = vars.entireSystemColl.sub(singleLiquidation.collToSendToSP).sub(singleLiquidation.collSurplus); ``` ### Impact The miscalculated entire collateral is used only to calculate the TCR and check if the system has been able to exit Recovery Mode. The miscalulation only persists temporarily, and within the`batchLiquidateTroves` transaction. Once the transaction completes the TCR and Recovery Mode will be calculated properly again. However, the bug could negatively impact the liquidation throughput and the gas efficiency gains from batching multiple liquidations in a single transaction. In normal situations, the impact of the collateral surplus of a Trove on the global TCR would be tiny. For instance, we have calculated that liquidating a trove with a collateral representing 1% of the total system collateral (so in the order of at least $10M at current values), would lead to an extra 0.53% in the temporary miscalculation of TCR. So for this bug to be meaningful, in such a scenario, the resulting real TCR must be already be very close to the Recovery Mode boundary anyway - i.e. between 149.47% and 150%. The batch liquidation transaction should also be executed with a particular trove ordering to achieve the TCR distortion. When a different trove order for the liquidation transaction is selected, the bug has no impact. In summary, the bug only has a non-negligible impact in a very narrow, specific set of circumstances. The potential effects of the bug after it occurs are: - The next trove in the sequence is not liquidated because the `batchLiquidateTroves` function calculates a premature exit from Recovery Mode. It could be liquidated in a subsequent transaction if the price of Ether doesn’t recover. - The next trove in the sequence has an ICR below 100% and it’s offset against the Stability Pool instead of redistributed among other troves because the function calculates a premature exit from Recovery Mode. For this to happen, the Ether price must have instantly plummeted by more than 10% (otherwise, the trove would have been already liquidated before). - The next trove in the sequence is liquidated while its ICR is over the real TCR: the function calculates the TCR as being slightly too high, and thus can liquidate a trove that has ICR less than the calculated TCR, but greater than the true TCR. This is probably the worst outcome - however it is already possible to achieve the same effect, regardless of the bug. A liquidator can craft a `batchLiquidateTroves` transaction whereby they select troves for liquidation such that the TCR increases and makes a given trove liquidateable. To liquidate trove A, they can order troves such that they first liquidate troves which raise the TCR to between A's ICR and 150%. This is intended and expected behavior. As clearly stated in Liquity documentation, to be completely safe and guarantee immunity from liquidation in Recovery Mode, borrowers should keep their ICR above 150%. We don't believe this bug creates a profitable exploit. Theoretically, and only in a very narrow set of circumstances, a liquidator could try to send a batch liquidation during Recovery Mode that lets the system very temporarily return to Normal Mode earlier than it should. In that case - _and only if the Ether price also happens to suddenly plummet by more than 10%_ - stability providers might take the haircut that should be taken by the borrowers (through redistribution). ### Patches The problem has been patched in the source code but not on mainnet contracts. Liquity protocol is immutable, and this issue is not critical, so it doesn't merit a launch of a new version. ### Bug bounty A reward of $1,000 (the maximum for its category) was awarded to Xiahong (`gaoxh06`) for reporting this bug. ### For more information If you have any questions or comments about this advisory: * Open an issue in [our repo](https://github.com/liquity/dev) * Email us at [security@liquity.org](mailto:security@liquity.org)

GHSA-xh2p-7p87-fhgh Affected @liquity/contracts Versions

1 component(s)
Product / Package Ecosystem Affected Versions Fixed Version
@liquity/contracts
npm
≤ 1.0.0

References

Frequently Asked Questions

What is GHSA-xh2p-7p87-fhgh?
GHSA-xh2p-7p87-fhgh is a security vulnerability in @liquity/contracts involving Incorrect TCR calculation in batchLiquidateTroves() during Recovery Mode under CWE-682: Incorrect Calculation.
Which @liquity/contracts versions are affected?
Affected versions include releases prior to current release patches across affected packages: @liquity/contracts.
What version fixes GHSA-xh2p-7p87-fhgh?
Upgrading to current release patches (or the latest patched release for your respective branch) resolves the vulnerability.
Is @liquity/contracts affected?
Yes, @liquity/contracts is affected in releases prior to Latest secure release. Upgrade your dependency to Latest secure release or later.
What is the CVSS score of GHSA-xh2p-7p87-fhgh?
GHSA-xh2p-7p87-fhgh has a CVSS v3.1 base score of 3.1 (LOW) with vector string CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N.
What CWE is associated with GHSA-xh2p-7p87-fhgh?
GHSA-xh2p-7p87-fhgh is classified under CWE-682: Incorrect Calculation (The product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management.).
How can I check npm dependencies for GHSA-xh2p-7p87-fhgh?
Run the dependency tree command: 'npm ls @liquity/contracts'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-xh2p-7p87-fhgh",
  "modified" : "2021-07-29T20:43:48Z",
  "published" : "2021-08-05T16:56:58Z",
  "aliases" : [ ],
  "summary" : "Incorrect TCR calculation in batchLiquidateTroves() during Recovery Mode",
  "details" : "TCR is temporarily miscalculated in the `batchLiquidateTroves` function during Recovery Mode.\n\nThe bug lies in [`batchLiquidateTroves` of `TroveManager`](https://github.com/liquity/dev/blob/7c83ea11378454629618b3808b16fbfda69ee3e5/packages/contracts/contracts/TroveManager.sol#L722). \n\nWhen calculating system's entire collateral, we should also exclude the liquidated trove's surplus collateral, since liquidation closes the trove and makes the surplus collateral claimable by the trove owner. This means, this line of code should look like this: \n```\nvars.entireSystemColl = vars.entireSystemColl.sub(singleLiquidation.collToSendToSP).sub(singleLiquidation.collSurplus);\n```\n### Impact\n\nThe miscalculated entire collateral is used only to calculate the TCR and check if the system has been able to exit Recovery Mode. The miscalulation only persists temporarily, and within the`batchLiquidateTroves` transaction. Once the transaction completes the TCR and Recovery Mode will be calculated properly again. However, the bug could negatively impact the liquidation throughput and the gas efficiency gains from batching multiple liquidations in a single transaction.\n\nIn normal situations, the impact of the collateral surplus of a Trove on the global TCR would be tiny. For instance, we have calculated that liquidating a trove with a collateral representing 1% of the total system collateral (so in the order of at least $10M at current values), would lead to an extra 0.53% in the temporary miscalculation of TCR. So for this bug to be meaningful, in such a scenario, the resulting real TCR must be already be very close to the Recovery Mode boundary anyway - i.e. between 149.47% and 150%. The batch liquidation transaction should also be executed with a particular trove ordering to achieve the TCR distortion. When a different trove order for the liquidation transaction is selected, the bug has no impact. In summary, the bug only has a non-negligible impact in a very narrow, specific set of circumstances.\n\nThe potential effects of the bug after it occurs are:\n\n- The next trove in the sequence is not liquidated because the `batchLiquidateTroves` function calculates a premature exit from Recovery Mode. It could be liquidated in a subsequent transaction if the price of Ether doesn’t recover.\n- The next trove in the sequence has an ICR below 100% and it’s offset against the Stability Pool instead of redistributed among other troves because the function calculates a premature exit from Recovery Mode. For this to happen, the Ether price must have instantly plummeted by more than 10% (otherwise, the trove would have been already liquidated before).\n- The next trove in the sequence is liquidated while its ICR is over the real TCR: the function calculates the TCR as being slightly too high, and thus can liquidate a trove that has ICR less than the calculated TCR, but greater than the true TCR. This is probably the worst outcome - however it is already possible to achieve the same effect, regardless of the bug.  A liquidator can craft a `batchLiquidateTroves` transaction whereby they select troves for liquidation such that the TCR increases and makes a given trove liquidateable. To liquidate trove A, they can order troves such that they first liquidate troves which raise the TCR to between A's ICR and 150%. This is intended and expected behavior. As clearly stated in Liquity documentation, to be completely safe and guarantee immunity from liquidation in Recovery Mode, borrowers should keep their ICR above 150%.\n\nWe don't believe this bug creates a profitable exploit. Theoretically, and only in a very narrow set of circumstances, a liquidator could try to send a batch liquidation during Recovery Mode that lets the system very temporarily return to Normal Mode earlier than it should. In that case - _and only if the Ether price also happens to suddenly plummet by more than 10%_ - stability providers might take the haircut that should be taken by the borrowers (through redistribution).\n\n### Patches\nThe problem has been patched in the source code but not on mainnet contracts. Liquity protocol is immutable, and this issue is not critical, so it doesn't merit a launch of a new version.\n\n### Bug bounty\n\nA reward of $1,000 (the maximum for its category) was awarded to Xiahong (`gaoxh06`) for reporting this bug.\n\n### For more information\n\nIf you have any questions or comments about this advisory:\n* Open an issue in [our repo](https://github.com/liquity/dev)\n* Email us at [security@liquity.org](mailto:security@liquity.org)\n",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@liquity/contracts"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "last_affected" : "1.0.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/liquity/dev/security/advisories/GHSA-xh2p-7p87-fhgh"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/liquity/dev/commit/c69d0bae30b5457e89724d880851a03ba7477905"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/liquity/dev/blob/7c83ea11378454629618b3808b16fbfda69ee3e5/packages/contracts/contracts/TroveManager.sol#L722"
  }, {
    "type" : "WEB",
    "url" : "https://www.npmjs.com/package/@liquity/contracts"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-682" ],
    "severity" : "LOW",
    "github_reviewed" : true,
    "github_reviewed_at" : "2021-07-29T20:43:48Z",
    "nvd_published_at" : null
  }
}