Each and every line of code you write is a liability. Even more so when you wrote it for someone else. You must always be able to rebuild it from source, at least as long as your client expect the software to work. If you feel it’s not worth it, you probably low-balled the contract. If you don’t want to maintain code, have the client pay a yearly maintenance fee, give the code and the responsibility to maintain it to your client at the end of development, or add a time limit to it’s support.
There’s no “maintenance mode” software: either it’s in use and must be kept updated with regard to it’s execution environment, or it’s not used anymore and can be erased and forgotten. Doing differently opens too much security issues, which shouldn’t be acceptable for us all as a trade.
A process owned by any user will be able to exploit a userspace vulnerability, whatever this user is. Selinux, chroot, cgroups/containerization add a layer of protection to this, but any vulnerability that bypass these will be as exploitable from nobody as from any other local user. It will protect a user files from some access attempts but will fail to prevent any serious attack. And as usual when it comes to security, a false sense of security is worse than no security at all.
Remember that some exploits exist that can climb outside of a full-blown virtual machine to the virtualisation host, finding a user escalation vulnerability is even more likely.
The only real protection is an up-to-date system, sane user behavior and maybe a little bit of paranoia.