Whenever an upgrade is made and deployed, there will be a new address for the implementation contract on the network. I understand that users will be interacting with the proxy contract. However, since older versions of implementation contracts are also on the chain, that means people can directly call those implementation contracts, right?
If there's a security bug in the older contract that may benefit malicious users, what's stopping those users from calling the old buggy contract, despite that the proxy contract is now pointing to a safe contract?
Do you have specific examples? It really depends on how the implementation contract is designed: does it have the selfdestruct function? does it have open external functions? etc.
Now, despite that our V2 does not have foo() anymore, people can still call it usign 0xV1_CONTRACT_ADDRESS , right?
This is correct, but the v1 implementation is not linked to any proxies' state. It has its own state which is not used by proxies and could have been initialized with gibberish values.
It's also possible for someone to deploy a new proxy and point it to the v1 implementation, or to "upgrade" (but really downgrade) a proxy from v2 back to v1 (as long as you have the right permissions and as long as the storage layouts do not conflict).