Common Weakness Enumeration

CWE-299

Allowed

Improper Check for Certificate Revocation

Abstraction: Base · Status: Draft

The product does not check or incorrectly checks the revocation status of a certificate, which may cause it to use a certificate that has been compromised.

23 vulnerabilities reference this CWE, most recent first.

CVE-2020-1675 (GCVE-0-2020-1675)

Vulnerability from cvelistv5 – Published: 2020-10-16 20:31 – Updated: 2024-09-16 22:01
VLAI
Title
Juniper Networks Mist Cloud UI: SAML authentication certificate vulnerability.
Summary
When Security Assertion Markup Language (SAML) authentication is enabled, Juniper Networks Mist Cloud UI might incorrectly process invalid authentication certificates which could allow a malicious network-based user to access unauthorized data. This issue affects all Juniper Networks Mist Cloud UI versions prior to September 2 2020.
CWE
  • CWE-299 - Improper Check for Certificate Revocation
References
URL Tags
https://kb.juniper.net/JSA11072 x_refsource_CONFIRM
Impacted products
Vendor Product Version
Juniper Networks MIST Cloud UI Affected: unspecified , < 09/02/2020 (custom)
Create a notification for this product.
Date Public
2020-10-14 00:00
Show details on NVD website

{
  "containers": {
    "adp": [
      {
        "providerMetadata": {
          "dateUpdated": "2024-08-04T06:46:30.238Z",
          "orgId": "af854a3a-2127-422b-91ae-364da2661108",
          "shortName": "CVE"
        },
        "references": [
          {
            "tags": [
              "x_refsource_CONFIRM",
              "x_transferred"
            ],
            "url": "https://kb.juniper.net/JSA11072"
          }
        ],
        "title": "CVE Program Container"
      }
    ],
    "cna": {
      "affected": [
        {
          "product": "MIST Cloud UI",
          "vendor": "Juniper Networks",
          "versions": [
            {
              "lessThan": "09/02/2020",
              "status": "affected",
              "version": "unspecified",
              "versionType": "custom"
            }
          ]
        }
      ],
      "datePublic": "2020-10-14T00:00:00.000Z",
      "descriptions": [
        {
          "lang": "en",
          "value": "When Security Assertion Markup Language (SAML) authentication is enabled, Juniper Networks Mist Cloud UI might incorrectly process invalid authentication certificates which could allow a malicious network-based user to access unauthorized data. This issue affects all Juniper Networks Mist Cloud UI versions prior to September 2 2020."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "attackComplexity": "LOW",
            "attackVector": "NETWORK",
            "availabilityImpact": "LOW",
            "baseScore": 8.3,
            "baseSeverity": "HIGH",
            "confidentialityImpact": "LOW",
            "integrityImpact": "LOW",
            "privilegesRequired": "NONE",
            "scope": "CHANGED",
            "userInteraction": "NONE",
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L",
            "version": "3.1"
          }
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-299",
              "description": "CWE-299 Improper Check for Certificate Revocation",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2020-10-16T20:31:32.000Z",
        "orgId": "8cbe9d5a-a066-4c94-8978-4b15efeae968",
        "shortName": "juniper"
      },
      "references": [
        {
          "tags": [
            "x_refsource_CONFIRM"
          ],
          "url": "https://kb.juniper.net/JSA11072"
        }
      ],
      "solutions": [
        {
          "lang": "en",
          "value": "Mist Cloud UI has been updated on September 2 2020 to resolve this specific issue."
        }
      ],
      "source": {
        "advisory": "JSA11072",
        "discovery": "INTERNAL"
      },
      "title": "Juniper Networks Mist Cloud UI: SAML authentication certificate vulnerability.",
      "workarounds": [
        {
          "lang": "en",
          "value": "No workarounds are required since the issue has been resolved in the Mist cloud UI."
        }
      ],
      "x_generator": {
        "engine": "Vulnogram 0.0.9"
      },
      "x_legacyV4Record": {
        "CVE_data_meta": {
          "ASSIGNER": "sirt@juniper.net",
          "DATE_PUBLIC": "2020-10-14T16:00:00.000Z",
          "ID": "CVE-2020-1675",
          "STATE": "PUBLIC",
          "TITLE": "Juniper Networks Mist Cloud UI: SAML authentication certificate vulnerability."
        },
        "affects": {
          "vendor": {
            "vendor_data": [
              {
                "product": {
                  "product_data": [
                    {
                      "product_name": "MIST Cloud UI",
                      "version": {
                        "version_data": [
                          {
                            "version_affected": "\u003c",
                            "version_value": "09/02/2020"
                          }
                        ]
                      }
                    }
                  ]
                },
                "vendor_name": "Juniper Networks"
              }
            ]
          }
        },
        "data_format": "MITRE",
        "data_type": "CVE",
        "data_version": "4.0",
        "description": {
          "description_data": [
            {
              "lang": "eng",
              "value": "When Security Assertion Markup Language (SAML) authentication is enabled, Juniper Networks Mist Cloud UI might incorrectly process invalid authentication certificates which could allow a malicious network-based user to access unauthorized data. This issue affects all Juniper Networks Mist Cloud UI versions prior to September 2 2020."
            }
          ]
        },
        "generator": {
          "engine": "Vulnogram 0.0.9"
        },
        "impact": {
          "cvss": {
            "attackComplexity": "LOW",
            "attackVector": "NETWORK",
            "availabilityImpact": "LOW",
            "baseScore": 8.3,
            "baseSeverity": "HIGH",
            "confidentialityImpact": "LOW",
            "integrityImpact": "LOW",
            "privilegesRequired": "NONE",
            "scope": "CHANGED",
            "userInteraction": "NONE",
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L",
            "version": "3.1"
          }
        },
        "problemtype": {
          "problemtype_data": [
            {
              "description": [
                {
                  "lang": "eng",
                  "value": "CWE-299 Improper Check for Certificate Revocation"
                }
              ]
            }
          ]
        },
        "references": {
          "reference_data": [
            {
              "name": "https://kb.juniper.net/JSA11072",
              "refsource": "CONFIRM",
              "url": "https://kb.juniper.net/JSA11072"
            }
          ]
        },
        "solution": [
          {
            "lang": "en",
            "value": "Mist Cloud UI has been updated on September 2 2020 to resolve this specific issue."
          }
        ],
        "source": {
          "advisory": "JSA11072",
          "discovery": "INTERNAL"
        },
        "work_around": [
          {
            "lang": "en",
            "value": "No workarounds are required since the issue has been resolved in the Mist cloud UI."
          }
        ]
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "8cbe9d5a-a066-4c94-8978-4b15efeae968",
    "assignerShortName": "juniper",
    "cveId": "CVE-2020-1675",
    "datePublished": "2020-10-16T20:31:32.283Z",
    "dateReserved": "2019-11-04T00:00:00.000Z",
    "dateUpdated": "2024-09-16T22:01:32.790Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.1"
}

GHSA-45V3-38PC-874V

Vulnerability from github – Published: 2025-01-13 16:14 – Updated: 2025-01-14 21:05
VLAI
Summary
notation-go's timestamp signature generation lacks certificate revocation check
Details

This issue was identified during Quarkslab's audit of the timestamp feature.

Summary

During the timestamp signature generation, the revocation status of the certificate(s) used to generate the timestamp signature was not verified.

Details

During timestamp signature generation, notation-go did not check the revocation status of the certificate chain used by the TSA. This oversight creates a vulnerability that could be exploited through a Man-in-The-Middle attack. An attacker could potentially use a compromised, intermediate, or revoked leaf certificate to generate a malicious countersignature, which would then be accepted and stored by notation.

Impact

This could lead to denial of service scenarios, particularly in CI/CD environments during signature verification processes because timestamp signature would fail due to the presence of a revoked certificate(s) potentially disrupting operations.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.3.0-rc.1"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/notaryproject/notation-go"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.2.0-beta.1"
            },
            {
              "fixed": "1.3.0-rc.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-56138"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-01-13T16:14:07Z",
    "nvd_published_at": "2025-01-13T22:15:14Z",
    "severity": "MODERATE"
  },
  "details": "This issue was identified during Quarkslab\u0027s audit of the timestamp feature.\n\n### Summary\nDuring the timestamp signature generation, the revocation status of the certificate(s) used to generate the timestamp signature was not verified.\n\n### Details\nDuring timestamp signature generation, notation-go did not check the revocation status of the certificate chain used by the TSA. This oversight creates a vulnerability that could be exploited through a Man-in-The-Middle attack. An attacker could potentially use a compromised, intermediate, or revoked leaf certificate to generate a malicious countersignature, which would then be accepted and stored by `notation`.\n\n### Impact\nThis could lead to denial of service scenarios, particularly in CI/CD environments during signature verification processes because timestamp signature would fail due to the presence of a revoked certificate(s) potentially disrupting operations.\n",
  "id": "GHSA-45v3-38pc-874v",
  "modified": "2025-01-14T21:05:54Z",
  "published": "2025-01-13T16:14:07Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/notaryproject/notation-go/security/advisories/GHSA-45v3-38pc-874v"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-56138"
    },
    {
      "type": "WEB",
      "url": "https://github.com/notaryproject/notation-go/commit/e7005a6d13e5ba472d4e166fbb085152f909e102"
    },
    {
      "type": "WEB",
      "url": "https://github.com/notaryproject/notation-go/commit/e99be1954a15673020150c5f8800b8174cd7428d"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/notaryproject/notation-go"
    },
    {
      "type": "WEB",
      "url": "https://pkg.go.dev/vuln/GO-2025-3381"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "notation-go\u0027s timestamp signature generation lacks certificate revocation check"
}

GHSA-5J2H-PWP3-258R

Vulnerability from github – Published: 2025-07-21 21:31 – Updated: 2025-07-21 21:31
VLAI
Details

IBM Cognos Analytics Mobile (iOS) 1.1.0 through 1.1.22

is vulnerable to authentication bypass by using the Local Authentication Framework library which is not needed as biometric authentication is not used in the application.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-36057"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-07-21T19:15:28Z",
    "severity": "MODERATE"
  },
  "details": "IBM Cognos Analytics Mobile (iOS) 1.1.0 through 1.1.22 \n\nis vulnerable to authentication bypass by using the Local Authentication Framework library which is not needed as biometric authentication is not used in the application.",
  "id": "GHSA-5j2h-pwp3-258r",
  "modified": "2025-07-21T21:31:37Z",
  "published": "2025-07-21T21:31:37Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-36057"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7239635"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-8CW5-PXRW-VQHC

