Like I mentioned in my comment, supply chain risks can't be completely eliminated. This question, which I also linked to, explains it rather well.
Let's have a look at each specific point of concern:
Dependencies are downloaded as already compiled code.
This could be because the dependency is some proprietary code and source code is not available, or simply out of convenience.
You could either decompile and reverse engineer what the dependency does, or analyze the source code if available. The problem is, nobody does that. It's thousands of lines of code - your developers already have an enormous codebase to deal with, so asking them to basically learn a whole new codebase for every dependency will get people to question the sanity of whoever ordered that. In other words: Analyzing the source code for every dependency, just to ensure it doesn't contain any bugs or backdoors, will bring development to a standstill. And then you have to assume that programmers will spot the backdoor. Just for fun, here's a backdoor:
if ((options == (__WCLONE|__WALL)) && (current->uid = 0))
retval = -EINVAL;
Try finding it. Keep in mind that this is 2 lines and you know there is a backdoor. Now imagine playing the same game with thousands of lines of code, and not knowing if there is one.
Problems with Jar Signatures
The fact that signatures are not checked by default is a feature. Requiring every Jar to be signed is not something that most developers care about - still only takes a handful of flags to enable that, so that's not the issue.
Problems arise only when developers of some library you want to use don't sign their Jars. Either use a different library or ask the developer to sign their Jars. However, even signed Jars don't stop an attacker from inserting a backdoor into the source code, depending on how well the signing practices of the developer are.
In essence, signing jars can help, but it's not the be-all-end-all of supply chain attacks. And against a malicious developer, it doesn't protect at all.
Developers can add arbitrary dependencies
Yeah, the point of build systems is to be easy to use and add as little friction as possible. That means developers are encouraged by the system to just add what they need.
Now, a responsible developer would consider the downsides of adding a new dependency to a project, weigh in whether this would be a reasonable thing to do or not, and then check how trustworthy the library and its developer is.
A less responsible developer just adds a library that sounds kind-of like it does what they need it to do, and then just see if it works. All an attacker needs to do is create a package named
json and tons of people will fly to it.
nothing you can really do in practice. You can do the things suggested in the linked answer, such as running separate environments, doing code audits for specific versions, etc.. Aside from that, you just have to trust.