I find that integrated tests in software projects go a long way to reducing rot. When something eventually invariably breaks due to some external factor, the test suite greatly reduces the time to identify and fix the problem.
Even though the VM image and tooling may still be runnable, the world around it with which it must interact continues to evolve and can leave your software obsolete.
Software doesn't exist in isolation. It interacts with its host OS, shared libraries, other programs, protocols, file formats and external systems. If it can't keep up then it effectively rots even though not a single byte of it has changed.
Software rots if you can no longer set up the exact tool chain and environment (compiler, build tool, OS version, external database, etc) required to build and run it. Even interpreted languages suffer from this problem as features are subtlely changed - by design or accident. It doesn't matter if your project is using an ancient version of VC++ or a two year old version of NodeJS. If it doesn't keep up with the latest releases of the tools then it's already got one foot in the grave.