From fe43126c426a80cc3e105b3401f39642f46cb5f7 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 5 Nov 2026 15:38:41 +0000 Subject: [PATCH 1/2] Add content from: Crates.io Supply-Chain Compromise Uses proc-macro1 Typosquat... --- .../pentesting-ci-cd-methodology.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md b/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md index d3e5e6d856..d2a058d0d6 100644 --- a/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md +++ b/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md @@ -122,6 +122,16 @@ Compromising a CI/CD pipeline or stealing credentials from it can let an attacke - **Workflow injection with stolen GitHub tokens**: a token with **`repo` + `workflow`** permissions can create a branch, commit a malicious file inside `.github/workflows/`, trigger it, collect the produced artifacts/logs, and then delete the temporary branch/workflow run to reduce traces.[[14]](#references)[[15]](#references)[[16]](#references)[[17]](#references)[[36]](#references) - **Wormable registry propagation**: stolen npm tokens should be validated for **publish** permissions and whether they bypass 2FA. If they do, enumerate writable packages, download their tarballs, inject a loader such as `setup.mjs`, set `preinstall` to execute it, bump the patch version, and republish. This turns one CI compromise into downstream auto-execution in other environments.[[2]](#references)[[23]](#references)[[24]](#references)[[25]](#references) +#### Cargo transitive dependencies and `build.rs` execution + +Cargo compiles and runs a package's root `build.rs` just before building that package; the script can use crates declared under `[build-dependencies]`.[[47]](#references) A downstream `cargo build` or `cargo check` can therefore execute a transitive dependency's script in a developer or CI environment without calling that dependency's library API.[[46]](#references)[[47]](#references) + +If an attacker can publish a new version of a trusted crate, they can add a dependency whose name resembles a legitimate crate and place the payload in the lookalike's `build.rs`.[[46]](#references) A fresh resolution or `cargo update` can pull the new dependency into `Cargo.lock`; execution occurs when Cargo subsequently builds or checks the project, **not** merely when it updates the lockfile.[[46]](#references)[[47]](#references) In the reported case, `proc-macro1` imitated `proc-macro2`: its library and normal configuration probes looked familiar, while `build.rs` contained the downloader and its manifest added `ureq`, `rustls`, and `base64` as build dependencies.[[46]](#references) + +To trace a suspicious crate in an already resolved project, inspect `Cargo.lock` and run `cargo tree --locked -i proc-macro1` from the relevant workspace member; `--workspace` extends reverse-dependency output across the workspace.[[48]](#references) Then inspect the **published crate**, not only its repository: compare its `Cargo.toml`, `build.rs`, and build dependencies against the expected crate and previous version.[[46]](#references) + +A downloader in `build.rs` can choose a payload by OS and architecture and launch it with null standard streams so the build does not visibly print the payload's output. On Windows, the reported dropper used a hidden `wscript`/VBS-to-PowerShell launcher instead of spawning the long-running payload directly: a child held in Cargo's job object could otherwise stall the build. This is a Cargo-specific constraint on detached execution, not a separate registry attack.[[46]](#references) + #### Package integrity when the serving source is compromised A compromised registry, mirror, CDN, or Git host can serve altered bytes for a dependency whose name and version have not changed. This differs from taking over a publisher account: TLS still authenticates the compromised endpoint, while a version pin alone does not authenticate the downloaded artifact. A lockfile hash helps only if its expected value was obtained through a trusted channel and the installer rejects a mismatch instead of accepting a new hash from that same source.[[37]](#references) @@ -207,5 +217,8 @@ Check this article about the top 10 CI/CD risks according to Cider: [**https://w - [43] [Rapid7 Analysis: GitLab CI/CD Regex Integer Overflow](https://rapid7.com/blog/post/ra-gitlab-ci-cd-regex-integer-overflow-technical-analysis-cve-2026-97229) - [44] [GitLab CI Lint API](https://docs.gitlab.com/api/lint/) - [45] [Ruby 3.3.12 regex recompilation source](https://github.com/ruby/ruby/blob/v3_3_12/re.c#L1586-L1664) +- [46] [Crates.io Supply-Chain Compromise Uses proc-macro1 Typosquat to Infect Rust Builds](https://research.jfrog.com/post/arrayref-proc-macro1-crates-io) +- [47] [Cargo Build Scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html) +- [48] [cargo tree](https://doc.rust-lang.org/cargo/commands/cargo-tree.html) {{#include ../banners/hacktricks-training.md}} From 85d167baa36b9f29bc6babf31b6998d74dcb7027 Mon Sep 17 00:00:00 2001 From: SirBroccoli Date: Thu, 5 Nov 2026 16:48:36 +0100 Subject: [PATCH 2/2] docs: repair PR placement and formatting after editorial review --- src/pentesting-ci-cd/pentesting-ci-cd-methodology.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md b/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md index d2a058d0d6..1a7a63dae0 100644 --- a/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md +++ b/src/pentesting-ci-cd/pentesting-ci-cd-methodology.md @@ -124,13 +124,13 @@ Compromising a CI/CD pipeline or stealing credentials from it can let an attacke #### Cargo transitive dependencies and `build.rs` execution -Cargo compiles and runs a package's root `build.rs` just before building that package; the script can use crates declared under `[build-dependencies]`.[[47]](#references) A downstream `cargo build` or `cargo check` can therefore execute a transitive dependency's script in a developer or CI environment without calling that dependency's library API.[[46]](#references)[[47]](#references) +Cargo normally compiles and runs a package's root `build.rs` before building that package. The script can use crates listed under `[build-dependencies]`. Thus, `cargo build` or `cargo check` can execute a transitive dependency's build script on a developer or CI host even when the project never calls that crate's library API.[[46]](#references)[[47]](#references) -If an attacker can publish a new version of a trusted crate, they can add a dependency whose name resembles a legitimate crate and place the payload in the lookalike's `build.rs`.[[46]](#references) A fresh resolution or `cargo update` can pull the new dependency into `Cargo.lock`; execution occurs when Cargo subsequently builds or checks the project, **not** merely when it updates the lockfile.[[46]](#references)[[47]](#references) In the reported case, `proc-macro1` imitated `proc-macro2`: its library and normal configuration probes looked familiar, while `build.rs` contained the downloader and its manifest added `ureq`, `rustls`, and `base64` as build dependencies.[[46]](#references) +A compromised publisher can add a lookalike crate as a dependency of a trusted crate and put the malicious behavior in the lookalike's `build.rs`. Its ordinary library source can still appear legitimate. A fresh resolution or `cargo update` can add that crate to `Cargo.lock`, but the script runs only when Cargo subsequently builds or checks it, not when the lockfile is updated.[[46]](#references)[[47]](#references) -To trace a suspicious crate in an already resolved project, inspect `Cargo.lock` and run `cargo tree --locked -i proc-macro1` from the relevant workspace member; `--workspace` extends reverse-dependency output across the workspace.[[48]](#references) Then inspect the **published crate**, not only its repository: compare its `Cargo.toml`, `build.rs`, and build dependencies against the expected crate and previous version.[[46]](#references) +To trace a suspicious crate in an already resolved project, inspect `Cargo.lock` and run `cargo tree --locked -i proc-macro1` from the relevant workspace member; `--workspace` extends reverse-dependency output across the workspace.[[48]](#references) Compare the published crate's `Cargo.toml`, `build.rs`, and build dependencies with its previous version and the legitimate crate it imitates, rather than trusting only its repository; see [published-artifact checks](#practical-checks-during-an-assessment).[[46]](#references) -A downloader in `build.rs` can choose a payload by OS and architecture and launch it with null standard streams so the build does not visibly print the payload's output. On Windows, the reported dropper used a hidden `wscript`/VBS-to-PowerShell launcher instead of spawning the long-running payload directly: a child held in Cargo's job object could otherwise stall the build. This is a Cargo-specific constraint on detached execution, not a separate registry attack.[[46]](#references) +On Windows, a long-running child of a Cargo build script can stay in Cargo's job object and stall the build. The reported dropper used a hidden `wscript`/VBS-to-PowerShell launcher to detach it instead of spawning it directly from `build.rs`.[[46]](#references) #### Package integrity when the serving source is compromised