Vulnerability from github – Published: 2025-10-27 12:32 – Updated: 2025-10-27 12:32
VLAI
Details

Incorrect validation of OCSP certificates vulnerability in TheGreenBow VPN, versions 7.5 and 7.6. During the IKEv2 authentication step, the OCSP-enabled VPN client establishes the tunnel even if it does not receive an OCSP response or if the OCSP response signature is invalid.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-11955"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-10-27T12:15:32Z",
    "severity": "HIGH"
  },
  "details": "Incorrect validation of OCSP certificates vulnerability in TheGreenBow VPN, versions 7.5 and 7.6. During the IKEv2 authentication step, the OCSP-enabled VPN client establishes the tunnel even if it does not receive an OCSP response or if the OCSP response signature is invalid.",
  "id": "GHSA-8cw5-pxrw-vqhc",
  "modified": "2025-10-27T12:32:52Z",
  "published": "2025-10-27T12:32:52Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-11955"
    },
    {
      "type": "WEB",
      "url": "https://www.incibe.es/en/incibe-cert/notices/aviso/incorrect-validation-ocsp-certificates-thegreenbow-vpn-client-windows"
    },
    {
      "type": "WEB",
      "url": "https://www.thegreenbow.com/en/support/security-alerts"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-8F6J-263M-G72X

Vulnerability from github – Published: 2026-07-13 23:49 – Updated: 2026-07-13 23:49
VLAI
Summary
Apple App Store Server Python Library: SignedDataVerifier accepts stale OCSP GOOD responses and can bypass certificate revocation checks
Details

Summary

SignedDataVerifier attempts to perform online revocation checking when enable_online_checks=True, but its OCSP validation logic accepts stale GOOD responses as valid indefinitely. In appstoreserverlibrary/signed_data_verifier.py, _ChainVerifier.check_ocsp_status() verifies the OCSP response signature and CertID match, but never validates the freshness window carried by producedAt, thisUpdate, or nextUpdate.

As a result, a previously valid signed OCSP GOOD response can be replayed after it is expired, and the library will still treat the certificate as good. If an App Store signing certificate or intermediate is ever revoked, applications using this library with online checks enabled can continue accepting JWS objects signed with the revoked key as long as a stale signed OCSP response is replayed.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.1.1"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "app-store-server-library"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.2.0"
            },
            {
              "fixed": "3.1.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-295",
      "CWE-299"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-13T23:49:14Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\n`SignedDataVerifier` attempts to perform online revocation checking when `enable_online_checks=True`, but its OCSP validation logic accepts stale `GOOD` responses as valid indefinitely. In `appstoreserverlibrary/signed_data_verifier.py`, `_ChainVerifier.check_ocsp_status()` verifies the OCSP response signature and CertID match, but never validates the freshness window carried by `producedAt`, `thisUpdate`, or `nextUpdate`.\n\nAs a result, a previously valid signed OCSP `GOOD` response can be replayed after it is expired, and the library will still treat the certificate as good. If an App Store signing certificate or intermediate is ever revoked, applications using this library with online checks enabled can continue accepting JWS objects signed with the revoked key as long as a stale signed OCSP response is replayed.",
  "id": "GHSA-8f6j-263m-g72x",
  "modified": "2026-07-13T23:49:14Z",
  "published": "2026-07-13T23:49:14Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/apple/app-store-server-library-python/security/advisories/GHSA-8f6j-263m-g72x"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/apple/app-store-server-library-python"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Apple App Store Server Python Library: SignedDataVerifier accepts stale OCSP GOOD responses and can bypass certificate revocation checks"
}

