Not only is there a solution, but it's pretty well known computer science. Use public key cryptography to create a digital signature. It's not even a novel use of this -- .NET has been using this to sign assemblies and packages from day one.

Package signing by the package's author /is/ the solution, right? This way the only entity that can publish a valid update is the the package author. This still has the problem of bootstrapping the trust relationship, and leaves the door open to the author publishing a malicious but signed package or the signing key being stolen and used to do the same. However if you don't trust the package author to be responsible or take precautions against the keys being stolen then you're essentially taking on the burden of implementing of your required functionality.

We also need some way to link packages to authors. In the Java world packages are supposed to be in a namespace that's the reverse domain name, so you could (potentially, theoretically) connect that up with something like DNSSEC and enforce that people can only publish packages for domains that they control. (Though even that is really just punting the problem up to the DNS registries).

I don't get it. If I keep a hash of every dependency in my project, and an attacker change a dependency, I will detect the attack by computing the dependency hash and comparing it with the one stored in my project (for example in the dependencies lock file), which cannot be changed by the attacker.

Now, what happens if an attacker compromises the repo where people download your package from? Or what if he executes a MitM attack on the repo or a user who downloads from it? He can change the entire package, including all manifests, all hashes, etc. Users who download it will be none the wiser. By the time someone notices and corrects it, people will have downloaded the compromised versions and be infected.

The only thing that protects against this is strong crypto signatures. For example, if a Debian mirror were compromised and an attacker uploaded compromised packages, users would be safe, because apt would refuse to install the packages, because they would fail signature verification.

SHA1 collisions are affordable for large actors now and getting cheaper all the time, so git, with its SHA1 assumptions hard-coded, unfortunately doesn't protect you anymore. But the local hash approach is a good one, proven in pip 8 (Python) and npm-lockdown (JS).