Safeguard
Vulnerability Analysis

CVE-2023-49083: NULL pointer dereference in python-crypto...

A NULL pointer dereference in python-cryptography's PKCS7 loader (CVE-2023-49083) lets malformed input crash applications. Here's what to patch and why.

Vikram Iyer
Security Researcher
6 min read

Lede

CVE-2023-49083 is a NULL pointer dereference vulnerability in pyca/cryptography, the widely used Python cryptography library that underpins TLS, certificate handling, and cryptographic primitives across the Python ecosystem. The flaw lives in the library's PKCS7 parsing code: calling load_pem_pkcs7_certificates() or load_der_pkcs7_certificates() on a PKCS7 structure that contains no certificates triggers a NULL pointer dereference in the underlying OpenSSL binding layer, crashing the Python process with a segmentation fault.

The impact is denial of service, not remote code execution or data disclosure. Any application that accepts untrusted PKCS7 blobs — for example, services validating S/MIME messages, Authenticode-style signatures, or certificate bundles delivered over an API — can be crashed by an attacker who supplies a malformed but structurally valid PKCS7 payload with an empty certificate set. Because cryptography sits underneath a long chain of popular packages (PyOpenSSL, Paramiko, requests via urllib3/PyOpenSSL bindings, Ansible, boto3 in some configurations, and many more), the practical exposure is broader than the narrow PKCS7 code path suggests: any environment that pulls in a vulnerable cryptography version and exposes PKCS7 parsing to attacker-controlled input inherits the risk.

Affected versions and components

  • Component: cryptography PyPI package (pyca/cryptography), specifically cryptography.hazmat.primitives.serialization.pkcs7
  • Vulnerable functions: load_pem_pkcs7_certificates() and load_der_pkcs7_certificates()
  • Root cause: insufficient validation before dereferencing a certificate pointer returned from the underlying OpenSSL call when the parsed PKCS7 structure contains zero certificates
  • Fixed version: cryptography 41.0.6 and later

Because cryptography is a transitive dependency for a large share of the Python packaging ecosystem, the practical set of affected environments extends well past applications that call the PKCS7 APIs directly. Container images, virtual environments, and lockfiles that pin cryptography below 41.0.6 are vulnerable if any code path — application code or a dependency — feeds untrusted PKCS7 data into the affected functions. Teams should treat this as a dependency-freshness issue first, then confirm whether their own code (or a library they depend on) actually invokes the PKCS7 loaders on external input.

CVSS, EPSS, and KEV context

Public advisories for this issue (tracked upstream as GHSA-3ww4-gg4f-jr7f) score the vulnerability in the medium range under CVSS v3.1, reflecting a network-exploitable, low-complexity, no-privileges-required condition whose only impact is availability — there is no confidentiality or integrity loss, since the bug crashes the process rather than corrupting memory in an exploitable way. That severity profile is consistent with a classic "malformed input causes a crash" bug: trivial to trigger once you can reach the parsing function, but limited in blast radius to a restart/recovery event rather than data compromise.

We aren't going to guess at a specific EPSS percentile here, but the shape of the bug is informative: DoS-only crash conditions in a library function that isn't universally invoked (most applications never call the PKCS7 loaders at all) typically see modest real-world exploitation interest compared to bugs offering code execution or data exfiltration. As of this writing, CVE-2023-49083 does not appear in CISA's Known Exploited Vulnerabilities (KEV) catalog, meaning there's no confirmed evidence of in-the-wild exploitation driving an active-use designation. That said, absence from KEV is not a reason to deprioritize the fix — DoS bugs in shared crypto libraries are cheap to exploit once an attacker identifies which of your services actually parses PKCS7 input, and availability incidents carry real operational cost.

Timeline

  • Disclosure: The issue was identified and reported to the pyca/cryptography maintainers through the project's standard security disclosure process, resulting in GitHub Security Advisory GHSA-3ww4-gg4f-jr7f.
  • Fix released: The maintainers shipped a fix in cryptography 41.0.6, adding a check for empty certificate sets in the PKCS7 loading path before the code reaches the vulnerable dereference.
  • CVE assignment: CVE-2023-49083 was assigned and published to track the issue in the CVE and NVD databases, aligned with the 41.0.6 release in late 2023.

As with most memory-safety-adjacent bugs in widely embedded libraries, the gap that matters most isn't the time between disclosure and patch — it's the time between patch availability and adoption across the dependency graphs of every application, container image, and CI pipeline that pulls in cryptography, directly or transitively.

Remediation steps

  1. Upgrade cryptography to 41.0.6 or later. This is the definitive fix. Check pip show cryptography or your lockfile (requirements.txt, Pipfile.lock, poetry.lock, uv.lock) to confirm the resolved version.
  2. Check transitive pins. cryptography is frequently vendored or pinned by intermediate dependencies such as PyOpenSSL, Paramiko, pyjwt[crypto], and various cloud SDKs. Run pip list --outdated or a full dependency tree resolution (pipdeptree, pip-compile) to confirm no transitive dependency is forcing an older, vulnerable version.
  3. Rebuild and redeploy artifacts. Container images and packaged binaries (PyInstaller, Docker) built before the fix was available will still carry the vulnerable wheel baked in. Bumping the requirement file alone doesn't help until images are rebuilt and redeployed.
  4. Audit code paths that call the PKCS7 loaders. If your application or a dependency calls load_pem_pkcs7_certificates() / load_der_pkcs7_certificates() on data from an external source (uploaded files, API payloads, email attachments, signed manifests), confirm those call sites are wrapped with appropriate error handling and, ideally, run in a process boundary that can restart cleanly rather than taking down a shared service.
  5. Add a regression test. A minimal test that feeds a PKCS7 structure with an empty certificate set through the loader (post-upgrade, expecting a clean exception rather than a crash) helps catch any accidental downgrade in the future.
  6. Re-scan and refresh SBOMs. After upgrading, regenerate software bills of materials for affected services so vulnerability trackers and compliance evidence reflect the current, patched dependency state.

How Safeguard Helps

CVE-2023-49083 is a good illustration of why software supply chain visibility can't stop at "what's in my requirements.txt." The vulnerable code lives several layers deep in a dependency graph that most engineering teams don't manually audit — cryptography is pulled in transitively by dozens of common packages, and knowing whether a given service is actually exposed requires both dependency visibility and an understanding of how that dependency is used.

Safeguard's software supply chain security platform is built for exactly this gap:

  • Continuous SBOM generation and monitoring across repositories and build artifacts, so when a CVE like this is disclosed, you can immediately identify every service, container image, and package that resolves to a vulnerable cryptography version — including transitive dependencies pulled in through PyOpenSSL, Paramiko, or other intermediaries.
  • Real-time vulnerability intelligence that maps newly disclosed CVEs against your existing SBOM inventory, surfacing affected components before they're weaponized rather than after an incident.
  • Policy-based CI/CD gating that can block builds or merges introducing (or failing to remediate) known-vulnerable dependency versions, turning "upgrade to 41.0.6" from a manual chase into an enforced pipeline check.
  • Provenance and build integrity verification, giving teams confidence that the patched version deployed in production actually matches what was built and tested, closing the gap between "we bumped the requirement" and "the fix is actually running."

For vulnerabilities like CVE-2023-49083 — narrow in exploit mechanics but broad in dependency reach — the difference between a quick, contained remediation and a scramble across dozens of services usually comes down to whether you had accurate, up-to-date visibility into your software supply chain before the advisory dropped. That's the problem Safeguard is built to solve.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.