GHSA-CM26-5974-52H8

Vulnerability from github – Published: 2026-07-14 20:28 – Updated: 2026-07-14 20:28
VLAI
Summary
nebula-mesh: Certificate revocation is never enforced at the mesh
Details

Summary

nebula-mesh revokes a host by adding its certificate fingerprint to a per-CA blocklist and shipping that list to every other agent on each poll. Slack's Nebula enforces certificate revocation ONLY through the pki.blocklist list in config.yml (no CRL/OCSP). The project's own code states this: internal/pki/durations.go:15 — "Revocation via the blocklist remains the immediate security control."

The server side is fully implemented (computes per-CA blocklist via GetBlocklistForCA, returns it in the agent-updates response, sets has_updates=true when non-empty). The agent side was never implemented:

  1. The agent decodes the blocklist JSON field into UpdatesResponse.Blocklist (internal/agent/poller.go:33) and then DISCARDS it — poll() applies CertificatePEM, CACertPEM, ConfigYAML, but never references updates.Blocklist (internal/agent/poller.go:300-339).
  2. The config generator has NO field to emit pki.blocklistpkiSection is only ca/cert/key (internal/configgen/marshal.go:42-46) and GeneratorInput carries no blocklist (internal/configgen/generator.go:23-52). So even the server-rendered config.yml shipped via ConfigYAML cannot carry it.

Result: a blocked/offboarded/compromised host's certificate is never rejected by its peers. Its handshakes keep succeeding for the full remaining cert lifetime — up to 30 days for agent hosts (DefaultAgentCertDuration) and 365 days for mobile hosts (DefaultMobileCertDuration). Blocking a host in the UI/API has no effect on the data plane.

Affected components

  • Agent drops the blocklist: internal/agent/poller.go:33 (decode target), internal/agent/poller.go:300-339 (poll() applies cert/CA/config, never the blocklist).
  • Generator cannot emit it: internal/configgen/marshal.go:42-46 (pkiSection{CA,Cert,Key}), internal/configgen/generator.go:23-52 (GeneratorInput has no blocklist), internal/api/enroll.go:255-330 (renderHostConfig, source of shipped ConfigYAML).
  • Server correctly produces/ships it (proves intent): internal/store/sqlite.go:2034 (GetBlocklistForCA), internal/api/updates.go:182-191 (resp.Blocklist), internal/api/updates.go:277 (has_updates set on blocklist change).
  • Dead helper: internal/pki/blocklist.go (Blocklist type) is never used in non-test code — no server-side enforcement either.

Reachability (hop by hop)

  1. Operator clicks Block on host B (or B is compromised/offboarded). B's fingerprint enters the per-CA blocklist table.
  2. Every other host A under the same CA polls GET /api/v1/agent/updates; server returns blocklist: [<B-fp>, ...] and has_updates=true.
  3. A's agent decodes Blocklist then discards it; poll() has no blocklist branch.
  4. Even on a config re-render, configgen.Generate emits pki: {ca,cert,key} with no blocklist key (proven by PoC).
  5. A's Nebula daemon has an empty blocklist and accepts handshakes from B's still-valid cert. B keeps full mesh access.

Impact

