diff --git a/.github/actions/fetch_ctk/action.yml b/.github/actions/fetch_ctk/action.yml index 5391c1f75ac..46d4296c429 100644 --- a/.github/actions/fetch_ctk/action.yml +++ b/.github/actions/fetch_ctk/action.yml @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -76,19 +76,22 @@ runs: mkdir $CACHE_TMP_DIR # The binary archives (redist) are guaranteed to be updated as part of the release posting. + # Use the runtime workspace mount so this also works inside container jobs. + CTK_REDIST_TOOL="${GITHUB_WORKSPACE}/ci/tools/fetch_ctk_redistrib.py" CTK_BASE_URL="https://developer.download.nvidia.com/compute/cuda/redist/" CTK_JSON_URL="$CTK_BASE_URL/redistrib_${{ inputs.cuda-version }}.json" + CTK_JSON_FILE="$CACHE_TMP_DIR/redistrib.json" + curl -LSs "$CTK_JSON_URL" -o "$CTK_JSON_FILE" + # Pin the metadata JSON: the per-archive sha256 checks below are only + # trustworthy if the JSON that carries those hashes is itself trusted. + python "$CTK_REDIST_TOOL" verify-metadata \ + --cuda-version "${{ inputs.cuda-version }}" \ + --metadata-path "$CTK_JSON_FILE" if [[ "${{ inputs.host-platform }}" == linux* ]]; then - if [[ "${{ inputs.host-platform }}" == "linux-64" ]]; then - CTK_SUBDIR="linux-x86_64" - elif [[ "${{ inputs.host-platform }}" == "linux-aarch64" ]]; then - CTK_SUBDIR="linux-sbsa" - fi function extract() { tar -xvf $1 -C $CACHE_TMP_DIR --strip-components=1 } elif [[ "${{ inputs.host-platform }}" == "win-64" ]]; then - CTK_SUBDIR="windows-x86_64" function extract() { _TEMP_DIR_=$(mktemp -d) unzip $1 -d $_TEMP_DIR_ @@ -101,14 +104,23 @@ runs: function populate_cuda_path() { # take the component name as a argument function download() { - curl -kLSs $1 -o $2 + curl -LSs $1 -o $2 } CTK_COMPONENT=$1 - CTK_COMPONENT_REL_PATH="$(curl -s $CTK_JSON_URL | - python -c "import sys, json; print(json.load(sys.stdin)['${CTK_COMPONENT}']['${CTK_SUBDIR}']['relative_path'])")" + CTK_COMPONENT_REL_PATH="$(python "$CTK_REDIST_TOOL" component-relative-path \ + --host-platform "${{ inputs.host-platform }}" \ + --component "$CTK_COMPONENT" \ + --metadata-path "$CTK_JSON_FILE")" CTK_COMPONENT_URL="${CTK_BASE_URL}/${CTK_COMPONENT_REL_PATH}" CTK_COMPONENT_COMPONENT_FILENAME="$(basename $CTK_COMPONENT_REL_PATH)" download $CTK_COMPONENT_URL $CTK_COMPONENT_COMPONENT_FILENAME + # Verify the downloaded archive against the sha256 in the (pinned) + # metadata before extracting; fail closed on any mismatch. + CTK_COMPONENT_SHA256="$(python "$CTK_REDIST_TOOL" component-sha256 \ + --host-platform "${{ inputs.host-platform }}" \ + --component "$CTK_COMPONENT" \ + --metadata-path "$CTK_JSON_FILE")" + echo "${CTK_COMPONENT_SHA256} ${CTK_COMPONENT_COMPONENT_FILENAME}" | sha256sum --check --strict - extract $CTK_COMPONENT_COMPONENT_FILENAME rm $CTK_COMPONENT_COMPONENT_FILENAME } diff --git a/.github/actions/harden-pip/action.yml b/.github/actions/harden-pip/action.yml deleted file mode 100644 index 868c30295f5..00000000000 --- a/.github/actions/harden-pip/action.yml +++ /dev/null @@ -1,28 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 - -name: Harden pip -description: >- - Install the security-fixed pip (26.2.2) from a hash-pinned wheel so that later - pip invocations do not fall back on the vendored certifi bundle that trusts the - compromised eMudhra/emSign intermediate CAs. The sha256 fragment guarantees the - bootstrap download's integrity even if the bootstrapping pip's trust store is - compromised. See https://github.com/NVIDIA/cuda-python/issues/3195 and - https://discuss.python.org/t/109576. - -inputs: - python: - description: Python interpreter whose pip should be hardened (e.g. a venv's python). - default: python - -runs: - using: composite - steps: - - name: Install hash-pinned pip 26.2.2 - shell: bash --noprofile --norc -xeuo pipefail {0} - env: - HARDEN_PIP_PYTHON: ${{ inputs.python }} - run: | - "${HARDEN_PIP_PYTHON}" -m pip install \ - "pip @ https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl#sha256=fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70" diff --git a/.github/actions/setup-hardened-python/action.yml b/.github/actions/setup-hardened-python/action.yml new file mode 100644 index 00000000000..a3ff530641e --- /dev/null +++ b/.github/actions/setup-hardened-python/action.yml @@ -0,0 +1,150 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +name: Set up hardened Python +description: >- + Install CPython with a pinned uv, create a venv from it, and put the venv + first on PATH. setup-uv verifies the uv binary and uv verifies the + python-build-standalone archive against embedded checksums, so the + interpreter's integrity does not depend on TLS. The job then fails unless + the interpreter's ssl module rejects the compromised eMudhra/emSign CA keys + (CVE-2026-115557; first fixed releases: 3.11.18, 3.12.16, 3.13.18, 3.14.10, + 3.15.2), and pip is updated through that ssl module. Unlike setup-python, + this provides patched Windows builds of maintenance series, for which + python.org publishes no installers. Series that have no fixed release + (3.10 and older, which this branch still builds and tests) are installed + with a warning instead, and their pip is replaced by a sha256-pinned + wheel, so that the pip update does not depend on TLS. See + https://github.com/NVIDIA/cuda-python/issues/3195 and + https://discuss.python.org/t/109678. + +inputs: + python-version: + description: >- + uv Python request, e.g. "3.12" or "3.14t" (free-threaded). The newest + patch known to the pinned uv is installed. Series with a fixed release + listed in the interpreter check (3.11-3.15) must carry it. Series + without a fixed release (3.10 and older) are accepted with a warning, + and pip is installed from a sha256-pinned wheel. + required: true + venv: + description: Directory for the venv. Defaults to a new directory under RUNNER_TEMP. + default: "" + +outputs: + python-path: + description: Absolute path of the venv's interpreter. + value: ${{ steps.venv.outputs.python-path }} + python-version: + description: Full version of the interpreter, e.g. "3.14.10". + value: ${{ steps.venv.outputs.python-version }} + +runs: + using: composite + steps: + - name: Install uv + uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3 + with: + # The newest uv whose checksum ships inside the pinned setup-uv, so + # the binary is verified against the SHA-pinned action itself. The uv + # release determines the newest patch of each CPython series, so + # bumping the setup-uv SHA also moves the CPython patch versions. + version: "latest-known" + enable-cache: false + # Some callers (e.g. release verification) have no checkout. + ignore-empty-workdir: true + + - name: Install Python and create venv + id: venv + shell: bash --noprofile --norc -euo pipefail {0} + env: + PY_REQUEST: ${{ inputs.python-version }} + VENV_DIR: ${{ inputs.venv }} + # A per-job install directory ensures the newest patch known to the + # pinned uv is used, never an older interpreter left on a persistent + # self-hosted runner. + UV_PYTHON_INSTALL_DIR: ${{ runner.temp }}/setup-hardened-python/interpreters + UV_NO_CONFIG: "1" + run: | + uv python install --no-bin --no-registry "${PY_REQUEST}" + base="$(uv python find --managed-python --no-project "${PY_REQUEST}")" + venv="${VENV_DIR}" + if [[ -z "${venv}" ]]; then + # A fresh directory per call, so a second call in the same job + # (e.g. build-wheel.yml) leaves the first venv intact. + venv="$("${base}" -c 'import sys, tempfile; print(tempfile.mkdtemp(prefix="venv-", dir=sys.argv[1]))' "${RUNNER_TEMP}")" + fi + # The stdlib venv seeds pip from the interpreter's bundled wheel, so + # nothing is downloaded before the ssl check below. + "${base}" -m venv --clear "${venv}" + if [[ "${RUNNER_OS}" == Windows ]]; then + py="${venv}/Scripts/python.exe" + else + py="${venv}/bin/python" + fi + # Let the interpreter report native absolute paths (Windows included). + python_path="$("${py}" -c 'import sys; print(sys.executable)')" + "${py}" -c 'import os, sys; print(os.path.dirname(sys.executable))' >> "${GITHUB_PATH}" + { + echo "python-path=${python_path}" + echo "python-version=$("${py}" -c 'import platform; print(platform.python_version())')" + } >> "${GITHUB_OUTPUT}" + + - name: Check Python interpreter is patched (CVE-2026-115557) + id: check + # Runs the venv's python through the PATH entry added above. + shell: python {0} + env: + PYTHON: ${{ steps.venv.outputs.python-path }} + run: | + import os + import platform + import sys + + if os.path.normcase(sys.executable) != os.path.normcase(os.environ["PYTHON"]): + print(f"::error::PATH resolves python to {sys.executable}, not the venv interpreter {os.environ['PYTHON']}.") + sys.exit(1) + + FIXED = {(3, 11): 18, (3, 12): 16, (3, 13): 18, (3, 14): 10, (3, 15): 2} + # Series that will never get a fixed release (end of life before the + # fix). Their pip is installed from a pinned wheel instead. + UNPATCHABLE_BELOW = (3, 11) + ssl_patched = "true" + v = sys.version_info + series = (v.major, v.minor) + name = f"{v.major}.{v.minor}" + full = platform.python_version() + print("sys.version:", sys.version) + if series in FIXED: + floor = f"{name}.{FIXED[series]}" + if v.micro < FIXED[series]: + print(f"::error::Python {full} is older than {floor}, the first {name} release whose ssl module rejects the compromised eMudhra CA keys (CVE-2026-115557).") + sys.exit(1) + print(f"Python {full}: ssl module carries the fix (first fixed: {floor}).") + elif series < UNPATCHABLE_BELOW: + ssl_patched = "false" + print(f"::warning::Python {full}: no {name} release rejects the compromised eMudhra CA keys (CVE-2026-115557); pip will be installed from a sha256-pinned wheel instead.") + else: + # Fail closed: a newer series is only accepted once its fixed release is listed. + print(f"::error::Python {full}: no {name} release is known to reject the compromised eMudhra CA keys (CVE-2026-115557).") + sys.exit(1) + + with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f: + f.write(f"ssl-patched={ssl_patched}\n") + + - name: Update pip + shell: bash --noprofile --norc -xeuo pipefail {0} + env: + PYTHON: ${{ steps.venv.outputs.python-path }} + SSL_PATCHED: ${{ steps.check.outputs.ssl-patched }} + run: | + if [[ "${SSL_PATCHED}" == "true" ]]; then + "${PYTHON}" -m pip install -U pip + else + # The interpreter's ssl module still trusts the compromised CA keys, + # so do not fetch pip through it. The sha256 fragment guarantees the + # wheel's integrity regardless of the transport. + "${PYTHON}" -m pip install \ + "pip @ https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl#sha256=fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70" + fi diff --git a/.github/actions/upgrade-ca-certificates/action.yml b/.github/actions/upgrade-ca-certificates/action.yml new file mode 100644 index 00000000000..0a8747bbce4 --- /dev/null +++ b/.github/actions/upgrade-ca-certificates/action.yml @@ -0,0 +1,144 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Temporary stopgap for the eMudhra/emSign CA key compromise (CVE-2026-111943) +# on GitHub-hosted runners until GitHub ships fixed images. +# +# On Linux: upgrades ca-certificates via apt so the compromised emSign ECC Root +# CA - G3 anchor is removed from /etc/ssl/certs/ca-certificates.crt. Ubuntu's +# bundle does not include AAA Certificate Services, so the Sectigo cross-signs +# do not chain to a trusted root there. +# On Windows: adds the eight compromised intermediates and their eight Sectigo +# cross-signs (impacted-intermediates.json) to Cert:\LocalMachine\Disallowed so +# schannel-based clients (git, gh, PowerShell/.NET) reject chains through them, +# including chains to AAA Certificate Services, which Windows still trusts. +# +# This action is a no-op on self-hosted runners (runner.environment != 'github-hosted') +# because self-hosted runner operators own and update their own host images. +# +# Removal criteria and implementation notes: security/emudhra-plan2.md +# Tracked by: actions/runner-images#15018 + +name: Harden OS certificate trust (eMudhra/emSign CA stopgap) +description: > + Temporary per-job stopgap for CVE-2026-111943. Upgrades ca-certificates on + GitHub-hosted Linux runners and adds the compromised eMudhra intermediates + and cross-signs to the Disallowed store on GitHub-hosted Windows runners. + No-op on self-hosted. + +runs: + using: composite + steps: + + # ------------------------------------------------------------------------- + # Windows path: add the compromised intermediates to LocalMachine\Disallowed. + # Takes effect immediately for all schannel-based clients in subsequent steps + # (git, gh, PowerShell/.NET, WinHTTP). Must precede actions/checkout. + # ------------------------------------------------------------------------- + - name: Distrust compromised eMudhra intermediates (Windows, GitHub-hosted) + if: ${{ runner.os == 'Windows' && runner.environment == 'github-hosted' }} + shell: pwsh + env: + ACTION_PATH: ${{ github.action_path }} + run: | + $ErrorActionPreference = 'Stop' + . (Join-Path $env:ACTION_PATH 'emudhra_intermediates.ps1') + + $certs = @(Get-EmudhraIntermediates) + try { + # Adding is idempotent, so no early exit when the image is already fixed. + $store = [System.Security.Cryptography.X509Certificates.X509Store]::new('Disallowed', 'LocalMachine') + $store.Open('ReadWrite') + try { + foreach ($cert in $certs) { $store.Add($cert) } + } finally { + $store.Close() + } + + $notDistrusted = @($certs | Where-Object { -not (Test-ExplicitlyDistrusted $_) } | ForEach-Object { $_.EmudhraLabel }) + if ($notDistrusted.Count -gt 0) { + Write-Error "Not explicitly distrusted after adding to LocalMachine\Disallowed: $($notDistrusted -join '; ')" + exit 1 + } + Write-Host "Distrusted $($certs.Count) compromised eMudhra intermediates and cross-signs." + } finally { + $certs | ForEach-Object { $_.Dispose() } + } + + # ------------------------------------------------------------------------- + # Linux path: upgrade ca-certificates via apt. + # The Ubuntu archive GPG check does not depend on the trust store being + # fixed, so this bootstrap is safe. Retries guard against transient mirror + # failures. Must precede actions/checkout. + # ------------------------------------------------------------------------- + - name: Upgrade ca-certificates (Linux, GitHub-hosted) + if: ${{ runner.os == 'Linux' && runner.environment == 'github-hosted' }} + shell: bash + run: | + set -euo pipefail + EMSIGN_G3_FP="86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B" + CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" + VERSION_ID="$(. /etc/os-release && echo "${VERSION_ID}")" + + # Fail closed if openssl is missing or the bundle cannot be parsed + # (mirrors ci/tools/runner_trust_probe.sh). + if ! command -v openssl >/dev/null 2>&1; then + echo "::error::openssl not found; cannot verify CA bundle" + exit 1 + fi + if [[ ! -f "${CA_BUNDLE}" ]]; then + echo "::error::CA bundle not found: ${CA_BUNDLE}" + exit 1 + fi + + fingerprints_in_bundle() { + awk '/-----BEGIN CERTIFICATE-----/{cert=""} {cert=cert $0 "\n"} + /-----END CERTIFICATE-----/{print cert | "openssl x509 -noout -fingerprint -sha256 2>/dev/null"; close("openssl x509 -noout -fingerprint -sha256 2>/dev/null")}' \ + "${CA_BUNDLE}" + } + + fps="$(fingerprints_in_bundle)" + cert_count="$(grep -c . <<< "${fps}" || true)" + if (( cert_count == 0 )); then + echo "::error::No certificates parsed from ${CA_BUNDLE}; openssl may have failed" + exit 1 + fi + + if grep -qiF "${EMSIGN_G3_FP}" <<< "${fps}"; then + before_state="not fixed" + else + before_state="already fixed" + fi + before_ver="$(dpkg-query -W -f='${Version}' ca-certificates 2>/dev/null || echo unknown)" + echo "::notice::emSign ECC Root CA - G3 on ${VERSION_ID}: ${before_state} (ca-certificates ${before_ver})" + + if [ "${before_state}" = "already fixed" ]; then + exit 0 + fi + + for attempt in 1 2 3; do + if sudo apt-get update -q && sudo apt-get install --only-upgrade -y ca-certificates; then + break + fi + if [ "${attempt}" -lt 3 ]; then + echo "apt-get attempt ${attempt} failed; retrying in 10s..." + sleep 10 + else + echo "::error::apt-get upgrade failed after ${attempt} attempts" + exit 1 + fi + done + + after_ver="$(dpkg-query -W -f='${Version}' ca-certificates 2>/dev/null || echo unknown)" + after_fps="$(fingerprints_in_bundle)" + after_count="$(grep -c . <<< "${after_fps}" || true)" + if (( after_count == 0 )); then + echo "::error::No certificates parsed after upgrade; cannot verify fix" + exit 1 + fi + if grep -qiF "${EMSIGN_G3_FP}" <<< "${after_fps}"; then + echo "::error::emSign ECC Root CA - G3 still present after upgrade (ca-certificates ${after_ver} on ${VERSION_ID})" + exit 1 + fi + echo "ca-certificates upgraded to ${after_ver}; emSign ECC Root CA - G3 absent." diff --git a/.github/actions/upgrade-ca-certificates/emudhra_intermediates.ps1 b/.github/actions/upgrade-ca-certificates/emudhra_intermediates.ps1 new file mode 100644 index 00000000000..0324c5df448 --- /dev/null +++ b/.github/actions/upgrade-ca-certificates/emudhra_intermediates.ps1 @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Helpers for the compromised eMudhra intermediates and their Sectigo +# cross-signs listed in impacted-intermediates.json. Dot-sourced by this +# action's Windows step and by ci/tools/runner_trust_probe.ps1. +# +# impacted-intermediates.json is the disclosure's file, unmodified (SHA-256 +# f67b3abe9b4879f4e91874ed041beccd71257f1db41c588c724ccf12aa90c59e). The set +# is closed: new certificates for these keys would have to be issued by +# another CA, and all existing ones are revoked. + +$EmudhraIntermediatesPath = Join-Path $PSScriptRoot 'impacted-intermediates.json' +$EmudhraIntermediatesCount = 16 + +# Returns the certificates as X509Certificate2 objects; callers dispose them. +function Get-EmudhraIntermediates { + $entries = @(Get-Content -LiteralPath $EmudhraIntermediatesPath -Raw | ConvertFrom-Json) + if ($entries.Count -ne $EmudhraIntermediatesCount) { + throw "Expected $EmudhraIntermediatesCount certificates in $EmudhraIntermediatesPath, found $($entries.Count)." + } + foreach ($entry in $entries) { + $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::CreateFromPem($entry.pem) + if ($cert.GetCertHashString('SHA256') -ne $entry.sha256.ToUpperInvariant()) { + $cert.Dispose() + throw "SHA-256 mismatch for $($entry.name) (issued by $($entry.issued_by))." + } + Add-Member -InputObject $cert -NotePropertyName EmudhraLabel -NotePropertyValue "$($entry.name) (issued by $($entry.issued_by))" + $cert + } +} + +# True if Windows chain building reports the certificate as explicitly +# distrusted. This covers both a local LocalMachine\Disallowed entry and +# Microsoft's automatically updated disallowed list. Revocation checking and +# AIA downloads are off so the result reflects the local trust state only. +function Test-ExplicitlyDistrusted([System.Security.Cryptography.X509Certificates.X509Certificate2]$Cert) { + $explicitDistrust = [System.Security.Cryptography.X509Certificates.X509ChainStatusFlags]::ExplicitDistrust + $chain = [System.Security.Cryptography.X509Certificates.X509Chain]::new() + try { + $chain.ChainPolicy.RevocationMode = [System.Security.Cryptography.X509Certificates.X509RevocationMode]::NoCheck + $chain.ChainPolicy.DisableCertificateDownloads = $true + [void]$chain.Build($Cert) + $statuses = @($chain.ChainStatus) + @($chain.ChainElements | ForEach-Object { $_.ChainElementStatus }) + return [bool]($statuses | Where-Object { $_.Status.HasFlag($explicitDistrust) }) + } finally { + $chain.Dispose() + } +} diff --git a/.github/actions/upgrade-ca-certificates/impacted-intermediates.json b/.github/actions/upgrade-ca-certificates/impacted-intermediates.json new file mode 100644 index 00000000000..034fe6e7b4c --- /dev/null +++ b/.github/actions/upgrade-ca-certificates/impacted-intermediates.json @@ -0,0 +1,466 @@ +[ + { + "name": "EM DV TLS CA - G3B", + "usage": "tls", + "issued_by": "emSign Root TLS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "subject": "CN=EM DV TLS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=emSign Root TLS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "A4AEE678F23362B4C0E460B772F214", + "sha256": "42C4ACCD12C4F59597925E1A08A7A90102608543809308D50EC427E118BA1493", + "spki_sha256": "EBED6475C2C2D80FCB199F3FE8DD6E6B3CE60B77EB15D4E42C3DEC0C6F5B5105", + "subject_key_identifier": "E21E2FE71C19390E554B62C120245735248A2514", + "authority_key_identifier": "E13AAB217CF1E34D54AED472B7FD8B5942209054", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T15:54:08Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:24:32Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?roottlscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDaDCCAu6gAwIBAgIQAKSu5njyM2K0wORgt3LyFDAKBggqhkjOPQQDAzBWMQsw\nCQYDVQQGEwJJTjElMCMGA1UECgwcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl\nZDEgMB4GA1UEAwwXZW1TaWduIFJvb3QgVExTIENBIC0gRzMwHhcNMjUwNDMwMTU1\nNDA4WhcNNDAwNDI4MTgzMDAwWjA/MQswCQYDVQQGEwJOTDETMBEGA1UECgwKZU11\nZGhyYSBCVjEbMBkGA1UEAwwSRU0gRFYgVExTIENBIC0gRzNCMHYwEAYHKoZIzj0C\nAQYFK4EEACIDYgAE557ZwEqXc8RzXlERHahawr1eZKs3S4DhLLwgOOweTw47gS/J\nhZ4eZ6+wTi+LyX90hbplqpEe6KTkW2LVzAPVa+Z4s8OMtNyTfKJGDiOEU8iSk10p\n1E+R4VYGtjzO2rRoo4IBljCCAZIwHwYDVR0jBBgwFoAU4TqrIXzx401UrtRyt/2L\nWUIgkFQwHQYDVR0OBBYEFOIeL+ccGTkOVUtiwSAkVzUkiiUUMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjBdBgNVHSAEVjBUMDkGCysGAQQBg44hAQABMCow\nKAYIKwYBBQUHAgEWHGh0dHA6Ly9yZXBvc2l0b3J5LmVtc2lnbi5jb20wDQYLKwYB\nBAGDjiEBAmQwCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAkBggrBgEFBQcwAYYY\naHR0cDovL29jc3AtYi5lbXNpZ24uY29tMD8GCCsGAQUFBzAChjNodHRwOi8vcmVw\nb3NpdG9yeS5lbXNpZ24uY29tL2NlcnRzL0VNRFZUTFNDQUczQi5wN2MwNwYDVR0f\nBDAwLjAsoCqgKIYmaHR0cDovL2NybC5lbXNpZ24uY29tLz9yb290dGxzY2FnMy5j\ncmwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwCgYIKoZIzj0E\nAwMDaAAwZQIwLmsGXi6oFMJ2klkcEMXMug6gvxQWZWkewiDWVzQyl2L6z6DuQfPO\nIbh1grvdULDCAjEAxZvLlxUavG69J6wnSjC8XBbqNIQsJ6CE2QdNOe84Ptxb6VG8\ngt2TlfJbHii+KNvK\n-----END CERTIFICATE-----" + }, + { + "name": "EM DV TLS CA - G3B", + "usage": "tls", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM DV TLS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "A024FDF4BA665C785CE4A020483858B7", + "sha256": "45A883F349AEDFD5F3A649B5498FFB121712BA8B448F3F2A91DBC5A766FCDDBE", + "spki_sha256": "EBED6475C2C2D80FCB199F3FE8DD6E6B3CE60B77EB15D4E42C3DEC0C6F5B5105", + "subject_key_identifier": "E21E2FE71C19390E554B62C120245735248A2514", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDzjCCAragAwIBAgIRAKAk/fS6Zlx4XOSgIEg4WLcwDQYJKoZIhvcNAQELBQAw\nezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\nA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV\nBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y\nODEyMzEyMzU5NTlaMD8xCzAJBgNVBAYTAk5MMRMwEQYDVQQKDAplTXVkaHJhIEJW\nMRswGQYDVQQDDBJFTSBEViBUTFMgQ0EgLSBHM0IwdjAQBgcqhkjOPQIBBgUrgQQA\nIgNiAATnntnASpdzxHNeUREdqFrCvV5kqzdLgOEsvCA47B5PDjuBL8mFnh5nr7BO\nL4vJf3SFumWqkR7opORbYtXMA9Vr5nizw4y03JN8okYOI4RTyJKTXSnUT5HhVga2\nPM7atGijggE1MIIBMTAfBgNVHSMEGDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAd\nBgNVHQ4EFgQU4h4v5xwZOQ5VS2LBICRXNSSKJRQwDgYDVR0PAQH/BAQDAgEGMBIG\nA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\nMDEGA1UdIAQqMCgwCAYGZ4EMAQIBMA0GCysGAQQBg44hAQABMA0GCysGAQQBg44h\nAQJkMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FB\nQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEF\nBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBCwUAA4IB\nAQBzQ1IoqpdotM6gFrR4Q3YrKifOLeaj5XXunldpVE/vZn2TxC2y0s8oYiLR5ICE\nwqVXSB7N6BM1Mp+Nif7Jbhb2IswAfSR4Iik8+B0iRmi7lYoNlycCgHjmsjOmZaxM\nQkPmjXAJbG5f4V41OsvJZmS7lI3r0IuvEDVX3GAZ13on6IImSs9ybNpHQ7NCqkMQ\n7wH4uAO1dtpFycgJSdHaCOhHjrox2BTYGLdpUrYwY3EOAjlZ8UGgsxs7mG+xquMl\nbN1LFURwfnkVMP3T/DBIZ/ys2+lNFyxK3FlArrV4/000uTnVB1lO8oGORYdXoT5V\nGUyRCEIDhF5TBUuKF4E3kf1h\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV TLS CA - G3B", + "usage": "tls", + "issued_by": "emSign Root TLS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "subject": "CN=EM OV TLS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=emSign Root TLS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "6CADA367FB1C100088120EA202D568", + "sha256": "98B896625C0C230ADEEC3EB2CF6AAD5001ECF9156A68644E82374CE5833BC25B", + "spki_sha256": "43BFFA19D6EF651451F6841E019931E96F6F2EAEFF28AB4B6F1CE4576DE2717B", + "subject_key_identifier": "9BD86551AFE7E72C37AD08EE6919D9BF3784AE0A", + "authority_key_identifier": "E13AAB217CF1E34D54AED472B7FD8B5942209054", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T16:00:12Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:37:19Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?roottlscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDZjCCAu2gAwIBAgIPbK2jZ/scEACIEg6iAtVoMAoGCCqGSM49BAMDMFYxCzAJ\nBgNVBAYTAklOMSUwIwYDVQQKDBxlTXVkaHJhIFRlY2hub2xvZ2llcyBMaW1pdGVk\nMSAwHgYDVQQDDBdlbVNpZ24gUm9vdCBUTFMgQ0EgLSBHMzAeFw0yNTA0MzAxNjAw\nMTJaFw00MDA0MjgxODMwMDBaMD8xCzAJBgNVBAYTAk5MMRMwEQYDVQQKDAplTXVk\naHJhIEJWMRswGQYDVQQDDBJFTSBPViBUTFMgQ0EgLSBHM0IwdjAQBgcqhkjOPQIB\nBgUrgQQAIgNiAARziXqg6zz9yosSQC/68KvE4SErr43ud4rJ7i1tuD+sKAxeBWOK\n56Ks1xwyKo42HN659pxDArndjXPRzGyqsswK7k4hbOl53VGKSvS2JuVoTN1lgDft\nDIVOTMEvTPhkbQ2jggGWMIIBkjAfBgNVHSMEGDAWgBThOqshfPHjTVSu1HK3/YtZ\nQiCQVDAdBgNVHQ4EFgQUm9hlUa/n5yw3rQjuaRnZvzeErgowHQYDVR0lBBYwFAYI\nKwYBBQUHAwEGCCsGAQUFBwMCMF0GA1UdIARWMFQwOQYLKwYBBAGDjiEBAAEwKjAo\nBggrBgEFBQcCARYcaHR0cDovL3JlcG9zaXRvcnkuZW1zaWduLmNvbTANBgsrBgEE\nAYOOIQECbjAIBgZngQwBAgIwdQYIKwYBBQUHAQEEaTBnMCQGCCsGAQUFBzABhhho\ndHRwOi8vb2NzcC1iLmVtc2lnbi5jb20wPwYIKwYBBQUHMAKGM2h0dHA6Ly9yZXBv\nc2l0b3J5LmVtc2lnbi5jb20vY2VydHMvRU1PVlRMU0NBRzNCLnA3YzA3BgNVHR8E\nMDAuMCygKqAohiZodHRwOi8vY3JsLmVtc2lnbi5jb20vP3Jvb3R0bHNjYWczLmNy\nbDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAKBggqhkjOPQQD\nAwNnADBkAjBAk+5BizdJhrED3wb7F2Gm7bWI60dlNd075nghT2TrR4NWKZtJZcbc\n28xxIY/NONICMF6mPdsjosaqmvEMWqKcBh4vsIvXSKnQj5o8zrFB4oKS+accjYTe\n8Dz3bQjauvy9uw==\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV TLS CA - G3B", + "usage": "tls", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM OV TLS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "E94223BDE92F914E5AB9ACABFDAC3710", + "sha256": "5F1DED4DD590AF74631290CF073B122A2AAC6A1FA479778A0BD43579BD832699", + "spki_sha256": "43BFFA19D6EF651451F6841E019931E96F6F2EAEFF28AB4B6F1CE4576DE2717B", + "subject_key_identifier": "9BD86551AFE7E72C37AD08EE6919D9BF3784AE0A", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDzjCCAragAwIBAgIRAOlCI73pL5FOWrmsq/2sNxAwDQYJKoZIhvcNAQELBQAw\nezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\nA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV\nBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y\nODEyMzEyMzU5NTlaMD8xCzAJBgNVBAYTAk5MMRMwEQYDVQQKDAplTXVkaHJhIEJW\nMRswGQYDVQQDDBJFTSBPViBUTFMgQ0EgLSBHM0IwdjAQBgcqhkjOPQIBBgUrgQQA\nIgNiAARziXqg6zz9yosSQC/68KvE4SErr43ud4rJ7i1tuD+sKAxeBWOK56Ks1xwy\nKo42HN659pxDArndjXPRzGyqsswK7k4hbOl53VGKSvS2JuVoTN1lgDftDIVOTMEv\nTPhkbQ2jggE1MIIBMTAfBgNVHSMEGDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAd\nBgNVHQ4EFgQUm9hlUa/n5yw3rQjuaRnZvzeErgowDgYDVR0PAQH/BAQDAgEGMBIG\nA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\nMDEGA1UdIAQqMCgwCAYGZ4EMAQICMA0GCysGAQQBg44hAQABMA0GCysGAQQBg44h\nAQJuMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FB\nQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEF\nBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBCwUAA4IB\nAQALRoOSvkzRa+tN5Rje9W5GiXd/qsicd9N6Gnh0SWC7VyWH+HycIqAnFCMYZznj\nCeGusomFYHE42SHWr85JDIbgzy6y3dO4i9n9w0Bx7yrXWBbDzFS8VgA3+EY4Cg7y\nmtoC3RPOJVtaXXPZ+68X804g1Mj+3vCSHj2lNPVgco0OzSIOJ/KMg1R9MLBkiKzb\nbERAGZHejY0HBhYd76IINZN8z6bBNah2UdFYxsOisLynPQUkol6gRLum024/FzVl\nCCDfnUusrkr+mAfPAvD/Vb8bhpA7jYtepuU+2mIdShj5lLlvAwZphn+ypWycuo2x\n0k9mldz2dqI9nhCiY+TTIOOR\n-----END CERTIFICATE-----" + }, + { + "name": "EM EV TLS CA - G3B", + "usage": "tls", + "issued_by": "emSign Root TLS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "subject": "CN=EM EV TLS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=emSign Root TLS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "C7C41EFE92D825F05EAE841A4A82C1", + "sha256": "E7568FE6E12331F4FD7DE61DA4C7559D0F8EB192A218D4741A3BA75184333838", + "spki_sha256": "E0254C7FCDC265E2F0F8A428DABB75AB4AE039B4872D62F5EE57F0877D5A8A41", + "subject_key_identifier": "3EDC20D9894698877B873FD88147B25C15D84706", + "authority_key_identifier": "E13AAB217CF1E34D54AED472B7FD8B5942209054", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T16:03:31Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:28:53Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?roottlscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDaDCCAu2gAwIBAgIQAMfEHv6S2CXwXq6EGkqCwTAKBggqhkjOPQQDAzBWMQsw\nCQYDVQQGEwJJTjElMCMGA1UECgwcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl\nZDEgMB4GA1UEAwwXZW1TaWduIFJvb3QgVExTIENBIC0gRzMwHhcNMjUwNDMwMTYw\nMzMxWhcNNDAwNDI4MTgzMDAwWjA/MQswCQYDVQQGEwJOTDETMBEGA1UECgwKZU11\nZGhyYSBCVjEbMBkGA1UEAwwSRU0gRVYgVExTIENBIC0gRzNCMHYwEAYHKoZIzj0C\nAQYFK4EEACIDYgAEJduoWmTTl9oLEFLp6lRuSHvv6pydnWigxerc/u91ppu11vwB\n9Cv7ym60C81kwHZ+Nv/QXZeoE8WqDGyVMOec9fCGZGjxOAZCCqXIUYQLHiUlQOeQ\n5LZUw4Uu1krx6GV9o4IBlTCCAZEwHwYDVR0jBBgwFoAU4TqrIXzx401UrtRyt/2L\nWUIgkFQwHQYDVR0OBBYEFD7cINmJRpiHe4c/2IFHslwV2EcGMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjBcBgNVHSAEVTBTMDkGCysGAQQBg44hAQABMCow\nKAYIKwYBBQUHAgEWHGh0dHA6Ly9yZXBvc2l0b3J5LmVtc2lnbi5jb20wDQYLKwYB\nBAGDjiEBAngwBwYFZ4EMAQEwdQYIKwYBBQUHAQEEaTBnMCQGCCsGAQUFBzABhhho\ndHRwOi8vb2NzcC1iLmVtc2lnbi5jb20wPwYIKwYBBQUHMAKGM2h0dHA6Ly9yZXBv\nc2l0b3J5LmVtc2lnbi5jb20vY2VydHMvRU1FVlRMU0NBRzNCLnA3YzA3BgNVHR8E\nMDAuMCygKqAohiZodHRwOi8vY3JsLmVtc2lnbi5jb20vP3Jvb3R0bHNjYWczLmNy\nbDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAKBggqhkjOPQQD\nAwNpADBmAjEA9Jq999oaOUKhFwopw33iCmt0OHIn3gjT43GfuOHR/YckXdwoNdDA\nlIEhz0NgRO3/AjEAvY/a3OMvktIZLYjn+WLKmp0QhrIMV+e6EpS7j4GVeOKouNp6\nMN/P+ByGeiRMghzB\n-----END CERTIFICATE-----" + }, + { + "name": "EM EV TLS CA - G3B", + "usage": "tls", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM EV TLS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "D8F8685E4F2BD9D82402A85A1C1EB731", + "sha256": "579480AEA166290BD3C643589E795FC0D0E54E86505D180F1DFF99EFD3199512", + "spki_sha256": "E0254C7FCDC265E2F0F8A428DABB75AB4AE039B4872D62F5EE57F0877D5A8A41", + "subject_key_identifier": "3EDC20D9894698877B873FD88147B25C15D84706", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDzTCCArWgAwIBAgIRANj4aF5PK9nYJAKoWhwetzEwDQYJKoZIhvcNAQELBQAw\nezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\nA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV\nBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y\nODEyMzEyMzU5NTlaMD8xCzAJBgNVBAYTAk5MMRMwEQYDVQQKDAplTXVkaHJhIEJW\nMRswGQYDVQQDDBJFTSBFViBUTFMgQ0EgLSBHM0IwdjAQBgcqhkjOPQIBBgUrgQQA\nIgNiAAQl26haZNOX2gsQUunqVG5Ie+/qnJ2daKDF6tz+73Wmm7XW/AH0K/vKbrQL\nzWTAdn42/9Bdl6gTxaoMbJUw55z18IZkaPE4BkIKpchRhAseJSVA55DktlTDhS7W\nSvHoZX2jggE0MIIBMDAfBgNVHSMEGDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAd\nBgNVHQ4EFgQUPtwg2YlGmId7hz/YgUeyXBXYRwYwDgYDVR0PAQH/BAQDAgEGMBIG\nA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\nMDAGA1UdIAQpMCcwBwYFZ4EMAQEwDQYLKwYBBAGDjiEBAAEwDQYLKwYBBAGDjiEB\nAngwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFB\nQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUF\nBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQELBQADggEB\nAJNFuAFW9Gnw/8+kCO4KIlZdnM1Sh2u+8cK0EYAHhXpb5FlGvYkcARigo5oS7VoM\n7FOYlTueV6yICZKNAYawZPJPhNCGK+rp3cQBEz6d0n8OZEYZov9lb3ll8ORgSDuf\nFVIW6Gagg/UnOamLBTOR8eD5V73SCme/B2cHUDw+m5E8cc+0Ujzz3Cn3ex5JrhXk\n2T3s8PoVzEmhTgGboFfcWO1EYhPPrYwdxPYRQIXAXUXhLEOVNL9ASbZJLFI8E1IM\nm7NwxVN2s38jWpaCUaaF0tg7hfiy7oe13rzJfHsdqldJVTTUTPWVx8TC4ju0VLet\nbAlwhwFT6AP8uIVMGUHNw24=\n-----END CERTIFICATE-----" + }, + { + "name": "EM DV TLS CA - G3C", + "usage": "tls", + "issued_by": "emSign Root TLS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "subject": "CN=EM DV TLS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=emSign Root TLS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "588B2E3C2BB8CDA13E1A1209254321", + "sha256": "0164D7CEAE5BB909C272AF151FF44B1177AE9B47D9424B94F1D9558C30934D19", + "spki_sha256": "49DD353DC2B919A3770645117D0E60C16115E7D1BC259EEFE734B00EA434FE5F", + "subject_key_identifier": "AE7E105C3C2996C1A847270559F1E03DD4E50AF3", + "authority_key_identifier": "E13AAB217CF1E34D54AED472B7FD8B5942209054", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T15:35:09Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:27:07Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?roottlscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDaDCCAu6gAwIBAgIPWIsuPCu4zaE+GhIJJUMhMAoGCCqGSM49BAMDMFYxCzAJ\nBgNVBAYTAklOMSUwIwYDVQQKDBxlTXVkaHJhIFRlY2hub2xvZ2llcyBMaW1pdGVk\nMSAwHgYDVQQDDBdlbVNpZ24gUm9vdCBUTFMgQ0EgLSBHMzAeFw0yNTA0MzAxNTM1\nMDlaFw00MDA0MjgxODMwMDBaMEAxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtlTXVk\naHJhIEluYzEbMBkGA1UEAwwSRU0gRFYgVExTIENBIC0gRzNDMHYwEAYHKoZIzj0C\nAQYFK4EEACIDYgAEOnp4YsjETTJN3WkDOmeCwO/u/kBV5ooSP6A3G6O9kZRRTuFy\npDPjYw8CvRiAN9nlFJ+bd9uUooHfmHsv6oiLdL3+j9pMEJnubKGVZv4+8OX2sJpV\nbMyLpQVh3xsqRB0Bo4IBljCCAZIwHwYDVR0jBBgwFoAU4TqrIXzx401UrtRyt/2L\nWUIgkFQwHQYDVR0OBBYEFK5+EFw8KZbBqEcnBVnx4D3U5QrzMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjBdBgNVHSAEVjBUMDkGCysGAQQBg44hAQABMCow\nKAYIKwYBBQUHAgEWHGh0dHA6Ly9yZXBvc2l0b3J5LmVtc2lnbi5jb20wDQYLKwYB\nBAGDjiEBAmQwCAYGZ4EMAQIBMHUGCCsGAQUFBwEBBGkwZzAkBggrBgEFBQcwAYYY\naHR0cDovL29jc3AtYy5lbXNpZ24uY29tMD8GCCsGAQUFBzAChjNodHRwOi8vcmVw\nb3NpdG9yeS5lbXNpZ24uY29tL2NlcnRzL0VNRFZUTFNDQUczQy5wN2MwNwYDVR0f\nBDAwLjAsoCqgKIYmaHR0cDovL2NybC5lbXNpZ24uY29tLz9yb290dGxzY2FnMy5j\ncmwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwCgYIKoZIzj0E\nAwMDaAAwZQIxAMEN2HWMocbuWdy1d33pH6JpMvP/V/DIS5PtZbv1Q7TXEbxrcyxg\nyuddOJscYDJJlAIwB4sH1BpbScDzkdD4tJBSwrG/1Mx82vb8YaySehNuu1+1oXNd\nAEKwaJ0mVzScy2+6\n-----END CERTIFICATE-----" + }, + { + "name": "EM DV TLS CA - G3C", + "usage": "tls", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM DV TLS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "91F347F1A5B7D39962B95E0EE4E299D1", + "sha256": "62B7F9868263F72F6911FC78CEAF72C1979158B7368BF648683BB2AA39B02E72", + "spki_sha256": "49DD353DC2B919A3770645117D0E60C16115E7D1BC259EEFE734B00EA434FE5F", + "subject_key_identifier": "AE7E105C3C2996C1A847270559F1E03DD4E50AF3", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDzzCCAregAwIBAgIRAJHzR/Glt9OZYrleDuTimdEwDQYJKoZIhvcNAQELBQAw\nezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\nA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV\nBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y\nODEyMzEyMzU5NTlaMEAxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtlTXVkaHJhIElu\nYzEbMBkGA1UEAwwSRU0gRFYgVExTIENBIC0gRzNDMHYwEAYHKoZIzj0CAQYFK4EE\nACIDYgAEOnp4YsjETTJN3WkDOmeCwO/u/kBV5ooSP6A3G6O9kZRRTuFypDPjYw8C\nvRiAN9nlFJ+bd9uUooHfmHsv6oiLdL3+j9pMEJnubKGVZv4+8OX2sJpVbMyLpQVh\n3xsqRB0Bo4IBNTCCATEwHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQw\nHQYDVR0OBBYEFK5+EFw8KZbBqEcnBVnx4D3U5QrzMA4GA1UdDwEB/wQEAwIBBjAS\nBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD\nAjAxBgNVHSAEKjAoMAgGBmeBDAECATANBgsrBgEEAYOOIQEAATANBgsrBgEEAYOO\nIQECZDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9B\nQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYB\nBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQsFAAOC\nAQEAr7b6Mx11TIJgVzHt6EH5qGNWeiiqoMrp8E5/k8s+jvupx1n083pZ5XOzUzND\nwEUe0W4C4FIGUHNQ4XDwqOw0yK42xqm2dvCKgsko2UvDlT0haZVtTCeWMQOe5J/J\nziaMfZwsZNfZ3aaI6XPtWDZtwY8AaNfyaeCpbtm5GcGnyNWk4jSNpbtpo6NjfXuP\nCFOm3rTjJ4zytP7Tso6iMm0L01cYFOlTmoPv4515R2r3SPnKDtijoB/D/vgxzojv\nDafgyG9afX8+laO9NbMMz4sqC1vZx3984i/sBNFiugm3Vvdq5OdJRjuGC1QILIs6\ndg/K3i8VQqRpbfaM9kIlMzZ3dQ==\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV TLS CA - G3C", + "usage": "tls", + "issued_by": "emSign Root TLS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "subject": "CN=EM OV TLS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=emSign Root TLS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "296926C227A3A1526392B19482A504", + "sha256": "CB6E15165AC802E9B3F993F16C25D41F4E81C21EBDE71AE1B012AC00BF9C7C3F", + "spki_sha256": "63ECEFEE431D49523BC1136C4E72D0206A477086CAF606CD5CF025686C109CF8", + "subject_key_identifier": "34EAEA0CEBC90ADAF9D0C5E2ED9B78C9879E1B6C", + "authority_key_identifier": "E13AAB217CF1E34D54AED472B7FD8B5942209054", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T15:37:41Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:38:46Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?roottlscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDaDCCAu6gAwIBAgIPKWkmwiejoVJjkrGUgqUEMAoGCCqGSM49BAMDMFYxCzAJ\nBgNVBAYTAklOMSUwIwYDVQQKDBxlTXVkaHJhIFRlY2hub2xvZ2llcyBMaW1pdGVk\nMSAwHgYDVQQDDBdlbVNpZ24gUm9vdCBUTFMgQ0EgLSBHMzAeFw0yNTA0MzAxNTM3\nNDFaFw00MDA0MjgxODMwMDBaMEAxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtlTXVk\naHJhIEluYzEbMBkGA1UEAwwSRU0gT1YgVExTIENBIC0gRzNDMHYwEAYHKoZIzj0C\nAQYFK4EEACIDYgAEE4JRzVKskpjByKrZdzId65fnCb0LTKCspV3IrVHc/J0ViaFZ\nfjpRIOHv1jHGPhg1ysrimGmmLhYx6KKBgatWYW3EXZGKvAnzqw5jz3kqpNztc4e+\nN7ulaVSfHAKycO1no4IBljCCAZIwHwYDVR0jBBgwFoAU4TqrIXzx401UrtRyt/2L\nWUIgkFQwHQYDVR0OBBYEFDTq6gzryQra+dDF4u2beMmHnhtsMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjBdBgNVHSAEVjBUMDkGCysGAQQBg44hAQABMCow\nKAYIKwYBBQUHAgEWHGh0dHA6Ly9yZXBvc2l0b3J5LmVtc2lnbi5jb20wDQYLKwYB\nBAGDjiEBAm4wCAYGZ4EMAQICMHUGCCsGAQUFBwEBBGkwZzAkBggrBgEFBQcwAYYY\naHR0cDovL29jc3AtYy5lbXNpZ24uY29tMD8GCCsGAQUFBzAChjNodHRwOi8vcmVw\nb3NpdG9yeS5lbXNpZ24uY29tL2NlcnRzL0VNT1ZUTFNDQUczQy5wN2MwNwYDVR0f\nBDAwLjAsoCqgKIYmaHR0cDovL2NybC5lbXNpZ24uY29tLz9yb290dGxzY2FnMy5j\ncmwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwCgYIKoZIzj0E\nAwMDaAAwZQIxAMSZt2xsPeumRdeSMSQ3CbzIZeQ/q7GDCWfeE1Pq+mhgA6gRM44c\nNVF3xJ+wsxJk+wIwFJbaDMokD8Ei6eNOiA8yUMYvfzQyngmrhZQMdPCK1SewrR79\n4rSb9vGqxZzelQth\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV TLS CA - G3C", + "usage": "tls", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM OV TLS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "8D5A4811939EF447D77111CDD9849AE9", + "sha256": "7485B51C0ED192878FA1D2F948FB529AE1842CC5086C4B67F7BE5B2039DE9489", + "spki_sha256": "63ECEFEE431D49523BC1136C4E72D0206A477086CAF606CD5CF025686C109CF8", + "subject_key_identifier": "34EAEA0CEBC90ADAF9D0C5E2ED9B78C9879E1B6C", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDzzCCAregAwIBAgIRAI1aSBGTnvRH13ERzdmEmukwDQYJKoZIhvcNAQELBQAw\nezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\nA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV\nBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y\nODEyMzEyMzU5NTlaMEAxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtlTXVkaHJhIElu\nYzEbMBkGA1UEAwwSRU0gT1YgVExTIENBIC0gRzNDMHYwEAYHKoZIzj0CAQYFK4EE\nACIDYgAEE4JRzVKskpjByKrZdzId65fnCb0LTKCspV3IrVHc/J0ViaFZfjpRIOHv\n1jHGPhg1ysrimGmmLhYx6KKBgatWYW3EXZGKvAnzqw5jz3kqpNztc4e+N7ulaVSf\nHAKycO1no4IBNTCCATEwHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQw\nHQYDVR0OBBYEFDTq6gzryQra+dDF4u2beMmHnhtsMA4GA1UdDwEB/wQEAwIBBjAS\nBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD\nAjAxBgNVHSAEKjAoMAgGBmeBDAECAjANBgsrBgEEAYOOIQEAATANBgsrBgEEAYOO\nIQECbjBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9B\nQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYB\nBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQsFAAOC\nAQEAHlbhZpjhkPEAQVhPHRtBDaHqiisVD20pQ1TUeSx3l62Qe7NQ0b7vWQy7DN0i\nKOu7BGpP5EnIjvXbz9FhpfPJ4FhKEt3tQ51rqXz2oD8vRaryvExWPobDUz3j7HN6\nOzBsVMIe3PD7AAkpky0x8zMSi/ep5R9OMzybmNptbtppyuB5ytgq+h7lQdRIP+CQ\nTaJX3qTgfMqzntYre5GljmEB5hU2/rSn8zoSU2APkJidlZFpghtgbD4I2VRHZvCw\nFFr/SrFM9pwrgbJNZ1MtyTSVgI5NlNb0aMfLR+/r6jJt3ROeY2yh2QQ2dx+Yqgdb\nuL5ChFWOQU+ErSDnUq7yr+pjBQ==\n-----END CERTIFICATE-----" + }, + { + "name": "EM EV TLS CA - G3C", + "usage": "tls", + "issued_by": "emSign Root TLS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "7DD78D5F4F13459A83DFF9ABBBA62EDBAF6F2D102BF257FD712F4D9F2746ED8D", + "subject": "CN=EM EV TLS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=emSign Root TLS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "8009928A64107601AF05FA2F19F109", + "sha256": "432EC25F0D28DE9006D97BF752F17BBB2CD41F669933FCB072D9A1148D0261F3", + "spki_sha256": "5C0660A2B164910D8FF589C18E14552E9E0EC237DCEFE2CB736D41A4811F81A0", + "subject_key_identifier": "A6255E80A94DB7F3967C1BC791DF92BCEE4BEB5F", + "authority_key_identifier": "E13AAB217CF1E34D54AED472B7FD8B5942209054", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T15:39:31Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:30:49Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?roottlscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDaDCCAu6gAwIBAgIQAIAJkopkEHYBrwX6LxnxCTAKBggqhkjOPQQDAzBWMQsw\nCQYDVQQGEwJJTjElMCMGA1UECgwcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl\nZDEgMB4GA1UEAwwXZW1TaWduIFJvb3QgVExTIENBIC0gRzMwHhcNMjUwNDMwMTUz\nOTMxWhcNNDAwNDI4MTgzMDAwWjBAMQswCQYDVQQGEwJVUzEUMBIGA1UECgwLZU11\nZGhyYSBJbmMxGzAZBgNVBAMMEkVNIEVWIFRMUyBDQSAtIEczQzB2MBAGByqGSM49\nAgEGBSuBBAAiA2IABC1W6Cmm+4LGSkaX2WCvlR6QZ66R+SbTQwbaSKiq63hptqZ+\nbSdCbgRCqgOzbhmI3/Y2UU7hzwf1uks/8qBmRa59MdWGatMao9JG6wsxd+6Zy3Vm\nxRbOdICKZo+R8MR/yqOCAZUwggGRMB8GA1UdIwQYMBaAFOE6qyF88eNNVK7Ucrf9\ni1lCIJBUMB0GA1UdDgQWBBSmJV6AqU2385Z8G8eR35K87kvrXzAdBgNVHSUEFjAU\nBggrBgEFBQcDAQYIKwYBBQUHAwIwXAYDVR0gBFUwUzA5BgsrBgEEAYOOIQEAATAq\nMCgGCCsGAQUFBwIBFhxodHRwOi8vcmVwb3NpdG9yeS5lbXNpZ24uY29tMA0GCysG\nAQQBg44hAQJ4MAcGBWeBDAEBMHUGCCsGAQUFBwEBBGkwZzAkBggrBgEFBQcwAYYY\naHR0cDovL29jc3AtYy5lbXNpZ24uY29tMD8GCCsGAQUFBzAChjNodHRwOi8vcmVw\nb3NpdG9yeS5lbXNpZ24uY29tL2NlcnRzL0VNRVZUTFNDQUczQy5wN2MwNwYDVR0f\nBDAwLjAsoCqgKIYmaHR0cDovL2NybC5lbXNpZ24uY29tLz9yb290dGxzY2FnMy5j\ncmwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwCgYIKoZIzj0E\nAwMDaAAwZQIwBy1wTnzH4lXDTy2PD91ysLjvnlVN3JbJmc1BIMEU8TOLkYVHibMc\n9HeyonikFSfmAjEA6uE3QRxlrZTz/1/lXPTEMUhoauAtycagtlNFp79kjhvNa2/f\nAal1GNxsOutLnr0Y\n-----END CERTIFICATE-----" + }, + { + "name": "EM EV TLS CA - G3C", + "usage": "tls", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM EV TLS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "05F078752DECE7A1BB8595D303167171", + "sha256": "FD9D5C2DBBD4995AB69B8D50C439D9527B00529199C2FD01B2174EB58F07021F", + "spki_sha256": "5C0660A2B164910D8FF589C18E14552E9E0EC237DCEFE2CB736D41A4811F81A0", + "subject_key_identifier": "A6255E80A94DB7F3967C1BC791DF92BCEE4BEB5F", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDzTCCArWgAwIBAgIQBfB4dS3s56G7hZXTAxZxcTANBgkqhkiG9w0BAQsFADB7\nMQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD\nVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE\nAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTI1MDUxNDAwMDAwMFoXDTI4\nMTIzMTIzNTk1OVowQDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC2VNdWRocmEgSW5j\nMRswGQYDVQQDDBJFTSBFViBUTFMgQ0EgLSBHM0MwdjAQBgcqhkjOPQIBBgUrgQQA\nIgNiAAQtVugppvuCxkpGl9lgr5UekGeukfkm00MG2kioqut4abamfm0nQm4EQqoD\ns24ZiN/2NlFO4c8H9bpLP/KgZkWufTHVhmrTGqPSRusLMXfumct1ZsUWznSAimaP\nkfDEf8qjggE0MIIBMDAfBgNVHSMEGDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAd\nBgNVHQ4EFgQUpiVegKlNt/OWfBvHkd+SvO5L618wDgYDVR0PAQH/BAQDAgEGMBIG\nA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\nMDAGA1UdIAQpMCcwBwYFZ4EMAQEwDQYLKwYBBAGDjiEBAAEwDQYLKwYBBAGDjiEB\nAngwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFB\nQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUF\nBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQELBQADggEB\nAIFfHiaMSjnrdZygRYV4ekRBmG7ybcFk4hGQWMMyMFi0cAEk2+dGfz5bl8IaIbLq\nz+uVJzhOgVEX7WqIfgbWfFsfPYHYjPHBmy7SlZ3BwA86IQ6qF/etpX2/qL9A5yRN\nN3nVowUpaqV6H3aCpkAh3wR2ZNkvAbLDvPz3J0l+sEWjWv+ZISOV4R+hXDTdPXV0\n1lKxnbwqEsdo/sE2QkCDKwFrZh/0uKjWspydJj+jSaDLTrGNx50Dgmn7VEcD1ZI5\nFXjknVUiO25YlmS1dtVZSBbyUKSjlrP/yDwPcZunoAsmCAAtCKsFLviLaymzvsKI\neSSDGxpSySp2VCxompGDk8g=\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV CS CA - G3B", + "usage": "code-signing", + "issued_by": "emSign Root CS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "F2EDAAFF3D9B701FB4D14C9F285F8C0BAD90FC3BCC1FA07D47F4718EDABA34A5", + "subject": "CN=EM OV CS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=emSign Root CS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "7818933F8F85B4619A2B35FBA83D0A", + "sha256": "9E39DE2881273ACC225A149C72BA3E0F51424963669AB633EE1DC7DF5DB067B4", + "spki_sha256": "EC4FFA1AD0AC88081314B7AAFFEF6A91F97CD57291BB5BA686C5415F5EB4F6B6", + "subject_key_identifier": "79FAE8ECCFDB0D758DA458D69FB6EDDC7C49DEE6", + "authority_key_identifier": "687403F885CA8D5450571D16E0C8DE450DABCD2D", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T16:08:27Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:33:37Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?rootcscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDWzCCAuCgAwIBAgIPeBiTP4+FtGGaKzX7qD0KMAoGCCqGSM49BAMDMFUxCzAJ\nBgNVBAYTAklOMSUwIwYDVQQKDBxlTXVkaHJhIFRlY2hub2xvZ2llcyBMaW1pdGVk\nMR8wHQYDVQQDDBZlbVNpZ24gUm9vdCBDUyBDQSAtIEczMB4XDTI1MDQzMDE2MDgy\nN1oXDTQwMDQyODE4MzAwMFowPjELMAkGA1UEBhMCTkwxEzARBgNVBAoMCmVNdWRo\ncmEgQlYxGjAYBgNVBAMMEUVNIE9WIENTIENBIC0gRzNCMHYwEAYHKoZIzj0CAQYF\nK4EEACIDYgAEqrsPsGZqz88B+tUr/P1MK/LLPDSX3nOVDlgZth/mlQmHQcjEkUOb\nNKBDHK/+W/m0wcjorgAB+fTcitgsWfNjnpbNbD1NsM7+wmw9YlF7N3YTcnQ/jord\nd7EAZPKr5eBQo4IBizCCAYcwHwYDVR0jBBgwFoAUaHQD+IXKjVRQVx0W4MjeRQ2r\nzS0wHQYDVR0OBBYEFHn66OzP2w11jaRY1p+27dx8Sd7mMBMGA1UdJQQMMAoGCCsG\nAQUFBwMDMF4GA1UdIARXMFUwOQYLKwYBBAGDjiEBAAEwKjAoBggrBgEFBQcCARYc\naHR0cDovL3JlcG9zaXRvcnkuZW1zaWduLmNvbTAOBgwrBgEEAYOOIQECgUgwCAYG\nZ4EMAQQBMHQGCCsGAQUFBwEBBGgwZjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3At\nYi5lbXNpZ24uY29tMD4GCCsGAQUFBzAChjJodHRwOi8vcmVwb3NpdG9yeS5lbXNp\nZ24uY29tL2NlcnRzL0VNT1ZDU0NBRzNCLnA3YzA2BgNVHR8ELzAtMCugKaAnhiVo\ndHRwOi8vY3JsLmVtc2lnbi5jb20vP3Jvb3Rjc2NhZzMuY3JsMA4GA1UdDwEB/wQE\nAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMAoGCCqGSM49BAMDA2kAMGYCMQC/zr03\nYEELsNKqzUtH2dVFi4BaKFdyrr/6G1dIWp8KAVgsw2/u4lyyboUDaC9jDvICMQC9\nHTxku84tNX9dmHOtH7aC2Nu/JM0jTf6KjZAvovCJzzv1IFWSZpVLZibynMLXOrM=\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV CS CA - G3B", + "usage": "code-signing", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM OV CS CA - G3B,O=eMudhra BV,C=NL", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "41E32B73AC185D6CE0D7480BACF84E69", + "sha256": "A496E23AC0CAB8155FC9B117B97EAE368EFCBB9041AEC8804D5A308D2D01C2D8", + "spki_sha256": "EC4FFA1AD0AC88081314B7AAFFEF6A91F97CD57291BB5BA686C5415F5EB4F6B6", + "subject_key_identifier": "79FAE8ECCFDB0D758DA458D69FB6EDDC7C49DEE6", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDwzCCAqugAwIBAgIQQeMrc6wYXWzg10gLrPhOaTANBgkqhkiG9w0BAQsFADB7\nMQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD\nVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE\nAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTI1MDUxNDAwMDAwMFoXDTI4\nMTIzMTIzNTk1OVowPjELMAkGA1UEBhMCTkwxEzARBgNVBAoMCmVNdWRocmEgQlYx\nGjAYBgNVBAMMEUVNIE9WIENTIENBIC0gRzNCMHYwEAYHKoZIzj0CAQYFK4EEACID\nYgAEqrsPsGZqz88B+tUr/P1MK/LLPDSX3nOVDlgZth/mlQmHQcjEkUObNKBDHK/+\nW/m0wcjorgAB+fTcitgsWfNjnpbNbD1NsM7+wmw9YlF7N3YTcnQ/jordd7EAZPKr\n5eBQo4IBLDCCASgwHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD\nVR0OBBYEFHn66OzP2w11jaRY1p+27dx8Sd7mMA4GA1UdDwEB/wQEAwIBBjASBgNV\nHRMBAf8ECDAGAQH/AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMDIGA1UdIAQrMCkw\nCAYGZ4EMAQQBMA0GCysGAQQBg44hAQABMA4GDCsGAQQBg44hAQKBSDBDBgNVHR8E\nPDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9BQUFDZXJ0aWZpY2F0\nZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6\nLy9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAIh0OzWsdBYhY\n7+yxPGyosRL+uUSN6/Mrd30fBuougs5FVWQ3cRgLhImnUUgXADY9buugWhMmfT3c\nyU5T1MFXZXClCILm5mfg+oqm/ikUWJl3Ayf2GvYf2O++6vzqvkn418nI5Lpdt0O7\nLi524YS/3CZHDA+zZQ7rrHpZXgQ9Hmp8AUQ4FneaGjNanFoYxiZxwCyW5z4u7AoK\n0bmOVqKtcDFoVNz5++G9TYDJdhWOXmKKgzqRo1MK0PjazNT7MGHqknP93SqMVJ1g\nmX/qNWxYteAjlvFanQxBNX/+TRxDjuFsEHO/7BvqSpIIck0UEEfizhN8zNpWLbcl\nEqVgl0g39A==\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV CS CA - G3C", + "usage": "code-signing", + "issued_by": "emSign Root CS CA - G3", + "issuer_operator": "eMudhra", + "issuer_sha256": "F2EDAAFF3D9B701FB4D14C9F285F8C0BAD90FC3BCC1FA07D47F4718EDABA34A5", + "subject": "CN=EM OV CS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=emSign Root CS CA - G3,O=eMudhra Technologies Limited,C=IN", + "serial_hex": "544B7F922C31AE220A4A922916F6E6", + "sha256": "4B2460A466F95FD40113BCDCCA2CEB29B3B093921DE45474DA7DF48874C630B1", + "spki_sha256": "92C063D67E8F14DB71D288E11266FFDAF69CBF115F7BAB14F3BC2F68D25E0E30", + "subject_key_identifier": "EE6F73298D6FBFA7B31BC39534F61556447866B7", + "authority_key_identifier": "687403F885CA8D5450571D16E0C8DE450DABCD2D", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "ecdsa-with-SHA384", + "not_before": "2025-04-30T16:38:40Z", + "not_after": "2040-04-28T18:30:00Z", + "revocation": { + "status": "revoked", + "date": "2026-10-18T09:35:24Z", + "reason": "ca_compromise", + "crl_url": "http://crl.emsign.com/?rootcscag3.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDWzCCAuGgAwIBAgIPVEt/kiwxriIKSpIpFvbmMAoGCCqGSM49BAMDMFUxCzAJ\nBgNVBAYTAklOMSUwIwYDVQQKDBxlTXVkaHJhIFRlY2hub2xvZ2llcyBMaW1pdGVk\nMR8wHQYDVQQDDBZlbVNpZ24gUm9vdCBDUyBDQSAtIEczMB4XDTI1MDQzMDE2Mzg0\nMFoXDTQwMDQyODE4MzAwMFowPzELMAkGA1UEBhMCVVMxFDASBgNVBAoMC2VNdWRo\ncmEgSW5jMRowGAYDVQQDDBFFTSBPViBDUyBDQSAtIEczQzB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABLnw4GNHAqacpqrdRDz9YsQbm6SyCSRpfXl052kaEm+5avs+NML9\nO8X0gwYfJl3CpYQ2NHMjUQQ2so8E84YjYwZ5gOJQPgJTLWVGI1pxZaJZoe9Jb3Qb\nX97neHII5Lj676OCAYswggGHMB8GA1UdIwQYMBaAFGh0A/iFyo1UUFcdFuDI3kUN\nq80tMB0GA1UdDgQWBBTub3MpjW+/p7Mbw5U09hVWRHhmtzATBgNVHSUEDDAKBggr\nBgEFBQcDAzBeBgNVHSAEVzBVMDkGCysGAQQBg44hAQABMCowKAYIKwYBBQUHAgEW\nHGh0dHA6Ly9yZXBvc2l0b3J5LmVtc2lnbi5jb20wDgYMKwYBBAGDjiEBAoFIMAgG\nBmeBDAEEATB0BggrBgEFBQcBAQRoMGYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw\nLWMuZW1zaWduLmNvbTA+BggrBgEFBQcwAoYyaHR0cDovL3JlcG9zaXRvcnkuZW1z\naWduLmNvbS9jZXJ0cy9FTU9WQ1NDQUczQy5wN2MwNgYDVR0fBC8wLTAroCmgJ4Yl\naHR0cDovL2NybC5lbXNpZ24uY29tLz9yb290Y3NjYWczLmNybDAOBgNVHQ8BAf8E\nBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAKBggqhkjOPQQDAwNoADBlAjEA8yPg\n8sntOhLwV2QXJ5LEaKSpo/fnE3uOgTadK73fDhyjiqr0Io9GVuQTYqBPbQ2TAjBg\neuApmBS486+iei03lRrp139dPw6k28jjGNvWsAU7A1N86J1zPJVDEyVH+nMAWC0=\n-----END CERTIFICATE-----" + }, + { + "name": "EM OV CS CA - G3C", + "usage": "code-signing", + "issued_by": "AAA Certificate Services", + "issuer_operator": "Sectigo", + "issuer_sha256": "D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", + "subject": "CN=EM OV CS CA - G3C,O=eMudhra Inc,C=US", + "issuer": "CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB", + "serial_hex": "D6A5EF613B390F32EF9CDF349F772841", + "sha256": "84112972B8E59D14560AE7E7119654474AAD119990CF3722BFC1E3B91615E1FD", + "spki_sha256": "92C063D67E8F14DB71D288E11266FFDAF69CBF115F7BAB14F3BC2F68D25E0E30", + "subject_key_identifier": "EE6F73298D6FBFA7B31BC39534F61556447866B7", + "authority_key_identifier": "A0110A233E96F107ECE2AF29EF82A57FD030A4B4", + "key": { + "algorithm": "EC", + "curve": "secp384r1", + "bits": 384 + }, + "signature_algorithm": "sha256WithRSAEncryption", + "not_before": "2025-05-14T00:00:00Z", + "not_after": "2028-12-31T23:59:59Z", + "revocation": { + "status": "revoked", + "date": "2026-10-19T10:35:36Z", + "reason": "ca_compromise", + "crl_url": "http://crl.comodoca.com/AAACertificateServices.crl" + }, + "pem": "-----BEGIN CERTIFICATE-----\nMIIDxTCCAq2gAwIBAgIRANal72E7OQ8y75zfNJ93KEEwDQYJKoZIhvcNAQELBQAw\nezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\nA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV\nBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0yNTA1MTQwMDAwMDBaFw0y\nODEyMzEyMzU5NTlaMD8xCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtlTXVkaHJhIElu\nYzEaMBgGA1UEAwwRRU0gT1YgQ1MgQ0EgLSBHM0MwdjAQBgcqhkjOPQIBBgUrgQQA\nIgNiAAS58OBjRwKmnKaq3UQ8/WLEG5uksgkkaX15dOdpGhJvuWr7PjTC/TvF9IMG\nHyZdwqWENjRzI1EENrKPBPOGI2MGeYDiUD4CUy1lRiNacWWiWaHvSW90G1/e53hy\nCOS4+u+jggEsMIIBKDAfBgNVHSMEGDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAd\nBgNVHQ4EFgQU7m9zKY1vv6ezG8OVNPYVVkR4ZrcwDgYDVR0PAQH/BAQDAgEGMBIG\nA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwMgYDVR0gBCsw\nKTAIBgZngQwBBAEwDQYLKwYBBAGDjiEBAAEwDgYMKwYBBAGDjiEBAoFIMEMGA1Ud\nHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmlj\nYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0\ncDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBgGbZ+NDkn\n2Fr5dCVs/51+6cT5iEPP1stglX4TI2UaNh9LmPdltxXw3crV8gK5L8i+d+ScGibF\ny0obtBHNTldXDgLnAHIzY3n+pceyKj7O2ae9CYnyuu5RBifeI3XYKowWE+oXnVGF\nOy0CvCJ/JsdP6aYgoCa9hGnAYicYQQL6MOMQZ5PuhcSM8t4giIzrpgrEkUP93GYE\nemDG5Z8BYwKs80lLeQNBnwg/VHJ3iEF/o84RXYwrlrKqJ+33C094o6LNikMJCqOK\n/WYHZSR8Xyhf8GXFAj5pZuI6Bcpug2V/E7i42j8OBhc25aNYDqK+B0qmb90sjNUB\ng3tJeSIb/599\n-----END CERTIFICATE-----" + } +] \ No newline at end of file diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 1a5880ae9b7..7856ae586d8 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -21,6 +21,14 @@ permissions: jobs: build: + env: + # pip 26.2.2 (first release with a certifi bundle that distrusts the + # compromised eMudhra/emSign intermediates). The sha256 fragment guarantees + # the integrity of the bootstrap download even if the pip that runs the + # install trusts the compromised CAs. Keep in sync with + # .github/actions/setup-hardened-python/action.yml. See + # https://github.com/NVIDIA/cuda-python/issues/3195. + HARDENED_PIP_REQUIREMENT: "pip @ https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl#sha256=fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70" strategy: fail-fast: false matrix: @@ -38,6 +46,9 @@ jobs: (inputs.host-platform == 'linux-aarch64' && 'linux-arm64-cpu8') || (inputs.host-platform == 'win-64' && 'windows-2022') }} steps: + - name: Harden OS certificate trust (eMudhra/emSign CA stopgap) + uses: $/.github/actions/upgrade-ca-certificates + - name: Checkout ${{ github.event.repository.name }} uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -52,16 +63,13 @@ jobs: enable-apt: true - name: Set up Python - id: setup-python1 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + id: host-python + uses: ./.github/actions/setup-hardened-python with: - # WAR: setup-python is not relocatable, and cibuildwheel hard-wires to 3.12... - # see https://github.com/actions/setup-python/issues/871 + # Also installs cibuildwheel (via python-path below), so the action + # does not fall back on its own unchecked setup-python interpreter. python-version: "3.12" - - name: Harden pip - uses: ./.github/actions/harden-pip - - name: Set up MSVC if: ${{ startsWith(inputs.host-platform, 'win') }} uses: ilammy/msvc-dev-cmd@v1 # TODO: ask admin to allow pinning commits @@ -120,7 +128,12 @@ jobs: CIBW_BUILD: ${{ env.CIBW_BUILD }} CIBW_ARCHS_LINUX: "native" CIBW_BUILD_VERBOSITY: 1 - CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel" + # Install the sha256-pinned, security-fixed pip first: the pip that + # cibuildwheel provides vendors a certifi bundle that still trusts the + # compromised eMudhra/emSign intermediates, and it would otherwise + # fetch the build dependencies (and delvewheel) with that bundle. + CIBW_BEFORE_BUILD_LINUX: 'python -m pip install "${{ env.HARDENED_PIP_REQUIREMENT }}"' + CIBW_BEFORE_BUILD_WINDOWS: 'python -m pip install "${{ env.HARDENED_PIP_REQUIREMENT }}" && python -m pip install delvewheel' CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --namespace-pkg cuda -w {dest_dir} {wheel}" CIBW_ENVIRONMENT: > CUDA_PYTHON_PARALLEL_LEVEL=${{ env.CUDA_PYTHON_PARALLEL_LEVEL }} @@ -128,6 +141,7 @@ jobs: with: package-dir: ./cuda_core/ output-dir: ${{ env.CUDA_CORE_ARTIFACTS_DIR }} + python-path: ${{ steps.host-python.outputs.python-path }} - name: List the cuda.core artifacts directory run: | @@ -170,12 +184,18 @@ jobs: CIBW_ENVIRONMENT_WINDOWS: > CUDA_HOME="$(cygpath -w ${{ env.CUDA_PATH }})" CUDA_PYTHON_PARALLEL_LEVEL=${{ env.CUDA_PYTHON_PARALLEL_LEVEL }} - CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel" + # Install the sha256-pinned, security-fixed pip first: the pip that + # cibuildwheel provides vendors a certifi bundle that still trusts the + # compromised eMudhra/emSign intermediates, and it would otherwise + # fetch the build dependencies (and delvewheel) with that bundle. + CIBW_BEFORE_BUILD_LINUX: 'python -m pip install "${{ env.HARDENED_PIP_REQUIREMENT }}"' + CIBW_BEFORE_BUILD_WINDOWS: 'python -m pip install "${{ env.HARDENED_PIP_REQUIREMENT }}" && python -m pip install delvewheel' CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --namespace-pkg cuda -w {dest_dir} {wheel}" CIBW_ENABLE: "cpython-prerelease" with: package-dir: ./cuda_bindings/ output-dir: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }} + python-path: ${{ steps.host-python.outputs.python-path }} - name: List the cuda.bindings artifacts directory run: | @@ -227,15 +247,9 @@ jobs: if-no-files-found: error - name: Set up Python - id: setup-python2 - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + uses: ./.github/actions/setup-hardened-python with: python-version: ${{ matrix.python-version }} - # TODO: remove allow-prereleases once 3.15 is officially supported - allow-prereleases: ${{ startsWith(matrix.python-version, '3.15') }} - - - name: Harden pip - uses: ./.github/actions/harden-pip - name: verify free-threaded build if: endsWith(matrix.python-verison, 't') @@ -243,10 +257,11 @@ jobs: - name: Set up Python include paths run: | + include="$(python -c "import sysconfig; print(sysconfig.get_paths()['include'])")" if [[ "${{ inputs.host-platform }}" == linux* ]]; then - echo "CPLUS_INCLUDE_PATH=${Python3_ROOT_DIR}/include/python${{ matrix.python-version }}" >> $GITHUB_ENV + echo "CPLUS_INCLUDE_PATH=${include}" >> $GITHUB_ENV elif [[ "${{ inputs.host-platform }}" == win* ]]; then - echo "CL=/I\"${Python3_ROOT_DIR}\include\python${{ matrix.python-version }}\"" >> $GITHUB_ENV + echo "CL=/I\"${include}\"" >> $GITHUB_ENV fi # For caching echo "PY_EXT_SUFFIX=$(python -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))")" >> $GITHUB_ENV diff --git a/.github/workflows/install_gpu_driver.ps1 b/.github/workflows/install_gpu_driver.ps1 index 8b94901989e..693ad013f7e 100644 --- a/.github/workflows/install_gpu_driver.ps1 +++ b/.github/workflows/install_gpu_driver.ps1 @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # SPDX-License-Identifier: Apache-2.0 @@ -10,6 +10,11 @@ function Install-Driver { $url = 'https://us.download.nvidia.com/tesla/572.13/572.13-data-center-tesla-desktop-win10-win11-64bit-dch-international.exe'; $file_dir = 'C:\NVIDIA-Driver\572.13-data-center-tesla-desktop-win10-win11-64bit-dch-international.exe'; $install_args = '/s /noeula /noreboot'; + # sha256 of the installer above. Whoever changes $url owns this value: + # compute it on a machine with an up-to-date trust store (for example + # `curl -fsSL | sha256sum`) and treat a CI mismatch as possible + # tampering. Never copy the "got" value from a job log into this file. + $expected_sha256 = 'e6663c8ca3685da149d357b03b89e0946d862a41788492a4c06f34744a2433a5'; # Create the folder for the driver download if (!(Test-Path -Path 'C:\NVIDIA-Driver')) { @@ -25,6 +30,14 @@ function Install-Driver { $ProgressPreference = $ProgressPreference_tmp Write-Output 'Download complete!' + # Verify the installer against the pinned sha256 before running it as admin. + $actual_sha256 = (Get-FileHash -Algorithm SHA256 -Path $file_dir).Hash.ToLower() + if ($actual_sha256 -ne $expected_sha256) { + Write-Error "Driver installer sha256 mismatch: expected $expected_sha256, got $actual_sha256" + exit 1 + } + Write-Output "Driver installer sha256 verified: $actual_sha256" + # Install the file with the specified path from earlier Write-Output 'Running the driver installer...' Start-Process -FilePath $file_dir -ArgumentList $install_args -Wait diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 019861ee832..9d408f88ea2 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -215,17 +215,9 @@ jobs: - name: Set up Python ${{ matrix.PY_VER }} - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + uses: ./.github/actions/setup-hardened-python with: python-version: ${{ matrix.PY_VER }} - # TODO: remove allow-prereleases once 3.15 is officially supported - allow-prereleases: ${{ startsWith(matrix.PY_VER, '3.15') }} - env: - # we use self-hosted runners on which setup-python behaves weirdly... - AGENT_TOOLSDIRECTORY: "/opt/hostedtoolcache" - - - name: Harden pip - uses: ./.github/actions/harden-pip - name: Set up mini CTK if: ${{ matrix.LOCAL_CTK == '1' }} diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 9ed697fc4b8..655e66c0b6c 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -205,14 +205,9 @@ jobs: - name: Set up Python ${{ matrix.PY_VER }} - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + uses: ./.github/actions/setup-hardened-python with: python-version: ${{ matrix.PY_VER }} - # TODO: remove allow-prereleases once 3.15 is officially supported - allow-prereleases: ${{ startsWith(matrix.PY_VER, '3.15') }} - - - name: Harden pip - uses: ./.github/actions/harden-pip - name: Verify LongPathsEnabled run: | diff --git a/ci/tools/fetch_ctk_redistrib.py b/ci/tools/fetch_ctk_redistrib.py new file mode 100644 index 00000000000..ec34d8f1d4c --- /dev/null +++ b/ci/tools/fetch_ctk_redistrib.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +"""Resolve mini-CTK components from NVIDIA redistrib metadata.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import sys +import urllib.error +import urllib.parse +import urllib.request +from pathlib import Path +from typing import Any + +HOST_PLATFORM_TO_SUBDIR: dict[str, str] = { + "linux-64": "linux-x86_64", + "linux-aarch64": "linux-sbsa", + "win-64": "windows-x86_64", + "win-arm64": "windows-arm64", +} + +# CTK 13.3.0 renamed the redistrib key from cuda_cccl to cccl. +COMPONENT_ALIASES: dict[str, tuple[str, ...]] = { + "cuda_cccl": ("cccl",), +} + +# Known-good sha256 of the redistrib metadata JSON, keyed by CUDA version. +# Per-archive verification is only trustworthy if the JSON that carries the +# archive hashes is itself trusted, so we pin the metadata too. A version that +# is absent here is not blocked -- failing closed would break CI on every new +# CTK -- but `verify-metadata` emits a warning; add the version's hash below as +# it enters the matrix to pin it. Regenerate with: +# curl -fsSL \ +# https://developer.download.nvidia.com/compute/cuda/redist/redistrib_.json \ +# | sha256sum +KNOWN_REDISTRIB_SHA256: dict[str, str] = { + "11.8.0": "941a950a4ab3b95311c50df7b3c8bca973e0cdda76fc2f4b456d2d5e4dac0281", + "12.0.1": "14edfe941958212d184fac97890ddd2e5eb05383ff3601e27f37a8514a215fef", + "12.6.3": "9c598598457a6463eb92889080c16b2b9dc04150e501b8bfc1536d403ba70aaf", + "12.9.1": "8335301010b0023ee1ff61eb11e2600ca62002d76780de4089011ad77e0c7630", + "13.0.1": "9c494bc13b34e8fbcad083a6486d185b0906068b821722502edf9d0e3bd14096", + "13.0.2": "fce66717a81c510ffeb89ecc3e79849ab34af3b80139f750876d9033e31d71c2", + "13.4.2": "015b97aa3977d4d0bade1631b226b6d4cbe48751cc841aad9193295df7f9047a", +} + + +def host_platform_to_subdir(host_platform: str) -> str: + try: + return HOST_PLATFORM_TO_SUBDIR[host_platform] + except KeyError as exc: + raise ValueError(f"unsupported host-platform: {host_platform!r}") from exc + + +def split_components(components: str) -> list[str]: + return [component for component in components.split(",") if component] + + +def filter_static_components( + components: list[str], host_platform: str, cuda_version: str +) -> list[str]: + try: + cuda_major = int(cuda_version.split(".", 1)[0]) + except ValueError as exc: + raise ValueError(f"invalid cuda-version: {cuda_version!r}") from exc + + filtered = [] + for component in components: + if component == "libnvjitlink" and cuda_major < 12: + continue + if component in {"cuda_crt", "libnvvm"} and cuda_major < 13: + continue + if component == "libcufile" and host_platform.startswith("win-"): + continue + filtered.append(component) + return filtered + + +def validate_metadata_url(metadata_url: str) -> str: + parsed = urllib.parse.urlsplit(metadata_url) + if parsed.scheme != "https" or not parsed.netloc: + raise ValueError(f"metadata URL must be an https URL: {metadata_url!r}") + return metadata_url + + +def load_metadata( + *, metadata_path: str | None, metadata_url: str | None +) -> dict[str, Any]: + if (metadata_path is None) == (metadata_url is None): + raise ValueError("exactly one of --metadata-path or --metadata-url is required") + + if metadata_path is not None: + return json.loads(Path(metadata_path).read_text(encoding="utf-8")) + + assert metadata_url is not None + metadata_url = validate_metadata_url(metadata_url) + with urllib.request.urlopen(metadata_url) as response: # noqa: S310 # nosec B310 - scheme is restricted to https above + return json.load(response) + + +def resolve_component_name(metadata: dict[str, Any], component: str) -> str: + if component in metadata: + return component + + for alias in COMPONENT_ALIASES.get(component, ()): + if alias in metadata: + return alias + + return component + + +def filter_components( + metadata: dict[str, Any], + *, + host_platform: str, + cuda_version: str, + components: str, +) -> tuple[list[str], list[str]]: + ctk_subdir = host_platform_to_subdir(host_platform) + filtered = [] + skipped = [] + for component in filter_static_components( + split_components(components), host_platform, cuda_version + ): + resolved_component = resolve_component_name(metadata, component) + if ctk_subdir in metadata.get(resolved_component, {}): + filtered.append(resolved_component) + else: + skipped.append(component) + return filtered, skipped + + +def get_component_subdir_info( + metadata: dict[str, Any], *, host_platform: str, component: str +) -> tuple[str, dict[str, Any]]: + ctk_subdir = host_platform_to_subdir(host_platform) + component = resolve_component_name(metadata, component) + component_info = metadata.get(component) + if component_info is None: + raise KeyError(f"unknown CTK component {component!r}") + + subdir_info = component_info.get(ctk_subdir) + if subdir_info is None: + raise KeyError( + f"CTK component {component!r} is not available for redistrib subdir {ctk_subdir!r}" + ) + return ctk_subdir, subdir_info + + +def get_component_relative_path( + metadata: dict[str, Any], *, host_platform: str, component: str +) -> str: + ctk_subdir, subdir_info = get_component_subdir_info( + metadata, host_platform=host_platform, component=component + ) + relative_path = subdir_info.get("relative_path") + if relative_path is None: + raise KeyError( + f"CTK component {component!r} for redistrib subdir {ctk_subdir!r} is missing 'relative_path'" + ) + return relative_path + + +def get_component_sha256( + metadata: dict[str, Any], *, host_platform: str, component: str +) -> str: + ctk_subdir, subdir_info = get_component_subdir_info( + metadata, host_platform=host_platform, component=component + ) + sha256 = subdir_info.get("sha256") + if not sha256: + raise KeyError( + f"CTK component {component!r} for redistrib subdir {ctk_subdir!r} is missing 'sha256'" + ) + return sha256 + + +def compute_file_sha256(path: str) -> str: + digest = hashlib.sha256() + with open(path, "rb") as handle: + for chunk in iter(lambda: handle.read(1 << 20), b""): + digest.update(chunk) + return digest.hexdigest() + + +def verify_metadata_sha256(*, cuda_version: str, metadata_path: str) -> int: + """Verify the redistrib JSON against the pinned hash for its CUDA version. + + Returns a process exit code: 1 on a mismatch (fail closed), 0 when the hash + matches or when the version is not pinned yet (warn only). + """ + actual = compute_file_sha256(metadata_path) + expected = KNOWN_REDISTRIB_SHA256.get(cuda_version) + if expected is None: + print( + f"WARNING: no pinned redistrib sha256 for CUDA {cuda_version!r}; got {actual}. " + f"Add it to KNOWN_REDISTRIB_SHA256 in {Path(__file__).name} to pin it.", + file=sys.stderr, + ) + return 0 + if actual != expected: + print( + f"ERROR: redistrib metadata sha256 mismatch for CUDA {cuda_version!r}: expected {expected}, got {actual}", + file=sys.stderr, + ) + return 1 + print(f"OK: redistrib metadata sha256 verified for CUDA {cuda_version}") + return 0 + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + subparsers = parser.add_subparsers(dest="command", required=True) + + filter_parser = subparsers.add_parser("filter-components") + filter_parser.add_argument("--host-platform", required=True) + filter_parser.add_argument("--cuda-version", required=True) + filter_parser.add_argument("--components", required=True) + filter_parser.add_argument("--metadata-path") + filter_parser.add_argument("--metadata-url") + + relpath_parser = subparsers.add_parser("component-relative-path") + relpath_parser.add_argument("--host-platform", required=True) + relpath_parser.add_argument("--component", required=True) + relpath_parser.add_argument("--metadata-path") + relpath_parser.add_argument("--metadata-url") + + sha_parser = subparsers.add_parser("component-sha256") + sha_parser.add_argument("--host-platform", required=True) + sha_parser.add_argument("--component", required=True) + sha_parser.add_argument("--metadata-path") + sha_parser.add_argument("--metadata-url") + + verify_parser = subparsers.add_parser("verify-metadata") + verify_parser.add_argument("--cuda-version", required=True) + verify_parser.add_argument("--metadata-path", required=True) + + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + + try: + # verify-metadata hashes the file directly; it does not parse the JSON. + if args.command == "verify-metadata": + return verify_metadata_sha256( + cuda_version=args.cuda_version, metadata_path=args.metadata_path + ) + + metadata = load_metadata( + metadata_path=args.metadata_path, metadata_url=args.metadata_url + ) + + if args.command == "filter-components": + filtered, skipped = filter_components( + metadata, + host_platform=args.host_platform, + cuda_version=args.cuda_version, + components=args.components, + ) + for component in skipped: + print( + f"Skipping unsupported CTK component {component!r} for host-platform {args.host_platform!r}", + file=sys.stderr, + ) + print(",".join(filtered)) + return 0 + + if args.command == "component-relative-path": + print( + get_component_relative_path( + metadata, + host_platform=args.host_platform, + component=args.component, + ) + ) + return 0 + + if args.command == "component-sha256": + print( + get_component_sha256( + metadata, + host_platform=args.host_platform, + component=args.component, + ) + ) + return 0 + + raise AssertionError(f"unexpected command: {args.command!r}") + except ( + ValueError, + KeyError, + OSError, + urllib.error.URLError, + json.JSONDecodeError, + ) as exc: + print(f"ERROR: {exc}", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ci/tools/tests/test_fetch_ctk_redistrib.py b/ci/tools/tests/test_fetch_ctk_redistrib.py new file mode 100644 index 00000000000..bfe7e9d5b31 --- /dev/null +++ b/ci/tools/tests/test_fetch_ctk_redistrib.py @@ -0,0 +1,159 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +import pytest + +sys.path.insert(0, str(Path(__file__).parent.parent)) +from fetch_ctk_redistrib import ( + compute_file_sha256, + get_component_relative_path, + get_component_sha256, + main, + verify_metadata_sha256, +) + +# Minimal redistrib-shaped metadata. "cccl" exercises the cuda_cccl -> cccl +# alias; "no_sha" lacks the sha256 field. +FAKE_METADATA = { + "cuda_nvcc": { + "linux-x86_64": { + "relative_path": "cuda_nvcc/linux-x86_64/cuda_nvcc-linux-x86_64-13.0.0-archive.tar.xz", + "sha256": "a" * 64, + }, + }, + "cccl": { + "linux-x86_64": { + "relative_path": "cccl/linux-x86_64/cccl-linux-x86_64-13.0.0-archive.tar.xz", + "sha256": "b" * 64, + }, + }, + "no_sha": { + "linux-x86_64": { + "relative_path": "no_sha/linux-x86_64/no_sha.tar.xz", + }, + }, +} + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_get_component_sha256_returns_hash(): + assert ( + get_component_sha256( + FAKE_METADATA, host_platform="linux-64", component="cuda_nvcc" + ) + == "a" * 64 + ) + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_get_component_sha256_resolves_alias(): + # cuda_cccl is absent; it must resolve to the renamed cccl key. + assert ( + get_component_sha256( + FAKE_METADATA, host_platform="linux-64", component="cuda_cccl" + ) + == "b" * 64 + ) + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_get_component_sha256_unknown_component_raises(): + with pytest.raises(KeyError): + get_component_sha256( + FAKE_METADATA, host_platform="linux-64", component="does_not_exist" + ) + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_get_component_sha256_unavailable_subdir_raises(): + with pytest.raises(KeyError): + get_component_sha256( + FAKE_METADATA, host_platform="win-64", component="cuda_nvcc" + ) + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_get_component_sha256_missing_field_raises(): + with pytest.raises(KeyError): + get_component_sha256( + FAKE_METADATA, host_platform="linux-64", component="no_sha" + ) + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_get_component_relative_path_still_resolves(): + assert get_component_relative_path( + FAKE_METADATA, host_platform="linux-64", component="cuda_nvcc" + ).endswith("cuda_nvcc-linux-x86_64-13.0.0-archive.tar.xz") + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_verify_metadata_match(tmp_path, monkeypatch): + f = tmp_path / "redistrib.json" + f.write_bytes(b"pinned-metadata") + monkeypatch.setitem( + sys.modules["fetch_ctk_redistrib"].KNOWN_REDISTRIB_SHA256, + "1.2.3", + compute_file_sha256(str(f)), + ) + assert verify_metadata_sha256(cuda_version="1.2.3", metadata_path=str(f)) == 0 + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_verify_metadata_mismatch_fails_closed(tmp_path, monkeypatch): + f = tmp_path / "redistrib.json" + f.write_bytes(b"tampered-metadata") + monkeypatch.setitem( + sys.modules["fetch_ctk_redistrib"].KNOWN_REDISTRIB_SHA256, + "1.2.3", + "f" * 64, + ) + assert verify_metadata_sha256(cuda_version="1.2.3", metadata_path=str(f)) == 1 + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_verify_metadata_unknown_version_warns(tmp_path, capsys): + f = tmp_path / "redistrib.json" + f.write_bytes(b"whatever") + # An unpinned version must not fail closed (it would break CI on every new + # CTK), but it must emit a warning. + assert verify_metadata_sha256(cuda_version="99.9.9", metadata_path=str(f)) == 0 + assert "WARNING" in capsys.readouterr().err + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_main_component_sha256(tmp_path, capsys): + f = tmp_path / "redistrib.json" + f.write_text(json.dumps(FAKE_METADATA), encoding="utf-8") + rc = main( + [ + "component-sha256", + "--host-platform", + "linux-64", + "--component", + "cuda_nvcc", + "--metadata-path", + str(f), + ] + ) + assert rc == 0 + assert capsys.readouterr().out.strip() == "a" * 64 + + +@pytest.mark.agent_authored(model="claude-opus-4.8") +def test_main_verify_metadata_mismatch_returns_1(tmp_path, monkeypatch): + f = tmp_path / "redistrib.json" + f.write_bytes(b"tampered") + monkeypatch.setitem( + sys.modules["fetch_ctk_redistrib"].KNOWN_REDISTRIB_SHA256, + "1.2.3", + "f" * 64, + ) + rc = main(["verify-metadata", "--cuda-version", "1.2.3", "--metadata-path", str(f)]) + assert rc == 1