diff --git a/docs/pages/world/reference/world.mdx b/docs/pages/world/reference/world.mdx index f25400d6e3..2bed5edbe2 100644 --- a/docs/pages/world/reference/world.mdx +++ b/docs/pages/world/reference/world.mdx @@ -44,7 +44,10 @@ constructor(); #### prohibitDirectCallback -_Prevents the World contract from calling itself._ +_Prevents the World contract from calling itself. +If the World is able to call itself via `delegatecall` from a system, the system would have root access to context like internal tables, causing a potential vulnerability. +Ideally this should not happen because all operations to internal tables happen as internal library calls, and all calls to root systems happen as a `delegatecall` to the system. +However, since this is an important invariant, we make it explicit by reverting if `msg.sender` is `address(this)` in all `World` methods._ ```solidity modifier prohibitDirectCallback(); diff --git a/packages/world/src/World.sol b/packages/world/src/World.sol index e6480edc1d..b05fb698f6 100644 --- a/packages/world/src/World.sol +++ b/packages/world/src/World.sol @@ -51,6 +51,9 @@ contract World is StoreData, IWorldKernel { /** * @dev Prevents the World contract from calling itself. + * If the World is able to call itself via `delegatecall` from a system, the system would have root access to context like internal tables, causing a potential vulnerability. + * Ideally this should not happen because all operations to internal tables happen as internal library calls, and all calls to root systems happen as a `delegatecall` to the system. + * However, since this is an important invariant, we make it explicit by reverting if `msg.sender` is `address(this)` in all `World` methods. */ modifier prohibitDirectCallback() { if (msg.sender == address(this)) {