Revocation is the only in-band mechanism that isolates a compromised/offboarded host from a Nebula mesh. Because the blocklist never reaches any peer's config.yml, a Blocked host retains full overlay reachability to every peer under its CA (and internal services on the mesh) for up to 30d (agent) / 365d (mobile). An attacker who exfiltrates host.key+host.crt can run stock slackhq/nebula directly, ignore the agent's 403/410 poll responses, and stay connected after the operator revokes the host. Operator-visible state (UI shows blocked, audit log records it) is misleading.

Proof of Concept (benign)

internal/configgen/blocklist_poc_test.go renders a fully-populated host config and asserts the output contains the pki section but NO blocklist key:

$ go test ./internal/configgen/ -run TestPoC_NMESH001 -v
=== RUN   TestPoC_NMESH001_GeneratedConfigOmitsBlocklist
    CONFIRMED: generated config has a pki section but no blocklist key
    pki:
      ca: /etc/nebula/ca.crt
      cert: /etc/nebula/host.crt
      key: /etc/nebula/host.key
    ...
--- PASS

The agent half is verifiable by inspection: poll() has branches for CertificatePEM/CACertPEM/ConfigYAML/RekeyRequired but none for Blocklist.

Distinctness

NOT a duplicate of GHSA-339v / CVE-2026-53602 (revocation durability = a blocked host getting a NEW cert re-issued; its fix CheckIssuanceAllowed is present and orthogonal). This bug is that the EXISTING cert is never rejected at peers — the distribution/enforcement layer. Checked against all 17 known advisories; none cover blocklist application in the agent or pki.blocklist generation.

Remediation

  1. Add Blocklist []safeString to pkiSection (yaml blocklist,omitempty) and GeneratorInput; consider also pki.disconnect_invalid: true.
  2. Have the agent apply updates.Blocklist by re-rendering/rewriting config.yml + SIGHUP (same path as ConfigYAML). Simplest: fold the blocklist into the server-rendered ConfigYAML so it flows through the existing write path.
  3. Add a regression test asserting a non-empty server blocklist yields a pki.blocklist entry in the agent's written config.yml.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/forgekeep/nebula-mesh"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.7.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-61699"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299",
      "CWE-672"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-14T20:28:18Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\nnebula-mesh revokes a host by adding its certificate fingerprint to a per-CA blocklist and shipping that list to every other agent on each poll. Slack\u0027s Nebula enforces certificate revocation ONLY through the `pki.blocklist` list in `config.yml` (no CRL/OCSP). The project\u0027s own code states this: `internal/pki/durations.go:15` \u2014 \"Revocation via the blocklist remains the immediate security control.\"\n\nThe server side is fully implemented (computes per-CA blocklist via `GetBlocklistForCA`, returns it in the agent-updates response, sets `has_updates=true` when non-empty). The agent side was never implemented:\n\n1. The agent decodes the `blocklist` JSON field into `UpdatesResponse.Blocklist` (`internal/agent/poller.go:33`) and then DISCARDS it \u2014 `poll()` applies `CertificatePEM`, `CACertPEM`, `ConfigYAML`, but never references `updates.Blocklist` (`internal/agent/poller.go:300-339`).\n2. The config generator has NO field to emit `pki.blocklist` \u2014 `pkiSection` is only `ca`/`cert`/`key` (`internal/configgen/marshal.go:42-46`) and `GeneratorInput` carries no blocklist (`internal/configgen/generator.go:23-52`). So even the server-rendered `config.yml` shipped via `ConfigYAML` cannot carry it.\n\nResult: a blocked/offboarded/compromised host\u0027s certificate is never rejected by its peers. Its handshakes keep succeeding for the full remaining cert lifetime \u2014 up to 30 days for agent hosts (`DefaultAgentCertDuration`) and 365 days for mobile hosts (`DefaultMobileCertDuration`). Blocking a host in the UI/API has no effect on the data plane.\n\n### Affected components\n\n- Agent drops the blocklist: `internal/agent/poller.go:33` (decode target), `internal/agent/poller.go:300-339` (poll() applies cert/CA/config, never the blocklist).\n- Generator cannot emit it: `internal/configgen/marshal.go:42-46` (`pkiSection{CA,Cert,Key}`), `internal/configgen/generator.go:23-52` (`GeneratorInput` has no blocklist), `internal/api/enroll.go:255-330` (`renderHostConfig`, source of shipped ConfigYAML).\n- Server correctly produces/ships it (proves intent): `internal/store/sqlite.go:2034` (`GetBlocklistForCA`), `internal/api/updates.go:182-191` (`resp.Blocklist`), `internal/api/updates.go:277` (`has_updates` set on blocklist change).\n- Dead helper: `internal/pki/blocklist.go` (`Blocklist` type) is never used in non-test code \u2014 no server-side enforcement either.\n\n### Reachability (hop by hop)\n\n1. Operator clicks Block on host B (or B is compromised/offboarded). B\u0027s fingerprint enters the per-CA `blocklist` table.\n2. Every other host A under the same CA polls `GET /api/v1/agent/updates`; server returns `blocklist: [\u003cB-fp\u003e, ...]` and `has_updates=true`.\n3. A\u0027s agent decodes `Blocklist` then discards it; `poll()` has no blocklist branch.\n4. Even on a config re-render, `configgen.Generate` emits `pki: {ca,cert,key}` with no `blocklist` key (proven by PoC).\n5. A\u0027s Nebula daemon has an empty blocklist and accepts handshakes from B\u0027s still-valid cert. B keeps full mesh access.\n\n### Impact\n\nRevocation is the only in-band mechanism that isolates a compromised/offboarded host from a Nebula mesh. Because the blocklist never reaches any peer\u0027s config.yml, a Blocked host retains full overlay reachability to every peer under its CA (and internal services on the mesh) for up to 30d (agent) / 365d (mobile). An attacker who exfiltrates `host.key`+`host.crt` can run stock slackhq/nebula directly, ignore the agent\u0027s 403/410 poll responses, and stay connected after the operator revokes the host. Operator-visible state (UI shows blocked, audit log records it) is misleading.\n\n### Proof of Concept (benign)\n\n`internal/configgen/blocklist_poc_test.go` renders a fully-populated host config and asserts the output contains the `pki` section but NO `blocklist` key:\n\n```\n$ go test ./internal/configgen/ -run TestPoC_NMESH001 -v\n=== RUN   TestPoC_NMESH001_GeneratedConfigOmitsBlocklist\n    CONFIRMED: generated config has a pki section but no blocklist key\n    pki:\n      ca: /etc/nebula/ca.crt\n      cert: /etc/nebula/host.crt\n      key: /etc/nebula/host.key\n    ...\n--- PASS\n```\n\nThe agent half is verifiable by inspection: `poll()` has branches for CertificatePEM/CACertPEM/ConfigYAML/RekeyRequired but none for Blocklist.\n\n### Distinctness\n\nNOT a duplicate of GHSA-339v / CVE-2026-53602 (revocation durability = a blocked host getting a NEW cert re-issued; its fix `CheckIssuanceAllowed` is present and orthogonal). This bug is that the EXISTING cert is never rejected at peers \u2014 the distribution/enforcement layer. Checked against all 17 known advisories; none cover blocklist application in the agent or `pki.blocklist` generation.\n\n### Remediation\n\n1. Add `Blocklist []safeString` to `pkiSection` (yaml `blocklist,omitempty`) and `GeneratorInput`; consider also `pki.disconnect_invalid: true`.\n2. Have the agent apply `updates.Blocklist` by re-rendering/rewriting `config.yml` + SIGHUP (same path as `ConfigYAML`). Simplest: fold the blocklist into the server-rendered `ConfigYAML` so it flows through the existing write path.\n3. Add a regression test asserting a non-empty server blocklist yields a `pki.blocklist` entry in the agent\u0027s written config.yml.",
  "id": "GHSA-cm26-5974-52h8",
  "modified": "2026-07-14T20:28:18Z",
  "published": "2026-07-14T20:28:18Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/security/advisories/GHSA-cm26-5974-52h8"
    },
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/commit/0426e2f224a9b1e2029029bf923c93ed39d21cdb"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/forgekeep/nebula-mesh"
    },
    {
      "type": "WEB",
      "url": "https://github.com/forgekeep/nebula-mesh/releases/tag/v0.7.1"
    }
  ],
  "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:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "nebula-mesh: Certificate revocation is never enforced at the mesh"
}

