GHSA-32G3-35G9-WC9G
Vulnerability from github – Published: 2026-06-10 13:38 – Updated: 2026-06-10 13:38Affected: @hulumi/drift < 1.4.0 — Fixed in: 1.4.0 — Severity: Medium — CWE-755 (Improper Handling of Exceptional Conditions)
Summary
@hulumi/drift runs four adapters that each ask a different question about whether a resource has drifted (Pulumi-state diff, provider-version change, CloudTrail event, etc.). A classifier combines the adapters' answers into a verdict like None / none, ConsoleBreakGlass / high, or Mixed / high, and caches the verdict for 6 hours by default.
Two related bugs from one root cause — the classifier only read each adapter's detected: true/false field and ignored whether the adapter itself succeeded:
- Cached "all clear" on adapter failure. When an adapter failed (e.g. transient network error from the Automation API), the classifier read
detected: false, concluded "no drift", and cached the verdict asNone / nonefor 6 hours. A single transient failure could mask real console-break-glass mutations for the rest of the window. - Mixed verdicts without real evidence. The
Mixed / highandConsoleBreakGlass / highverdicts (incident severity) could fire on the "the CloudTrail probe round-tripped successfully" signal rather than actual evidence that anything had been changed via the console. Normal provider-API churn could end up falsely escalated to incident severity.
Impact
Consumers running drift detection in CI / cron could see transient adapter failures silently cached as "all clear" — masking real attacks for up to six hours — or see ordinary provider-version churn falsely promoted to incident severity. Either way, the verdict source was unreliable for downstream incident workflows that gate on it.
Patches
Upgrade to @hulumi/drift@1.4.0. Classifier-only fix (the TLA+-verified 6-row verdict matrix is byte-identical):
- adapter failures now fail closed to
Unknown / low, and degraded verdicts are not written to the cache; - the
Mixed/ConsoleBreakGlasspromotion now requires real CloudTrail event evidence rather than probe liveness.
Workarounds
Setting options.minConfidence: "medium" on the classifier call prevents the degraded None / none from being cached (it doesn't meet the threshold), partially mitigating case (1). No workaround for case (2).
Resources
- PR #178 (Cluster D); regression tests in
packages/drift/tests/classifier-fail-closed.test.ts.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@hulumi/drift"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.4.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-48036"
],
"database_specific": {
"cwe_ids": [
"CWE-755"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-10T13:38:50Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "**Affected:** `@hulumi/drift` `\u003c 1.4.0` \u2014 **Fixed in:** `1.4.0` \u2014 **Severity:** Medium \u2014 **CWE-755 (Improper Handling of Exceptional Conditions)**\n\n#### Summary\n\n`@hulumi/drift` runs four adapters that each ask a different question about whether a resource has drifted (Pulumi-state diff, provider-version change, CloudTrail event, etc.). A classifier combines the adapters\u0027 answers into a verdict like `None / none`, `ConsoleBreakGlass / high`, or `Mixed / high`, and caches the verdict for 6 hours by default.\n\nTwo related bugs from one root cause \u2014 the classifier only read each adapter\u0027s `detected: true/false` field and ignored whether the adapter itself succeeded:\n\n1. **Cached \"all clear\" on adapter failure.** When an adapter failed (e.g. transient network error from the Automation API), the classifier read `detected: false`, concluded \"no drift\", and cached the verdict as `None / none` for 6 hours. A single transient failure could mask real console-break-glass mutations for the rest of the window.\n2. **Mixed verdicts without real evidence.** The `Mixed / high` and `ConsoleBreakGlass / high` verdicts (incident severity) could fire on the \"the CloudTrail probe round-tripped successfully\" signal rather than actual evidence that anything had been changed via the console. Normal provider-API churn could end up falsely escalated to incident severity.\n\n#### Impact\n\nConsumers running drift detection in CI / cron could see transient adapter failures silently cached as \"all clear\" \u2014 masking real attacks for up to six hours \u2014 or see ordinary provider-version churn falsely promoted to incident severity. Either way, the verdict source was unreliable for downstream incident workflows that gate on it.\n\n#### Patches\n\nUpgrade to `@hulumi/drift@1.4.0`. Classifier-only fix (the TLA+-verified 6-row verdict matrix is byte-identical):\n\n- adapter failures now fail closed to `Unknown / low`, and degraded verdicts are not written to the cache;\n- the `Mixed` / `ConsoleBreakGlass` promotion now requires real CloudTrail event evidence rather than probe liveness.\n\n#### Workarounds\n\nSetting `options.minConfidence: \"medium\"` on the classifier call prevents the degraded `None / none` from being cached (it doesn\u0027t meet the threshold), partially mitigating case (1). No workaround for case (2).\n\n#### Resources\n\n- [PR #178](https://github.com/kerberosmansour/hulumi/pull/178) (Cluster D); regression tests in `packages/drift/tests/classifier-fail-closed.test.ts`.",
"id": "GHSA-32g3-35g9-wc9g",
"modified": "2026-06-10T13:38:50Z",
"published": "2026-06-10T13:38:50Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/kerberosmansour/hulumi/security/advisories/GHSA-32g3-35g9-wc9g"
},
{
"type": "WEB",
"url": "https://github.com/kerberosmansour/hulumi/pull/178"
},
{
"type": "PACKAGE",
"url": "https://github.com/kerberosmansour/hulumi"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:H/VA:L/SC:N/SI:H/SA:L",
"type": "CVSS_V4"
}
],
"summary": "@hulumi/drift: Drift classifier fails open on adapter errors and over-promotes Mixed verdicts"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.