4 ms·
He describes compile time backdoors (Rust macros) and backdoors that can be triggered by loading the code into a standard development environment (standard hook
by stubish 5y ago
He describes compile time backdoors (Rust macros) and backdoors that can be triggered by loading the code into a standard development environment (standard hooks called by code editors on load). Both of these are novel. Name squatting and account compromise are common to several ecosystems, but using a compromised account to backdoor a transient dependency that automatically executes code when your CI system compiles, allowing it to steal the tokens you use to publish builds to your customers, while you are asleep, is somewhat novel and worrying. And then as a bonus, compromise your laptop when you start inspecting the rubble to work out what just happened.
- lilyball 5y agoNeither of these are novel. Compile-time behavior in existing language ecosystems such as C/C++ require running supplied configure/build scripts. The idea of running untrusted code at build-time is not remotely new. The part about triggered by loading code into a standard dev environment is identical to "my dev environment automatically compiles dependencies for me", and is something that is handled by the dev environment (e.g. VSCode's "trusted workspace" stuff) rather than the language. Rust is not responsible for IDE tooling running build scripts and compile-time macros. Also FWIW, rust-analyzer has settings for whether to do this (separate from VSCode's trusted workspaces).
- stubish 5y agoWhile my C/C++ knowledge is minimal and decades out of date, I don't recall dependency management systems that automatically download new versions of transient dependencies rather than using the tarballs you provided or simply linked with whatever it found in $INCLUDES (although I do recall custom build scripts that 'helpfully' tried to download and build dependencies like libssl, always annoying and often MITMable). Yes, you will be running untrusted code but you downloaded it and all the transient dependencies and had the opportunity to audit it (or realize you could be using the prebuilt OS packages instead and choosing to trust the those maintainers). I think Python shares the same issue as Rust in that the standard tooling will by default pull down newer versions of packages and building them can run arbitrary code. I don't think Go does, as I don't think the potentially dangerous code generation comments are run by default?
- lilyball 5y ago> I don't recall dependency management systems that automatically download new versions of transient dependencies This isn't how modern dependency management systems like Rust work either though. Modern systems use a lockfile to pin the versions, and they only get updated as a result of direct action (either explicitly updating dependencies, or declaring a new dependency that requires a newer version of the transient dependency). You can choose to audit the new dependency versions based on the lockfile change at your discretion, just like if you have to update e.g. openssl you can choose whether or not to actually audit the code changes instead of just bumping the version you declared in your CMakeLists.
- pdimitar 5y agoThank you for the breakdown. I was under the impression that all these techniques are rather known (e.g. Homebrew also allows for random script executing by the mere virtue of installing a seemingly unrelated package) but I might have been wrong.