{"id":"CVE-2026-114096","kind":"vulnerability","aliases":["CVE-2026-114096"],"related":[],"title":"Dulwich: symlink following in checkout lets crafted repos plant hooks","description":"Dulwich from 0.24.0 before 1.2.8 contains a symlink following vulnerability in porcelain.checkout(paths=[...]) that allows attackers to write arbitrary files by abusing raw os.open without O_NOFOLLOW. Attackers can craft a repository where a worktree symlink points to .git/hooks/post-checkout, so restoring the file from a tag writes a malicious hook for code execution.","summary":"Dulwich, a pure-Python Git implementation, follows a worktree symlink during porcelain.checkout(paths=[...]) because it opens files without O_NOFOLLOW. A crafted repository can point a symlink at .git/hooks/post-checkout, so restoring a file writes a malicious hook that runs code.","severity":"high","cvss":7.8,"epss":0.00155,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["ci","dulwich","git-tooling","package","python"],"not_affected_if":["trusted-repos-only","version-1.2.8-or-later"],"how_to_check":"- Run `pip show dulwich` (or check your lockfile) and see whether the version is between `0.24.0` and `1.2.8`.\n- Find code that calls `porcelain.checkout` with a `paths=` argument on repositories you did not create.","fix":"- Upgrade the dulwich package to `1.2.8` or later.\n- Until upgraded, avoid calling `porcelain.checkout(paths=[...])` on untrusted repositories.","status":"open","published_at":"2026-10-21T01:17:34+00:00","first_seen_at":"2026-10-23T21:57:28+00:00","triaged_at":"2026-10-25T03:08:27+00:00","updated_at":"2026-10-25T03:08:27+00:00","category":"package","confidence":0.6,"triage":{"at":"2026-10-25T03:08:27Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade the dulwich package to `1.2.8` or later.\n- Until upgraded, avoid calling `porcelain.checkout(paths=[...])` on untrusted repositories.","reach":"unknown","title":"Dulwich: symlink following in checkout lets crafted repos plant hooks","impact":"high","summary":"Dulwich, a pure-Python Git implementation, follows a worktree symlink during porcelain.checkout(paths=[...]) because it opens files without O_NOFOLLOW. A crafted repository can point a symlink at .git/hooks/post-checkout, so restoring a file writes a malicious hook that runs code.","category":"package","nicknames":[],"who_cares":["python","dulwich","git-tooling","ci"],"confidence":0.6,"needs_auth":"no","worst_case":"Attacker plants a hook that runs code when the repository is checked out","analyst_note":"Confirm whether the trigger needs a user to run checkout on the hostile repo and whether other porcelain functions are affected; check the NVD page https://nvd.nist.gov/vuln/detail/CVE-2026-114096.","how_to_check":"- Run `pip show dulwich` (or check your lockfile) and see whether the version is between `0.24.0` and `1.2.8`.\n- Find code that calls `porcelain.checkout` with a `paths=` argument on repositories you did not create.","needs_analyst":true,"not_affected_if":["trusted-repos-only","version-1.2.8-or-later"],"who_is_affected":"Services or tools that clone or check out Git repositories from untrusted sources using Dulwich's porcelain checkout with a paths argument are exposed, because the attacker's repository controls the symlinks. Applications that only work with repositories they create themselves, or that use Dulwich only for reading objects, are less exposed. The sources do not say whether other Dulwich APIs share the flaw.","user_interaction":"yes","needs_special_setup":"unknown","severity_if_unknown":"high"},"cost_usd":0.000688,"input_tokens":3412,"output_tokens":693,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-114096':13A,16A '-2026':12A,15A '0.24.0':67C '1.2.8':69C 'abus':86C 'allow':79C 'arbitrari':83C 'attack':80C,92C 'checkout':5A 'ci':17B 'code':64B,116C 'contain':70C 'craft':7A,46B,94C 'cve':11A,14A 'dulwich':1A,18B,24B,65C 'execut':117C 'file':41B,57B,84C,107C 'follow':3A,31B,73C 'git':20B,29B 'git-tool':19B 'git/hooks/post-checkout':53B,103C 'hook':10A,61B,114C 'implement':30B 'let':6A 'malici':60B,113C 'nofollow':44B,91C 'o':43B,90C 'open':40B 'os.open':88C 'packag':22B 'path':37B,77C 'plant':9A 'point':49B,101C 'porcelain.checkout':36B,76C 'pure':27B 'pure-python':26B 'python':23B,28B 'raw':87C 'repo':8A 'repositori':47B,96C 'restor':55B,105C 'run':63B 'symlink':2A,34B,51B,72C,100C 'tag':110C 'tool':21B 'vulner':74C 'without':42B,89C 'worktre':33B,99C 'write':58B,82C,111C","nicknames":[],"mitigations":[],"who_affected":"Services or tools that clone or check out Git repositories from untrusted sources using Dulwich's porcelain checkout with a paths argument are exposed, because the attacker's repository controls the symlinks. Applications that only work with repositories they create themselves, or that use Dulwich only for reading objects, are less exposed. The sources do not say whether other Dulwich APIs share the flaw.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-21T01:17:34+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"disclosure@vulncheck.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-114096","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-114096","severity":null,"published_at":"2026-10-21T01:17:34+00:00","modified_at":"2026-10-21T01:17:35+00:00","first_seen_at":"2026-10-23T21:57:28+00:00","fetched_at":"2026-10-23T22:29:01+00:00","note":null},{"source":"epss","external_id":"CVE-2026-114096","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-114096","severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-24T13:15:54+00:00","fetched_at":"2026-10-24T13:15:54+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}