There are indeed a number of subnet resources that could be exhausted by malicious actors with enough money / ICP / cycles. And the issue has not yet been addressed holistically. Partly because it would take quite a bit of money to mount such an attack; partly because such an attack has never been attempted; and partly because addressing it requires a change of mindset (see below).
We do have one-off solutions for specific resources (e.g. progressively higher storage cycle reservations when subnet storage usage exceeds some threshold), but the elephant in the room is the fact that even in those situation fees are still flat (i.e. in the case of storage reservations, canisters are forced to reserve cycles to pay for said storage for longer and longer time spans, but the fee itself is flat – $5 / GB / year).
In order to more widely address abuse, we need a generalized model of progressive fees / surge pricing. Storage can get away with increasingly longer term reservations while keeping fees flat, but we cannot apply this approach to all types of resources. So while it’s really nice to easily be able to predict one’s costs due to flat fees, efficient and reliable use of shared resources requires the ability to dynamically react to malicious behavior (or just random spikes). Also note that, as you observed, it is relatively trivial to mount a Sybil attack on the IC, so that surge pricing won’t only affect the “bad guys”. Everyone using the resource under attack at the time of an attack would have to face significantly higher fees. Meaning that any solution will have to be carefully designed so as to not make the protection mechanism itself be a tool for a potential attack (e.g. if there’s a hefty fee penalty for some resource when its subnet or global usage exceeds some threshold, an attacker could exhaust just enough of said resource to make everyone else pay the fee penalty while avoiding it themselves).
And given the nature of the IC, those maintaining and extending the protocol (i.e. DFINITY engineers) cannot unilaterally decide to tweak the fee structure, even if that would mean a safer, more scalable network. We need to do a comprehensive analysis, put together a well argued solution, get the community to weigh in on it; and, finally, ask them to vote on a high-level design.
In the meantime, in addition to the specific solutions mentioned above, we also have (less granular) tools and processes to help us deal with such occurrences as one-off incidents: we can create new subnets to spread the load (there are still many hundreds of unassigned nodes); we can split heavily oversubscribed subnets; controllers will soon be able to migrate their canisters to less loaded subnets; and there’s always the option to fall back on the NNS to deal with problematic behavior (e.g. by taking down / blocking / penalizing actively malicious canisters; including by implementing one-off changes to the protocol to achieve these).
And we are continuously working on improving scalability. For a while now, the limits on the number of canisters and subnet storage have been there mostly to ensure responsive subnets and less as a hard limit beyond which the subnet would fall over. There is now quite a bit of headroom for subnets to scale vertically if need be.