chore(security): pin safe @asyncapi versions (Miasma RAT advisory, #3824)#3830
chore(security): pin safe @asyncapi versions (Miasma RAT advisory, #3824)#3830gpardhivvarma wants to merge 1 commit into
Conversation
…perdoc-dev#3824) The 2026-07-14 Miasma RAT supply-chain attack published malicious versions of four @asyncapi packages. superdoc reaches @asyncapi/specs via the apps/docs devDependency mintlify -> @mintlify/common -> @asyncapi/specs. The repo is not currently exposed (the lockfile resolves only @asyncapi/specs@6.8.1, and none of the malicious versions appear), but the bad 6.11.2 is reachable: @asyncapi/parser@3.4.0 declares "@asyncapi/specs": "^6.8.0", so an unfrozen re-resolution could adopt it. Add surgical pnpm.overrides that rewrite only the exact malicious versions to their safe counterparts, for all four advisory packages. The currently-resolved 6.8.1 is untouched (no forced upgrade) and no package resolution changes; the lockfile delta is limited to the overrides section. Verified with `pnpm install --frozen-lockfile`. No credential rotation is required — no malicious version was ever installed.
Code Review by Qodo
Context used 1. Baseline bypasses overrides
|
| '@asyncapi/specs@6.11.2': 6.11.1 | ||
| '@asyncapi/specs@6.11.2-alpha.1': 6.11.1 | ||
| '@asyncapi/generator@3.3.1': 3.3.0 | ||
| '@asyncapi/generator-helpers@1.1.1': 1.1.0 | ||
| '@asyncapi/generator-components@0.7.1': 0.7.0 |
There was a problem hiding this comment.
1. Lockfile contains @asyncapi/specs@6.11.2 📎 Requirement gap ⛨ Security
pnpm-lock.yaml now includes the known-malicious version identifiers (e.g., @asyncapi/specs@6.11.2) in the overrides keys, which fails the checklist’s grep-based success criteria. This may also trigger automated “malicious version present” scanners even though the override maps them to safe versions.
Agent Prompt
## Issue description
Compliance rule requires that lockfiles do not contain any of the known-malicious `@asyncapi/*` versions. The current `pnpm.overrides` approach writes those malicious version identifiers into `pnpm-lock.yaml` as override selectors, which fails a simple grep-based compliance check.
## Issue Context
The override mappings are security-positive (they redirect malicious versions to safe ones), but the checklist’s success criteria explicitly checks lockfiles for those version strings.
## Fix Focus Areas
- package.json[143-147]
- pnpm-lock.yaml[320-324]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| "@asyncapi/specs@6.11.2": "6.11.1", | ||
| "@asyncapi/specs@6.11.2-alpha.1": "6.11.1", | ||
| "@asyncapi/generator@3.3.1": "3.3.0", | ||
| "@asyncapi/generator-helpers@1.1.1": "1.1.0", | ||
| "@asyncapi/generator-components@0.7.1": "0.7.0", |
There was a problem hiding this comment.
2. Baseline bypasses overrides 🐞 Bug ⛨ Security
The new pnpm.overrides mitigation is not applied in visual-baseline.yml because the workflow checks out ref: stable and does not bring in the updated root package.json/pnpm-lock.yaml before running pnpm install --no-frozen-lockfile. This leaves a CI path (with secrets exported) where dependency re-resolution is not protected by the overrides added in this PR.
Agent Prompt
### Issue description
This PR adds security overrides in the repo root `package.json`/`pnpm-lock.yaml`, but `visual-baseline.yml` installs dependencies from the `stable` branch and never checks out the updated manifest/lockfile. As a result, the workflow’s `pnpm install --no-frozen-lockfile` does not use these overrides.
### Issue Context
- The mitigation is implemented via `pnpm.overrides` in the repo root.
- `visual-baseline.yml` checks out `stable`, then runs an unfrozen install.
- The job exports multiple secrets as environment variables.
### Fix Focus Areas
- package.json[126-154]
- pnpm-lock.yaml[304-331]
- .github/workflows/visual-baseline.yml[31-52]
### Suggested fix
Update `.github/workflows/visual-baseline.yml` so the install step uses a revision that contains the new overrides, e.g.:
- also checkout `package.json` and `pnpm-lock.yaml` from `main` in the "Get visual test infrastructure from main" step (similar to how it already checks out `tests/visual pnpm-workspace.yaml patches/`), **or**
- stop installing from `stable` for this job (checkout `main`), **or**
- alternatively, inject equivalent pnpm override configuration in the workflow before `pnpm install`.
Keep `--no-frozen-lockfile` only if it’s required for the cross-branch file mix; otherwise prefer using a consistent lockfile + `--frozen-lockfile` to avoid re-resolution.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a430171ed0
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "@asyncapi/specs@6.11.2": "6.11.1", | ||
| "@asyncapi/specs@6.11.2-alpha.1": "6.11.1", | ||
| "@asyncapi/generator@3.3.1": "3.3.0", | ||
| "@asyncapi/generator-helpers@1.1.1": "1.1.0", | ||
| "@asyncapi/generator-components@0.7.1": "0.7.0", |
There was a problem hiding this comment.
Don’t rely on version-qualified overrides as exact-version guards
When the lockfile is regenerated, pnpm 10.25 matches pkg@range override keys against each dependency's declared range by intersection, not against the version that would have been resolved; the current @asyncapi/parser@3.4.0 declares @asyncapi/specs: ^6.8.0, which intersects 6.11.2. These entries therefore rewrite that broad edge to 6.11.1 rather than only replacing an actually resolved 6.11.2, so an unfrozen refresh such as .github/workflows/visual-baseline.yml's pnpm install --ignore-scripts --no-frozen-lockfile will turn this into a broad/stale pin that also suppresses future safe 6.11.3/6.12.x resolutions. If the intent is an exact bad-version block, use a lockfile/advisory check; if the intent is a temporary safe pin, make the broad pin explicit and easy to remove.
Useful? React with 👍 / 👎.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
Addresses #3824 — the 2026-07-14 Miasma RAT supply-chain attack that published malicious, credential-stealing versions of four
@asyncapipackages. superdoc reaches@asyncapi/specsvia theapps/docsdevDependencymintlify@4.2.624→@mintlify/common/@asyncapi/parser→@asyncapi/specs.Exposure assessment
Not currently exposed — verified across every lockfile in the repo:
pnpm-lock.yamlresolves only@asyncapi/specs@6.8.1(safe) and@asyncapi/parser@3.4.0(not on the advisory list). None of the malicious versions appear; the three@asyncapi/generator*packages aren't in the tree at all.demos/grading-papers/pnpm-lock.yaml,.github/scripts/package-lock.json, andtests/consumer-typecheck/package-lock.jsoncontain no@asyncapi/mintlify.But the bad version is genuinely reachable:
@asyncapi/parser@3.4.0declares"@asyncapi/specs": "^6.8.0"(>=6.8.0 <7.0.0), which includes the malicious6.11.2. An unfrozen re-resolution (e.g.visual-baseline.ymlrunspnpm install --no-frozen-lockfile) could adopt it.No credential rotation is required — no malicious version was ever installed. (That step only applies if a malicious version had been pinned.)
Change
Surgical
pnpm.overrides(rootpackage.json) that rewrite only the exact malicious versions to their safe counterparts, for all four advisory packages:@asyncapi/specs6.11.2,6.11.2-alpha.1→6.11.1@asyncapi/generator3.3.1→3.3.0@asyncapi/generator-helpers1.1.1→1.1.0@asyncapi/generator-components0.7.1→0.7.0@asyncapi/specs@6.8.1is untouched (no forced upgrade), and a legitimate future6.11.3would still be allowed.6.11.1satisfies parser's^6.8.0.protobufjs@7/protobufjs@8) and pnpm's documented security-override pattern.Verification
git diffis exactly 10 insertions — five inpackage.json, five in thepnpm-lock.yamloverrides:section. No package resolution changes / no lockfile churn.pnpm install --frozen-lockfilesucceeds (lockfile internally consistent — matters because most CI jobs run frozen-by-default).@asyncapi/specs@6.8.1is unchanged.