Rust doesn’t have the kind of high performance garbage collection you’d want for this, so starting with unsafe makes perfect sense to me. Hopefully they keep the unsafe layer small to minimise mistakes, but it seems reasonable to me.
For some use cases, that means that "user code" can have no `unsafe`. But implementing a GC is very much not one of those.
If I were to write a toy JS runtime in Rust, I'd try to make it as safe as possible and deal with unsafe only when optimization starts to become necessary, but it's not like that's the only way to use Rust.
That's really just any language with a built-in package manager. Go somewhat sidesteps this by making you vendor your dependencies, but very few other languages escape the ballooning dependency graph.
However, it isn't really part of the Rust OSS culture to operate like that. The culture typically values safety over compile times, and prefers to lean on a deep stable of battle-hardened abstractions.