The basic problem is fundamental: outsourcing is a very common thing you find in all walks of life, it is often the most reasonable choice due to comparative advantage. This is the reason I eventually gave up on "decentralization" as a worthwhile technical goal (after years spent working on Bitcoin). Everyone is trying to outsource everything that isn't their key competitive advantage, and that's because specialization is the heart of progress. The costs of centralization are obvious in terms of loss of resiliency, but when people aren't actually needing that resiliency for entire lifetimes it's hard to convince anyone to take the loss of progress that decentralization may appear to entail.
So what to do? As you found with your 1,600 line imgur alternative just starting over to make stuff be secure is ... hard. You wrote in C++ (not the most security conscious choice) and some of those vulnerabilities are very basic, like the one where you discover that due to a bug some users are getting empty passwords. You also sort of assume that your users will keep your app up to date, but we know they won't. So simply demanding programs be smaller isn't going to work. You'll just speedrun the history of vulnerabilities. Indeed, one reason to outsource stuff to a handful of giant providers is that they do a much better job of security overall. Yeah Microsoft may have problems with Chinese hackers, but government IT routinely has problems with greedy teenagers. So MS is still ahead of the pack.
IMO the most critical thing is really whole-systems analysis to find sources of unnecessary complexity and fix it. That won't necessarily turn the tide, but it can at least help. As a trivial example, HTTP stacks don't understand the concept of load balancing. They're still stuck in a world where every website is run by a single computer. That entails a lot of server-side complexity like dedicated LBs, maybe even DNS LB, replicated databases, health checks, drain periods etc just to avoid users seeing little dinosaurs due to normal maintenance. The complexity of this is overwhelming. When users accepted things like "This service will be offline on Sunday due to maintenance" you could get away with it but now people expect everything to be 24/7, so that complexity drives people to the cloud where it's somewhat handled for them.
Thus an obvious quick win - extend HTTP and DNS to understand IP address globbing and maybe even static route matching. If a connection to a server fails, have the stack transparently fail over to another one. Now you can scrap your server side LBs and reverse proxies but still have an HA service.