GHSA-555P-6GRF-MH7F

Vulnerability from github – Published: 2026-06-08 23:04 – Updated: 2026-06-11 14:07
VLAI
Summary
Dulwich doesn't sanitize commit subjects in `porcelain.format_patch`
Details

Impact

dulwich.porcelain.format_patch(outdir=...) derives each patch filename from the commit's subject line. Prior to this fix, get_summary only replaced spaces with dashes - path separators (/, ), parent-directory components (..), and other filename-hostile characters (e.g. :) were preserved verbatim and passed straight into os.path.join(outdir, f"{i:04d}-{summary}.patch").

A malicious commit subject could therefore direct the generated patch file outside the requested outdir. Reduced examples:

  • x/../../x produced /0001-x/../../x.patch, resolving two directories above outdir.
  • x....\x produced the equivalent escape on Windows, here \ is also a path separator.

Related issues from the same root cause:

  • Subjects containing characters that are illegal in Windows filenames (e.g. :) caused format_patch to fail outright on Windows, where git would have succeeded.
  • Very long subjects produced excessively long filenames that could exceed filesystem limits; git truncates them.

Anyone calling porcelain.format_patch (or the dulwich format-patch CLI) against untrusted commits - for example, a service that runs format-patch over user-supplied repositories or pull requests - could have patch files written to attacker-chosen locations within the process's write permissions.

Patches

Fixed in Dulwich 1.2.5. Users should upgrade.

dulwich.patch.get_summary now mirrors git's format_sanitized_subject: only [A-Za-z0-9._] are kept, runs of other characters collapse to a single -, consecutive . collapse to a single ., trailing ./- are stripped, and the result is length-limited. This makes the returned string safe to embed as a filename component, so format_patch can no longer be steered out of outdir via the commit subject.

Workarounds

Until upgrading, callers that pass untrusted commits to porcelain.format_patch can:

  • Use stdout=True and write the patch to a destination they control, rather than letting format_patch choose the filename.
  • Validate the chosen path before opening - e.g. compare os.path.realpath(returned_path) against os.path.realpath(outdir) and reject any patch whose resolved path is not inside outdir.
  • Pre-screen commits and refuse to format any whose subject's first line contains /, \, .., or other characters that are not safe on the target filesystem.

Resources

  • Fix commit: https://github.com/jelmer/dulwich/commit/c2446e51b
  • Affected API: dulwich.porcelain.format_patch / dulwich format-patch
  • Reference behavior: git's format_sanitized_subject in pretty.c
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "dulwich"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.24.0"
            },
            {
              "fixed": "1.2.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47712"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-08T23:04:48Z",
    "nvd_published_at": "2026-06-10T23:16:48Z",
    "severity": "LOW"
  },
  "details": "### Impact\n\ndulwich.porcelain.format_patch(outdir=...) derives each patch filename from the commit\u0027s subject line. Prior to this fix, get_summary only replaced spaces with dashes - path separators (/, \\),   parent-directory components (..), and   other filename-hostile characters (e.g. :)  were preserved verbatim and passed   straight into os.path.join(outdir,   f\"{i:04d}-{summary}.patch\").\n\nA malicious commit subject could therefore direct the generated patch file outside the requested outdir. Reduced examples:\n\n- x/../../x produced \u003coutdir\u003e/0001-x/../../x.patch, resolving\n  two directories above outdir.\n- x\\..\\..\\x produced the equivalent escape on Windows, here \\ is also a path separator.\n\nRelated issues from the same root cause:\n\n- Subjects containing characters that are illegal in Windows filenames (e.g. :) caused format_patch to fail outright on  Windows, where git would have succeeded.\n- Very long subjects produced excessively long filenames that could exceed filesystem limits; git truncates them.\n\nAnyone calling porcelain.format_patch (or the dulwich format-patch CLI) against untrusted commits - for example, a service that runs format-patch over user-supplied repositories or pull requests - could have patch files written to attacker-chosen locations within the process\u0027s write permissions.\n\n### Patches\n\nFixed in Dulwich 1.2.5. Users should upgrade.\n\n dulwich.patch.get_summary now mirrors git\u0027s format_sanitized_subject: only `[A-Za-z0-9._]` are kept, runs of other characters collapse to a single -, consecutive . collapse to a single ., trailing ./- are stripped, and the result is length-limited. This makes the returned string safe to embed as a filename component, so format_patch can no longer be steered out of outdir via the commit subject.\n\n###  Workarounds\n\nUntil upgrading, callers that pass untrusted commits to   porcelain.format_patch can:\n\n- Use stdout=True and write the patch to a destination they control, rather than letting format_patch choose the filename.\n- Validate the chosen path before opening - e.g. compare os.path.realpath(returned_path) against  os.path.realpath(outdir) and reject any patch whose resolved path is not inside outdir.\n- Pre-screen commits and refuse to format any whose subject\u0027s first line contains /, \\, .., or other characters that are not safe on the target filesystem.\n\n### Resources\n\n- Fix commit: https://github.com/jelmer/dulwich/commit/c2446e51b\n- Affected API: dulwich.porcelain.format_patch / dulwich format-patch\n- Reference behavior: git\u0027s format_sanitized_subject in pretty.c",
  "id": "GHSA-555p-6grf-mh7f",
  "modified": "2026-06-11T14:07:14Z",
  "published": "2026-06-08T23:04:48Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/jelmer/dulwich/security/advisories/GHSA-555p-6grf-mh7f"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47712"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jelmer/dulwich/commit/c2446e51b"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/jelmer/dulwich"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jelmer/dulwich/releases/tag/dulwich-1.2.5"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dulwich doesn\u0027t sanitize commit subjects in `porcelain.format_patch`"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…