The docs say to use the
_disableInitializers function, otherwise our contract might be vulnerable to attacks. Is this true?
If so, how would one perform this attack? How can this function prevent the attack from happening? Is any contract without this vulnerable?
Having a constructor that uses
_disableInitializers() is recommended as a best practice to prevent initialization of the implementation contract itself.
There was a previous UUPS vulnerability where if an implementation contract was initialized by an attacker, the attacker could give themselves upgrade authority and delegate a call to a malicious contract that causes the implementation contract to self destruct. That vulnerability was resolved by restricting the upgrade functions to
onlyProxy, but disabling initializers is still recommended as an extra layer of protection against these types of attacks.