GHSA-FVQ9-7G3P-R5G2

Vulnerability from github – Published: 2026-07-14 18:31 – Updated: 2026-07-14 18:31
VLAI
Details

A security issue exists within CompactLogix® 5380, ControlLogix® 5580, and EN4 communication modules related to CIP Security certificate revocation handling. The security issue stems from the controller failing to properly reject certificates signed by an intermediate certificate that has been revoked via a Certificate Revocation List (CRL). This could allow a network-based attacker to establish a connection using a certificate that should be untrusted, potentially bypassing CIP Security protections.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-9636"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-14T16:17:05Z",
    "severity": "HIGH"
  },
  "details": "A security issue exists within CompactLogix\u00ae 5380, ControlLogix\u00ae 5580, and EN4 communication modules related to CIP Security certificate revocation handling. The security issue stems from the controller failing to properly reject certificates signed by an intermediate certificate that has been revoked via a Certificate Revocation List (CRL). This could allow a network-based attacker to establish a connection using a certificate that should be untrusted, potentially bypassing CIP Security protections.",
  "id": "GHSA-fvq9-7g3p-r5g2",
  "modified": "2026-07-14T18:31:56Z",
  "published": "2026-07-14T18:31:56Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-9636"
    },
    {
      "type": "WEB",
      "url": "https://www.rockwellautomation.com/en-us/trust-center/security-advisories/advisory.SD1788.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-G25M-MG72-9V2W

Vulnerability from github – Published: 2022-05-24 17:28 – Updated: 2023-12-12 21:31
VLAI
Details

Patient Information Center iX (PICiX) Versions B.02, C.02, C.03, PerformanceBridge Focal Point Version A.01, IntelliVue patient monitors MX100, MX400-MX850, and MP2-MP90 Versions N and prior, IntelliVue X3 and X2 Versions N and prior. The software does not check or incorrectly checks the revocation status of a certificate, which may cause it to use a compromised certificate.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-16228"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-09-11T13:15:00Z",
    "severity": "MODERATE"
  },
  "details": "Patient Information Center iX (PICiX) Versions B.02, C.02, C.03, PerformanceBridge Focal Point Version A.01, IntelliVue patient monitors MX100, MX400-MX850, and MP2-MP90 Versions N and prior, IntelliVue X3 and X2 Versions N and prior. The software does not check or incorrectly checks the revocation status of a certificate, which may cause it to use a compromised certificate.",
  "id": "GHSA-g25m-mg72-9v2w",
  "modified": "2023-12-12T21:31:06Z",
  "published": "2022-05-24T17:28:06Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-16228"
    },
    {
      "type": "WEB",
      "url": "https://us-cert.cisa.gov/ics/advisories/icsma-20-254-01"
    },
    {
      "type": "WEB",
      "url": "https://www.philips.com/productsecurity"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:A/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-G27R-R6PH-VF5R

Vulnerability from github – Published: 2026-05-04 22:28 – Updated: 2026-05-04 22:28
VLAI
Summary
sequoia-git has broken hard revocation handling
Details

Before sq-git checks if a commit can be authenticated, it first looks for hard revocations. Because parsing a policy is expensive and a project's policy rarely changes, sq-git has an optimization to only check a policy if it hasn't checked it before. It does this by maintaining a set of policies that it had already seen keyed on the policy's hash. Unfortunately, due to a bug the hash was truncated to be 0 bytes and thus only hard revocations in the target commit were considered. Normally this is not a problem as hard revocations are not removed from the signing policy.

An attacker could nevertheless exploit this flaw as follows. Consider Alice and Bob who maintain a project together. If Bob's certificate is compromised and Bob issues a hard revocation, Alice can add it to the project's signing policy. An attacker who has access to Bob's key can then create a merge request that strips the hard revocation. If Alice merges Bob's merge request, then the latest commit will not carry the hard revocation, and sq-git will not see the hard revocation when authenticating that commit or any following commits.

Note: for this attack to be successful, Alice needs to be tricked into merging the malicious MR. If Alice is reviewing MRs, then she is likely to notice changes to the signing policy.

Reported-by: Hassan Sheet

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "sequoia-git"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-04T22:28:50Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "Before `sq-git` checks if a commit can be authenticated, it first looks for hard revocations.  Because parsing a policy is expensive\nand a project\u0027s policy rarely changes, `sq-git` has an optimization to only check a policy if it hasn\u0027t checked it before.  It does this by maintaining a set of policies that it had already seen keyed on the policy\u0027s hash.  Unfortunately, due to a bug the hash was truncated to be 0 bytes and thus only hard revocations in the target commit were considered.  Normally this is not a problem as hard revocations are not removed from the signing policy.\n\nAn attacker could nevertheless exploit this flaw as follows. Consider Alice and Bob who maintain a project together.  If Bob\u0027s\ncertificate is compromised and Bob issues a hard revocation, Alice can add it to the project\u0027s signing policy.  An attacker who has\naccess to Bob\u0027s key can then create a merge request that strips the hard revocation.  If Alice merges Bob\u0027s merge request, then\nthe latest commit will not carry the hard revocation, and `sq-git` will not see the hard revocation when authenticating that commit or any following commits.\n\nNote: for this attack to be successful, Alice needs to be tricked into merging the malicious MR.  If Alice is reviewing MRs, then she is likely to notice changes to the signing policy.\n\nReported-by: Hassan Sheet",
  "id": "GHSA-g27r-r6ph-vf5r",
  "modified": "2026-05-04T22:28:50Z",
  "published": "2026-05-04T22:28:50Z",
  "references": [
    {
      "type": "PACKAGE",
      "url": "https://gitlab.com/sequoia-pgp/sequoia-git"
    },
    {
      "type": "WEB",
      "url": "https://gitlab.com/sequoia-pgp/sequoia-git/-/commit/f9c9074bd80023456221f09c3c4ff19957ee9c58"
    },
    {
      "type": "WEB",
      "url": "https://rustsec.org/advisories/RUSTSEC-2026-0109.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:H/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "sequoia-git has broken hard revocation handling"
}

GHSA-G7HG-VRCF-MVMR

Vulnerability from github – Published: 2026-07-22 21:46 – Updated: 2026-07-22 21:46
VLAI
Summary
Netty: Out-of-date OCSP Responses Accepted by OcspServerCertificateValidator
Details

Summary

OcspServerCertificateValidator flags an out-of-date OCSP response but does not stop processing it, so an expired GOOD response is still reported as VALID, letting an on-path attacker replay a stale GOOD response to bypass revocation of a since-revoked certificate.

Details

In io.netty.handler.ssl.ocsp.OcspServerCertificateValidator#userEventTriggered the freshness check has no return, so execution falls through and a VALID OcspValidationEvent is still fired:

                        if (!(current.after(response.getThisUpdate()) &&
                                current.before(response.getNextUpdate()))) {
                            ctx.fireExceptionCaught(new IllegalStateException("OCSP Response is out-of-date"));
                        }

Nonce validation is optional and off by default, so freshness is the only replay defense — and it is not enforced. Additionally getNextUpdate() may be null, making current.before(null) throw NullPointerException.

https://datatracker.ietf.org/doc/html/rfc6960#section-3.2

   5. The time at which the status being indicated is known to be
      correct (thisUpdate) is sufficiently recent;

   6. When available, the time at or before which newer information will
      be available about the status of the certificate (nextUpdate) is
      greater than the current time.

PoC

Add the test below to io.netty.handler.ssl.ocsp.OcspServerCertificateValidatorTest

    @Test
    void staleOcspResponseIsRejected() throws Exception {
        X509Bundle caRoot = new CertificateBuilder()
                .algorithm(CertificateBuilder.Algorithm.rsa2048)
                .subject("CN=TrustedRootCA")
                .setIsCertificateAuthority(true)
                .buildSelfSigned();

        GeneralName ocspName = new GeneralName(GeneralName.uniformResourceIdentifier, "http://localhost/");
        AuthorityInformationAccess aia = new AuthorityInformationAccess(
                new AccessDescription(AccessDescription.id_ad_ocsp, ocspName));
        X509Bundle targetCert = new CertificateBuilder()
                .algorithm(CertificateBuilder.Algorithm.rsa2048)
                .subject("CN=TargetServer")
                .addExtensionOctetString("1.3.6.1.5.5.7.1.1", false, aia.getEncoded())
                .buildIssuedBy(caRoot);

        Date past = new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7));
        CertificateID certId = new CertificateID(
                new JcaDigestCalculatorProviderBuilder().build().get(CertificateID.HASH_SHA1),
                new JcaX509CertificateHolder(caRoot.getCertificate()),
                targetCert.getCertificate().getSerialNumber());
        BasicOCSPRespBuilder respBuilder = new BasicOCSPRespBuilder(
                new RespID(new JcaX509CertificateHolder(caRoot.getCertificate()).getSubject()));
        respBuilder.addResponse(certId, CertificateStatus.GOOD, past, past);
        BasicOCSPResp expiredBasicResp = respBuilder.build(
                new JcaContentSignerBuilder("SHA256withRSA").build(caRoot.getKeyPair().getPrivate()),
                new X509CertificateHolder[0],
                past);
        final byte[] responseEncoded = new OCSPRespBuilder()
                .build(OCSPRespBuilder.SUCCESSFUL, expiredBasicResp).getEncoded();

        IoTransport defaultTransport = createDefaultTransport();
        IoTransport mockTransport = IoTransport.create(defaultTransport.eventLoop(), () -> {
                NioSocketChannel channel = new NioSocketChannel();
                channel.pipeline().addFirst(new ChannelOutboundHandlerAdapter() {
                    @Override
                    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
                                        SocketAddress localAddress, ChannelPromise promise) {
                        promise.setSuccess();
                        ctx.executor().execute(() -> {
                            ctx.pipeline().fireChannelActive();
                            DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(
                                    HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                                    Unpooled.wrappedBuffer(responseEncoded));
                            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/ocsp-response");
                            httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH,
                                    httpResponse.content().readableBytes());
                            ctx.pipeline().fireChannelRead(httpResponse);
                        });
                    }
                });
                return channel;
            }, defaultTransport.datagramChannel());

            SslContext serverSslCtx = SslContextBuilder
                    .forServer(targetCert.getKeyPair().getPrivate(),
                            targetCert.getCertificate(), caRoot.getCertificate())
                    .build();
            Channel serverChannel = new ServerBootstrap()
                    .group(defaultTransport.eventLoop())
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(serverSslCtx.newHandler(ch.alloc()));
                        }
                    })
                    .bind(0).sync().channel();

            int serverPort = ((InetSocketAddress) serverChannel.localAddress()).getPort();

            AtomicBoolean validEventFired = new AtomicBoolean();
            AtomicReference<Throwable> caughtException = new AtomicReference<>();
            CountDownLatch latch = new CountDownLatch(1);

            DnsNameResolver resolver = OcspServerCertificateValidator.createDefaultResolver(mockTransport);
            SslContext clientSslCtx = SslContextBuilder.forClient()
                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
                    .build();
            new Bootstrap()
                    .group(defaultTransport.eventLoop())
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(clientSslCtx.newHandler(ch.alloc(), "127.0.0.1", serverPort));
                            ch.pipeline().addLast(
                                    new OcspServerCertificateValidator(true, false, mockTransport, resolver));
                            ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
                                    if (evt instanceof OcspValidationEvent &&
                                            ((OcspValidationEvent) evt).response().status() ==
                                                    OcspResponse.Status.VALID) {
                                        validEventFired.set(true);
                                    }
                                    ctx.fireUserEventTriggered(evt);
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                                    caughtException.compareAndSet(null, cause);
                                    ctx.channel().close();
                                    latch.countDown();
                                }
                            });
                        }
                    })
                    .connect("127.0.0.1", serverPort).sync();

            assertTrue(latch.await(5, TimeUnit.SECONDS));
            assertFalse(validEventFired.get(),
                    "OcspValidationEvent(VALID) must not be emitted for a stale OCSP response");
            assertNotNull(caughtException.get());
            assertInstanceOf(IllegalStateException.class, caughtException.get());

            serverChannel.close().sync();
            resolver.close();
    }

