Skip to content

Releases: jelmer/dulwich

dulwich-1.2.17

Choose a tag to compare

@jelmer jelmer released this 03 Oct 22:43
  • Define __all__ in all modules, listing the public names each module defines. (Jelmer VernooΔ³)
  • Deprecate importing LOCAL_TAG_PREFIX, SYMREF, check_ref_format, read_packed_refs, read_packed_refs_with_peeled and write_packed_refs from dulwich.repo; import them from dulwich.refs instead. Likewise BundleList, fetch_bundle_uri and parse_bundle_list should be imported from dulwich.bundle_uri rather than dulwich.client. (Jelmer VernooΔ³)
  • Restore dulwich.index.SHA1Reader and dulwich.index.SHA1Writer, which were dropped in 1.2.16, as deprecated aliases for the classes in dulwich.pack. (Jelmer VernooΔ³)
  • Refuse to write a loose ref through a symref whose target escapes the ref store. (Kartik Kenchi, Jelmer VernooΔ³)

dulwich-1.2.16

Choose a tag to compare

@jelmer jelmer released this 03 Oct 14:13
  • Add PackIndex.object_sha_at_position to look up an object by its position in the sorted index, and use it when loading a .bitmap instead of re-scanning the index for every entry, which made loading quadratic in the pack size, unlike git. (Kartik Kenchi)
  • Fix applying patches without content changes, such as mode changes and added or deleted empty files. They have no ---/+++ lines and failed with "Patch has no file path". (Jelmer VernooΔ³)
  • Fix applying binary patches produced by git diff --binary. Their paths are now taken from the diff --git line, literal data is inflated, base85 line lengths are decoded correctly and binary deletions remove the file. (Jelmer VernooΔ³)
  • Support delta binary patches, binary changes combined with a rename or copy and reverse application of binary patches in apply_patches. (Jelmer VernooΔ³)
  • Unquote C-style quoted file names (as git emits for names with special or non-ASCII characters) when parsing patches. (Jelmer VernooΔ³)
  • SECURITY: Validate index paths in sparse checkout, mixed reset, lfs_pull and lfs_migrate, so that a malicious repository can no longer write files outside the work tree via .. entries or symlinks. (Jelmer VernooΔ³, reported by Choudhry Shehryar)
  • SECURITY: Don't write through symlinks in apply_patches. A tracked symlink such as trap -> .git/hooks/pre-commit was followed when writing, so porcelain.am/apply_patch could install a hook. Symlinks are now patched as links, like git does, and a patch whose mode doesn't match the type in the work tree or that adds a file over an existing path is refused. (Jelmer VernooΔ³, reported by @manus-pi)
  • Apply a mode change in build_file_from_blob when the content is unchanged. (Jelmer VernooΔ³)
  • Fix parsing of a rename or copy without content changes followed by another patch, which swallowed the next patch. (Jelmer VernooΔ³)
  • Honour \ No newline at end of file markers when applying patches, which previously made patches to files without a trailing newline fail. (Jelmer VernooΔ³)
  • Ignore a multi-pack-index entry whose pack has been removed when answering whether an object is present. After a prune the stale index made sha in repo.object_store disagree with repo.object_store[sha]. (Kartik Kenchi)
  • Don't follow a symlink when reading .gitignore or .gitattributes from the work tree. A tree could point either name at a file outside the repository and have its contents drive dulwich. (Kartik Kenchi)
  • Honour GIT_OPTIONAL_LOCKS=0 in dulwich status, skipping the index stat-cache refresh that would otherwise lock the index. (Jelmer VernooΔ³, #1861)
  • Preserve original URL in remote origin configuration when cloning, matching C git behavior. (Suprovo Ghosh, #2428)
  • Report conflicts in criss-cross merges where the merge bases disagree on a file. The recursive merge silently kept one base's blob as the virtual base, so the final three-way merge published the other side's content without recording a conflict. (Jelmer VernooΔ³, #2419)
  • Record merge conflicts in the index with stages 1/2/3 and write MERGE_HEAD/MERGE_MSG when porcelain.merge leaves conflicts, so the working tree matches git's state and git commit can finish the merge. (Jelmer VernooΔ³)
  • Preserve index entries that differ only by case when loading the index, resetting mixed, or restoring a stashed index tree under core.ignorecase. (Jelmer VernooΔ³, #2434)
  • Fix a crash in dulwich log <path> on merge commits where the path is unchanged relative to one parent. tree_changes_for_merge reports None for such parents, which the walker and the --name-status and --name-only output wrongly assumed to be a TreeChange. (Jelmer VernooΔ³, #2412)
  • dulwich log <path> now applies git's default history simplification. Pass --full-history for the old behavior. Walker and get_walker gain a simplify_history flag. (Jelmer VernooΔ³, #2414)
  • Carry the repository's object format through the index and the work tree. add and commit on a SHA-256 repository wrote SHA-1 identities into the index, trees and refs, leaving a repository neither dulwich nor git could read back. (Jelmer VernooΔ³, #2416)
  • Honour the eol gitattribute. Line ending conversion is now resolved per path from the text/crlf and eol attributes, falling back to core.autocrlf and core.eol only where the attributes are silent, so eol=crlf and eol=lf take precedence over the configuration as they do in git. (Jelmer VernooΔ³, #2403)
  • Write carriage returns in configuration values literally rather than as a \r escape. (Jelmer VernooΔ³)
  • Strip leading blank lines in stripspace in a single pass. The previous pop(0) loop made an all-blank input O(n^2); it is now linear like git. (Kartik Kenchi)

dulwich-1.2.15

Choose a tag to compare

@jelmer jelmer released this 14 Sep 21:04
  • Detect delta cycles in Pack.resolve_object: a crafted pack with REF_DELTA objects that name each other sent get_raw into an unbounded loop. Such chains now raise DeltaCycle.
  • Fix porcelain.clean when the target directory and the repository path are spelled differently, such as via a relative path or a symlink. (Jelmer VernooΔ³)
  • Memoize tag peeling on the object store, so refs sharing an annotated tag chain no longer re-walk it once per ref. show_ref --dereference and the ref advertisement were quadratic. (Jelmer VernooΔ³, #2406)
  • Give a .gitignore in a subdirectory precedence over one closer to the root, matching git. A negation in a deeper file no longer loses to a rule at the root, and a nested negation no longer re-includes a path whose parent directory stays excluded. (Jelmer VernooΔ³, #2399)
  • Reject reftable tables.list entries that contain a path separator or are absolute, so a hostile repository cannot make a ref lookup open a file outside the reftable directory. (netliomax25-code)
  • Support dulwich commit -C/--reuse-message and -c/--reedit-message to reuse a commit's message, author and author date, optionally editing the message. The committer and new commit ancestry remain independent. (eunwoo song, #1845)
  • List local branches for bare dulwich branch and standalone dulwich branch --list [pattern]. Listing empty repositories or patterns with no matches succeeds without changing refs. (be-student, #1847)
  • Add dulwich commit --author="Name <email>" to override the author of a new or amended commit. (kudala-bharani, #1845)
  • Set branch.<name>.remote and branch.<name>.merge for the branch checked out by a clone, so that a subsequent git pull with no arguments has tracking information. (Jelmer VernooΔ³, #2376)
  • Keep relative paths relative in SSHGitClient.get_url, emitting git's ssh://host/~/path form. Cloning from an scp-style URL like user@host:git/repo.git previously stored ssh://user@host/git/repo.git as the remote URL, which points at a different repository. (Jelmer VernooΔ³, #2375)
  • Name a symlink by its own path in porcelain.path_to_tree_path, rather than by the path of its target. porcelain.status listed a tracked symlink as untracked whenever the file it pointed at was itself untracked or missing, so a modified symlink was reported twice. (Jerry Xiao)
  • Ignore gitignore lines that carry no pattern, such as a bare ! or /. A bare ! previously re-included a directory that an earlier pattern in the same file had ignored. (Jelmer VernooΔ³, #2398)
  • Avoid quadratic cost in PktLineParser.parse, which resliced its remaining buffer once per pkt-line. (Jelmer VernooΔ³, #2408)

dulwich-1.2.14

Choose a tag to compare

@jelmer jelmer released this 28 Aug 14:55

Collapse consecutive ** segments in wildmatch translation, matching git's behavior and avoiding catastrophic regex backtracking on patterns like a/**/**/**/z from untrusted repositories. (netliomax25-code)

dulwich-1.2.13

Choose a tag to compare

@jelmer jelmer released this 24 Aug 10:48
  • Make concurrent Pack.get_raw calls thread-safe by synchronizing
    PackData's resolved-object offset cache.
    (Bojan Zivanovic)

  • Speed up cached PackData.get_object_at lookups by acquiring the
    offset-cache lock directly instead of through a with statement.
    (Bojan Zivanovic)

  • Bound fetch negotiation the way C Git's MAX_IN_VAIN does: give up
    after 256 unacknowledged "have" lines instead of draining the whole
    graph walker into stateless (HTTP) requests. (Bojan Zivanovic, #2343)

  • Add repo.sanitize_user_identity, which builds an identity from a
    name and an email sanitized the way git's fmt_ident does, for
    callers who cannot reject invalid input via check_user_identity.
    (Bojan Zivanovic, #2342)

  • Make concurrent PackData reads thread-safe by mmap-ing pack contents
    and indexing the mapping at explicit offsets instead of sharing the file
    position. New unpack_object_at, read_pack_header_at,
    read_zlib_chunks_at, take_msb_bytes_at and compute_buffer_sha
    read from a buffer; the existing read-callable variants remain for streams.
    (Bojan Zivanovic, Jelmer VernooΔ³)

  • Deduplicate the commit walk in find_shallow and get_depth
    (dulwich.object_store). Both re-expanded a commit once per path that
    reached it, so a merge-heavy history walked in exponential time.
    (netliomax25-code)

  • SECURITY: Don't follow symlinks when writing messages in
    porcelain.format_patch, mbox.split_mbox and mbox.split_maildir.
    A symlink pre-planted at an output filename was followed, writing the
    message outside the output
    directory. (Jelmer VernooΔ³; Reported by wzc)

  • Only reject reserved Windows device names (aux, nul, con, ...)
    when actually running on Windows. C git confines this check to its Windows
    compat layer, so repositories carrying such paths could not be cloned
    elsewhere. (Jelmer VernooΔ³, #2351)

  • Fix ignore and attrs matching for patterns ending in **/. The
    trailing slash was dropped when translating the pattern, so foo/**/ also
    matched foo/ itself and every file directly inside it. Git only ignores
    the directories below foo. (adarshsm)

  • Catch PackFileDisappeared in the bitmap probe in
    get_reachability_provider, which only guarded FileNotFoundError.
    (Jelmer VernooΔ³, #2344)

  • SECURITY: Widen modes for core.sharedRepository as git does rather than
    chmodding to a precomputed one, which left .git/hooks and .git/refs
    world-writable for all. (netliomax25-code, Jelmer VernooΔ³, #2323)

  • parse_shared_repository now returns a SharedPerm, and
    DiskObjectStore, Index and GitFile take a shared_perm
    argument in place of file_mode/dir_mode. (Jelmer VernooΔ³)

  • Fix commit-graph extra edge indexing: the stored value is a position in a
    list of 4-byte entries, not a byte offset, so every octopus merge after
    the first got a wrong parent list. (netliomax25-code)

  • Refresh the mtime of an existing loose object in
    DiskObjectStore.add_object(), so that a concurrent git gc cannot
    prune an object that was just reported as present.
    (Bojan Zivanovic, #2340)

  • HARDEN: Validate shallow object ids received from the remote.
    (netliomax25-code)

  • SECURITY: Refuse patch targets addressing the .git control directory.
    apply_patches (via porcelain.am/apply_patch) previously wrote and
    ran .git/hooks/pre-commit. (Jelmer VernooΔ³, reported by @bhaswanthc)

  • Extend the verify_leading_dirs symlink guard to
    update_working_tree (used by pull, merge and checkout).
    The 1.2.12 fix only covered build_index_from_tree, so a tree pairing a
    symlink x with a descendant x/config could still write through the
    link and overwrite .git/config on pull.
    (Jelmer VernooΔ³, reported by Hugh Lewis)

  • Translate .gitignore/.gitattributes bracket expressions with Git's
    wildmatch() semantics: [^...] negation, POSIX classes, backslash
    escapes and malformed-class handling. ignore and attrs now share
    one translator, the new public dulwich.wildmatch.
    (Vincent Gao, #2326)

  • Always single-quote the repository path in the SSH command, matching git's
    sq_quote(). shlex.quote left paths without shell metacharacters
    bare, which broke cloning from servers that parse the command themselves
    rather than handing it to a shell, such as Bitbucket Server.
    (Jelmer VernooΔ³, #2319)

dulwich-1.2.12

Choose a tag to compare

@jelmer jelmer released this 19 Jul 10:50
  • SECURITY: Refuse to write a checkout entry whose leading path resolves
    through a symlink. `build_index_from_tree` (used by `reset_index` and
    thus by `clone`/`checkout`) materialized a tree in sorted order without
    checking leading components, so a tree pairing a symlink `link` with a
    descendant `link/foo` wrote `foo` through the link to an arbitrary
    absolute path. The same `verify_leading_dirs` guard already used by
    porcelain and stash is now applied here.
    (Jelmer VernooΔ³, reported by Hugh Lewis)

  • Fix `Bundle.store_objects()` silently dropping every OFS_DELTA/REF_DELTA
    object in the bundle's pack instead of resolving it, leaving the target
    object store missing most objects with no error raised. Delta resolution
    now goes through `PackInflater`, matching how packs are ingested
    elsewhere in the object store code.
    (theVinchi, #2312)

dulwich-1.2.11

Choose a tag to compare

@jelmer jelmer released this 16 Jul 14:37

Security and hardening

  • Apply core.protectHFS and core.protectNTFS together when selecting the checkout path-element validator. Previously only the NTFS validator ran when protectNTFS was on (the default), so on macOS an HFS+ spelling of .git using ignorable code points could pass validation and poison .git on checkout.
  • Canonicalize file modes in git archive tarballs, so a crafted tree entry can no longer carry setuid/setgid/sticky bits into an extracted file.
  • Collapse embedded whitespace in reflog messages, so a crafted multi-line commit message can no longer forge additional reflog entries with attacker-chosen SHAs.
  • Verify that a .bitmap index matches the pack it is loaded for, so a stale or swapped-in bitmap can't produce a wrong reachable-object set during fetch negotiation.
  • Parse commit-message trailers in linear time, fixing a cubic blowup where a crafted commit message could tie up CPU for minutes to hours.

Features and fixes

  • Honour core.worktree, so the working tree can live outside the parent of the control directory.
  • Porcelain functions now take an env argument, and read GIT_PROTOCOL, GIT_SSH_COMMAND/GIT_SSH when called as a library rather than only from the CLI (fixes a regression since 1.2.1 where porcelain.clone() silently ignored the SSH variables).
  • porcelain.archive() gained a remote argument.
  • Recurse into subtrees when merging trees, so non-overlapping changes under a shared directory merge cleanly.
  • Clear core.bare when setting up a submodule's working tree.

Security and hardening fixes in this release were contributed by Kartik Kenchi (@netliomax25-code).

dulwich-1.2.10

Choose a tag to compare

@jelmer jelmer released this 07 Jul 00:26
  • Fix regression in 1.2.9 where loose objects whose content inflates to
    more than 8192 bytes failed to parse with `zlib.error: object header
    exceeds maximum size`. (Jelmer VernooΔ³, #2292)

dulwich-1.2.9

Choose a tag to compare

@jelmer jelmer released this 06 Jul 20:48

Highlights of this release:

Security fixes

  • Reject checkout paths whose leading component is a DOS drive-letter prefix on Windows (e.g. C:), which os.path.join would otherwise treat as absolute and let a crafted tree write outside the work tree. (reported by Luke Baton)
  • Bound zlib decompression of pack entries and loose objects against decompression-bomb DoS. read_zlib_chunks now caps the inflated size at the declared decomp_len, and loose-object parsing accepts max_size defaulting to git's core.bigFileThreshold (512 MiB). (reported by Luke Bento)
  • Reject OFS_DELTA pack entries whose delta_base_offset is zero. Such an entry references itself, so Pack.resolve_object would loop forever growing its delta stack until OOM. (reported by Luke Banto)
  • Bound Transfer-Encoding: chunked request bodies in dulwich.web: strip chunk extensions, reject negative sizes, enforce per-chunk and per-request size limits, and cap requests that omit Content-Length.
  • Bound the running length when decoding EWAH bitmaps so a corrupt or malformed .bitmap index raises ValueError instead of hanging in an unbounded loop that exhausts memory.

Other changes

  • web: Reject smart HTTP git-upload-pack / git-receive-pack POSTs whose Content-Type is not the exact application/x-<service>-request value, matching git http-backend.
  • dulwich.web: Warn at startup that running python3 -m dulwich.web is not intended as a production web server (no authentication, etc.).

See NEWS for the full list.

dulwich-1.2.8

Choose a tag to compare

@jelmer jelmer released this 05 Jul 15:28

Security

  • GHSA-8w8g-wq8h-fq33: Write files through build_file_from_blob in path-restricted porcelain.checkout(paths=...) instead of a raw os.open. The old path followed a symlink left at the target, so a crafted repository could write attacker content outside the work tree (e.g. into .git/hooks) on checkout.
  • GHSA-5fqc-mrg8-w798: Build the temporary index for filter-branch --index-filter in memory instead of materializing tree entries into CWD. Persisted entries between commits let a symlink from an ancestor commit redirect a descendant's writes outside the work tree.
  • Refuse to write a stash entry through an intermediate symlink on stash.pop. The old os.path.exists check followed symlinks, so a crafted stash whose parent path was a symlink already present in the worktree (e.g. link -> .git/hooks) let the subsequent write land outside the work tree.
  • Refuse path-restricted porcelain.checkout, restore and reset_file writes whose leading directory is an existing symlink, so a crafted repository can no longer land sub as a link to .git/hooks and have a write to sub/anything traverse it.
  • Canonicalize file modes to 0o644/0o755 before chmod on checkout and patch apply, matching git. An untrusted tree entry or patch `new file mode` could otherwise set setuid/setgid/sticky or world-writable bits on a materialized file.
  • Reject non-hex pkt-line length prefixes in the protocol parser. int(sizestr, 16) accepted a leading -, whose negative length made the following `read(size - 4)` slurp the rest of the stream and caused `PktLineParser` to loop without consuming its buffer. (#2267)
  • Escape the repository path passed to the remote in the SSH client, so a path containing a single quote can no longer close the quoting and have the remainder interpreted by the remote shell. (#2254)
  • Reject an option-like host in TCPGitClient before invoking the core.gitProxy command, matching the SubprocessSSHVendor guard, so a URL like `git://-oProxyCommand=...` can no longer be interpreted as a flag by the proxy program. (#2240)
  • Validate object ids in the object store and refs container. An id containing path separators would previously be joined into a filename by `DiskObjectStore._get_shafile_path` (escaping the objects directory) or stored as a ref value. (#2256)
  • Validate the object id in LFS server request handlers before it reaches the store, so a request path containing .. cannot escape the LFS directory. (#2255)
  • Don't expand config include/includeIf directives when parsing bundle lists served by an untrusted bundle-uri host, matching the handling of `.gitmodules`. (#2243)
  • Read the signing key from gpg's --status-fd (VALIDSIG) in `GPGCliSignatureVendor.verify` instead of the human-readable stderr text, which could be spoofed by embedding a matching line in the signed payload. (#2245)
  • Raise UntrustedSignature from verify_commit/verify_tag when keyids is set and the object carries no signature, instead of silently accepting it. (#2238)
  • Fix quadratic backtracking in _find_scissors_line so a crafted patch can no longer stall mailinfo/git am --scissors. (#2239)
  • Collapse consecutive * wildcards to at most ** in .gitattributes, .gitignore and config glob translation to avoid catastrophic backtracking (ReDoS). (#2237)
  • Fix quadratic buffering in web.ChunkReader.read. (#2262)
  • Skip invalid tree paths (containing .., .git, etc.) in `diff_working_tree_to_tree` instead of joining them onto the work tree; a working-tree diff against an untrusted commit could otherwise read a file outside the work tree and disclose its contents. (#2261)
  • Fix quadratic header accumulation in ShaFile._parse_message. (#2273)

Fixes

  • Enumerate the objects to push before the HTTP git-receive-pack request body starts streaming. `generate_pack_data` previously ran lazily inside the body generator, after the header pkt-lines were already on the wire, so on large repositories the request stalled mid-body while objects were counted and servers such as GitHub aborted the push with a timeout / broken pipe. (#2248)
  • Replace a symlink left at the target path with a fresh regular file in build_file_from_blob instead of writing through it, matching git on checkout. (#2259)
  • Raise GitProtocolError carrying the server's message when the fetch/send-pack tail loop sees a fatal side-band channel (\x03), instead of crashing with `AssertionError: Invalid sideband channel 3` and swallowing the server's error text.
  • Use ThreadingHTTPServer and advertise HTTP/1.1 in lfs_server so urllib3's keep-alive pool doesn't race a torn-down connection into RemoteDisconnected.

Other

  • Support http.postBuffer. (#2248)
  • Support pyo3 0.29.
  • Deprecate dulwich.objects.filename_to_hex, which is unused.