CVE-2021-39168 (published 2021-08-27T00:15Z)

OpenZepplin is a library for smart contract development. In affected versions a vulnerability in TimelockController allowed an actor with the executor role to escalate privileges. Further details about the vulnerability will be disclosed at a later date. As a workaround revoke the executor role from accounts not strictly under the team's control. We recommend revoking all executors that are not also proposers. When applying this mitigation, ensure there is at least one proposer and executor remaining.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-269
cwe_name: Improper Privilege Management
description: The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
extended_description: 
            
         
         

Fix information:
repo_url: https://github.com/OpenZeppelin/openzeppelin-contracts
commit_details: repo_url: https://github.com/OpenZeppelin/openzeppelin-contracts
author: Francisco Giordano
author_date: 2021-08-24 16:09:39-03:00
msg: Add additional isOperationReady check in TimelockController
repository: repo_url: https://github.com/OpenZeppelin/openzeppelin-contracts
repo_name: OpenZeppelin/openzeppelin-contracts
description: OpenZeppelin Contracts is a library for secure smart contract development.
repo_language: JavaScript
owner: OpenZeppelin
file_changes: filename: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,9 @@
 # Changelog
 
+## 4.3.1
+
+ * `TimelockController`: Add additional isOperationReady check.
+
 ## 4.3.0 (2021-08-17)
 
  * `ERC2771Context`: use private variable from storage to store the forwarder address. Fixes issues where `_msgSender()` was not callable from constructors. ([#2754](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2754))
@@ -95,6 +99,10 @@ Make sure you're using git or another version control system to be able to recov
 
 Some further changes have been done between the different beta iterations. Transitions made during this period are configured in the `migrate-imports` script. Consequently, you can upgrade from any previous 4.0-beta.x version using the same script as described in the *How to upgrade from 3.x* section.
 
+## 3.4.2
+
+ * `TimelockController`: Add additional isOperationReady check.
+
 ## 3.4.1 (2021-03-03)
 
  * `ERC721`: made `_approve` an internal function (was private).

programming_language: Markdown
filename: TimelockController.sol
change_type: ModificationType.MODIFY
diff: @@ -268,7 +268,7 @@ contract TimelockController is AccessControl {
         bytes32 salt
     ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
         bytes32 id = hashOperation(target, value, data, predecessor, salt);
-        _beforeCall(predecessor);
+        _beforeCall(id, predecessor);
         _call(id, 0, target, value, data);
         _afterCall(id);
     }
@@ -293,7 +293,7 @@ contract TimelockController is AccessControl {
         require(targets.length == datas.length, "TimelockController: length mismatch");
 
         bytes32 id = hashOperationBatch(targets, values, datas, predecessor, salt);
-        _beforeCall(predecessor);
+        _beforeCall(id, predecessor);
         for (uint256 i = 0; i < targets.length; ++i) {
             _call(id, i, targets[i], values[i], datas[i]);
         }
@@ -303,7 +303,8 @@ contract TimelockController is AccessControl {
     /**
      * @dev Checks before execution of an operation's calls.
      */
-    function _beforeCall(bytes32 predecessor) private view {
+    function _beforeCall(bytes32 id, bytes32 predecessor) private view {
+        require(isOperationReady(id), "TimelockController: operation is not ready");
         require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency");
     }
 

programming_language: JavaScript