first, I am just on-and-off with Rust, not really a seasoned programmer.
With 'safe' in the thread title I mean what's dubbed supply chain attacks, the possibility that someone deliberately posts malware code, or hijacks or compromises a crate? Are there mechanisms to prevent this?
There is an older thread on this in this forum, but it appears that there is no clarity on how to curb such scenarios.
For the most part, caveat emptor applies, and you need to be responsible for your own safety:
Anyone can publish a crate under a new name on crates.io and AFAIK there is no mechanism to prevent typosquatting.
The only restriction on publishing a new version of a crate is that it must be done by one of the crate owners. This is protected via GitHub credentials, so a hijacking can only occur if those credentials are compromised.
All published crate versions, however, are frozen. If you've audited a particular version of a crate, you can rely on an identical copy being delivered whenever you request that version.
It should be noted that this only helps if you pin the version with =1.2.3 for example (see comparison requirements). And I think this doesn't avoid dependencies of such a create to be updated in regard to the minor version number, right?
I think ultimately, this problem isn't Rust / crates.io specific. The only way to be safe is to audit every dependency and pin their version and/or only rely on code of owners who you trust to not do something bad and who you expect to pick their dependencies wisely. (Neither solution might work out very well in practice.)
From a security p.o.v., I think crates.io does a good job already with freezing the uploaded code and documenting who has privileges to publish updates. I think weaknesses are more in implementation details such as not providing 2FA for authenticating owners.
Another issue I was concerned about was that yanking / unyanking didn't seem to be well-documented (see this post), but it turned out this is just an issue of the GUI. The action of yanking / unyanking is recorded and published also, just not through the crates.io GUI.
The dependency information is also frozen though. If you specify those dependencies from your own crate with a =1.2.3 version specifier, the crate resolver should unify the requirements and use exactly the version you specify.
I think this behavior might have been affected by the v2 crate resolver, but I don't know the details.
So I would have to add an entries to the dependencies section of the Cargo.toml for every dependency in the tree? And then those (recursive) dependencies get fixed to their version?
That's certainly one way to do it, but I'm not familiar enough with Cargo to know if it's the best way. Cargo.lock is also supposed to help with this sort of thing, but I don't know exactly what its mechanism is.
I believe Cargo.lock is just for transiently fixing your versions. For example, I think you cannot publish a crate without updating, see also the --frozen and --locked options for cargo publish.
There is the Rust Security Advisory Database https://rustsec.org/ with lists of crates.io crates that have vulnerabilities. There seems to also be tooling that checks dependencies against it.
I am also more dabbling in Rust, but I did check it once. It looks like a good mechanism for sharing information (reporting vulnerabilities) and using this data for auditing or other actions one may want to take.