Impact

Certificate revocation bypass via replay of an expired OCSP response. Any application using OcspServerCertificateValidator is affected; a revoked certificate can be accepted.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-handler-ssl-ocsp"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.2.0.Final"
            },
            {
              "fixed": "4.2.16.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Maven",
        "name": "io.netty:netty-handler-ssl-ocsp"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.1.136.Final"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-56821"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-299"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-22T21:46:39Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n`OcspServerCertificateValidator` flags an out-of-date OCSP response but does not stop processing it, so an expired GOOD response is still reported as `VALID`, letting an on-path attacker replay a stale GOOD response to bypass revocation of a since-revoked certificate.\n\n### Details\nIn `io.netty.handler.ssl.ocsp.OcspServerCertificateValidator#userEventTriggered` the freshness check has no `return`, so execution falls through and a `VALID` `OcspValidationEvent` is still fired:\n\n```java\n                        if (!(current.after(response.getThisUpdate()) \u0026\u0026\n                                current.before(response.getNextUpdate()))) {\n                            ctx.fireExceptionCaught(new IllegalStateException(\"OCSP Response is out-of-date\"));\n                        }\n```\n\nNonce validation is optional and off by default, so freshness is the only replay defense \u2014 and it is not enforced. Additionally `getNextUpdate()` may be `null`, making `current.before(null)` throw `NullPointerException`.\n\nhttps://datatracker.ietf.org/doc/html/rfc6960#section-3.2\n\n```\n   5. The time at which the status being indicated is known to be\n      correct (thisUpdate) is sufficiently recent;\n\n   6. When available, the time at or before which newer information will\n      be available about the status of the certificate (nextUpdate) is\n      greater than the current time.\n```\n\n### PoC\n\nAdd the test below to `io.netty.handler.ssl.ocsp.OcspServerCertificateValidatorTest`\n\n```java\n    @Test\n    void staleOcspResponseIsRejected() throws Exception {\n        X509Bundle caRoot = new CertificateBuilder()\n                .algorithm(CertificateBuilder.Algorithm.rsa2048)\n                .subject(\"CN=TrustedRootCA\")\n                .setIsCertificateAuthority(true)\n                .buildSelfSigned();\n\n        GeneralName ocspName = new GeneralName(GeneralName.uniformResourceIdentifier, \"http://localhost/\");\n        AuthorityInformationAccess aia = new AuthorityInformationAccess(\n                new AccessDescription(AccessDescription.id_ad_ocsp, ocspName));\n        X509Bundle targetCert = new CertificateBuilder()\n                .algorithm(CertificateBuilder.Algorithm.rsa2048)\n                .subject(\"CN=TargetServer\")\n                .addExtensionOctetString(\"1.3.6.1.5.5.7.1.1\", false, aia.getEncoded())\n                .buildIssuedBy(caRoot);\n\n        Date past = new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7));\n        CertificateID certId = new CertificateID(\n                new JcaDigestCalculatorProviderBuilder().build().get(CertificateID.HASH_SHA1),\n                new JcaX509CertificateHolder(caRoot.getCertificate()),\n                targetCert.getCertificate().getSerialNumber());\n        BasicOCSPRespBuilder respBuilder = new BasicOCSPRespBuilder(\n                new RespID(new JcaX509CertificateHolder(caRoot.getCertificate()).getSubject()));\n        respBuilder.addResponse(certId, CertificateStatus.GOOD, past, past);\n        BasicOCSPResp expiredBasicResp = respBuilder.build(\n                new JcaContentSignerBuilder(\"SHA256withRSA\").build(caRoot.getKeyPair().getPrivate()),\n                new X509CertificateHolder[0],\n                past);\n        final byte[] responseEncoded = new OCSPRespBuilder()\n                .build(OCSPRespBuilder.SUCCESSFUL, expiredBasicResp).getEncoded();\n\n        IoTransport defaultTransport = createDefaultTransport();\n        IoTransport mockTransport = IoTransport.create(defaultTransport.eventLoop(), () -\u003e {\n                NioSocketChannel channel = new NioSocketChannel();\n                channel.pipeline().addFirst(new ChannelOutboundHandlerAdapter() {\n                    @Override\n                    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,\n                                        SocketAddress localAddress, ChannelPromise promise) {\n                        promise.setSuccess();\n                        ctx.executor().execute(() -\u003e {\n                            ctx.pipeline().fireChannelActive();\n                            DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(\n                                    HttpVersion.HTTP_1_1, HttpResponseStatus.OK,\n                                    Unpooled.wrappedBuffer(responseEncoded));\n                            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, \"application/ocsp-response\");\n                            httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH,\n                                    httpResponse.content().readableBytes());\n                            ctx.pipeline().fireChannelRead(httpResponse);\n                        });\n                    }\n                });\n                return channel;\n            }, defaultTransport.datagramChannel());\n\n            SslContext serverSslCtx = SslContextBuilder\n                    .forServer(targetCert.getKeyPair().getPrivate(),\n                            targetCert.getCertificate(), caRoot.getCertificate())\n                    .build();\n            Channel serverChannel = new ServerBootstrap()\n                    .group(defaultTransport.eventLoop())\n                    .channel(NioServerSocketChannel.class)\n                    .childHandler(new ChannelInitializer\u003cSocketChannel\u003e() {\n                        @Override\n                        protected void initChannel(SocketChannel ch) {\n                            ch.pipeline().addLast(serverSslCtx.newHandler(ch.alloc()));\n                        }\n                    })\n                    .bind(0).sync().channel();\n\n            int serverPort = ((InetSocketAddress) serverChannel.localAddress()).getPort();\n\n            AtomicBoolean validEventFired = new AtomicBoolean();\n            AtomicReference\u003cThrowable\u003e caughtException = new AtomicReference\u003c\u003e();\n            CountDownLatch latch = new CountDownLatch(1);\n\n            DnsNameResolver resolver = OcspServerCertificateValidator.createDefaultResolver(mockTransport);\n            SslContext clientSslCtx = SslContextBuilder.forClient()\n                    .trustManager(InsecureTrustManagerFactory.INSTANCE)\n                    .build();\n            new Bootstrap()\n                    .group(defaultTransport.eventLoop())\n                    .channel(NioSocketChannel.class)\n                    .handler(new ChannelInitializer\u003cSocketChannel\u003e() {\n                        @Override\n                        protected void initChannel(SocketChannel ch) {\n                            ch.pipeline().addLast(clientSslCtx.newHandler(ch.alloc(), \"127.0.0.1\", serverPort));\n                            ch.pipeline().addLast(\n                                    new OcspServerCertificateValidator(true, false, mockTransport, resolver));\n                            ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {\n                                @Override\n                                public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {\n                                    if (evt instanceof OcspValidationEvent \u0026\u0026\n                                            ((OcspValidationEvent) evt).response().status() ==\n                                                    OcspResponse.Status.VALID) {\n                                        validEventFired.set(true);\n                                    }\n                                    ctx.fireUserEventTriggered(evt);\n                                }\n\n                                @Override\n                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {\n                                    caughtException.compareAndSet(null, cause);\n                                    ctx.channel().close();\n                                    latch.countDown();\n                                }\n                            });\n                        }\n                    })\n                    .connect(\"127.0.0.1\", serverPort).sync();\n\n            assertTrue(latch.await(5, TimeUnit.SECONDS));\n            assertFalse(validEventFired.get(),\n                    \"OcspValidationEvent(VALID) must not be emitted for a stale OCSP response\");\n            assertNotNull(caughtException.get());\n            assertInstanceOf(IllegalStateException.class, caughtException.get());\n\n            serverChannel.close().sync();\n            resolver.close();\n    }\n```\n### Impact\nCertificate revocation bypass via replay of an expired OCSP response. Any application using `OcspServerCertificateValidator` is affected; a revoked certificate can be accepted.",
  "id": "GHSA-g7hg-vrcf-mvmr",
  "modified": "2026-07-22T21:46:39Z",
  "published": "2026-07-22T21:46:39Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/security/advisories/GHSA-g7hg-vrcf-mvmr"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/netty/netty"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/releases/tag/netty-4.1.136.Final"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netty/netty/releases/tag/netty-4.2.16.Final"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Netty: Out-of-date OCSP Responses Accepted by OcspServerCertificateValidator"
}

Mitigation
Architecture and Design

Ensure that certificates are checked for revoked status.

Mitigation
Implementation

If certificate pinning is being used, ensure that all relevant properties of the certificate are fully validated before the certificate is pinned, including the revoked status.

No CAPEC attack patterns related to this CWE.