Skip to content

Security: ivarvong/exgit

Security

SECURITY.md

Security Policy

Supported versions

Exgit is in active pre-1.0 development. Security fixes are made against main. No back-porting to older 0.x releases is currently offered.

Version Supported
main
0.1.x
< 0.1

Reporting a vulnerability

Do not open a public issue for security vulnerabilities.

Email ivar@ivarvong.com with:

  • A description of the issue
  • Exact steps to reproduce (a minimal test case is best)
  • The affected version / commit
  • Any known mitigations

You should receive an acknowledgement within 3 business days. We'll work with you on a disclosure timeline — typically 30–90 days depending on severity and complexity of the fix.

We request embargo until the fix is released.

Threat model

Exgit is a git client library. The trust boundaries we enumerate and defend:

Boundary Input Defenses
Remote server → client ls-refs output, pack bytes, redirects Exgit.RefName validates ref names at the wire perimeter; RefStore.Disk re-validates defense-in-depth on every read/resolve/write/delete (#1). Exgit.Object.Tree.decode/1 validates each entry name against path-traversal rules — rejects .., /, NUL, .git/.gitmodules in any case (#2). Exgit.Object.Commit.decode/1 and Tag.decode/1 validate hex in header values so accessor calls (Commit.tree/1, Commit.parents/1, Tag.object) are infallible — a hostile remote cannot DoS a walk/diff/FS operation by shipping a structurally-valid commit with non-hex headers (#23). Pack.Reader bounds memory via :max_pack_bytes / :max_object_bytes / :max_resolved_bytes (#11/#35) and never raises on hostile input. Credentials are host-bound by default with ASCII-case-folding + trailing-dot-stripping normalization (#5); redirects are disabled unless explicitly opted-in.
User-supplied URL Transport construction No special validation — it's the caller's responsibility to avoid SSRF-class risks from user-controlled URLs. Host-bound credentials limit damage.
User-supplied credential PATs, basic auth, callbacks %Exgit.Credentials{} and %Exgit.Transport.HTTP{} both implement custom Inspect protocols that redact auth values. Crash logs, SASL reports, and IEx sessions do not leak tokens.
Local filesystem (Disk store) Object/ref files on disk SHA verification on read detects bit-rot and tampering. :zlib.uncompress/1 is wrapped in try/rescue so corrupt loose objects return {:error, :zlib_error} instead of crashing the caller (#3). Ref-store resolve_ref/2 re-validates symbolic targets read from disk so a ref: ../../etc/passwd file cannot escape the repo root (#1).
Local filesystem (config) .git/config .git/config is treated as caller-controlled input, not remote-controlled. Config.parse/1 returns `{:ok, _}
User-supplied pack for push Exgit.push/3 arguments Caller-generated input is within the trust boundary for push. Note that Exgit.push/3 reads objects from the local store, which may contain objects that came from a remote via an earlier clone/fetch — objects ingress through Pack.Reader which enforces the bounds above. A hostile pack cached earlier cannot trigger traversal at push time because tree entry names have already been validated at fetch-time decode.

Not defended: the agent/caller can push arbitrary content to a remote if it has a write-scoped credential. That's by design — our job is to prevent a remote from attacking the client, not to sandbox the caller.

Regression corpus

The test suite includes explicit regression tests for each CVE-worthy finding. Per review:

Finding Test file
#1 Ref-store disk path escape test/exgit/security/ref_escape_test.exs + test/exgit/security/ref_store_disk_boundary_test.exs
#2 Tree entry path traversal test/exgit/security/tree_entry_name_test.exs
#3 Loose object zlib raise test/exgit/security/zlib_error_test.exs + test/exgit/security/loose_object_test.exs
#4 Pack inflate desync test/exgit/pack/inflate_tracked_test.exs
#5 Credential host confusion test/exgit/security/credential_host_normalization_test.exs + test/exgit/credentials_host_test.exs
#23 Commit hex DoS test/exgit/security/malformed_hex_commit_test.exs
#23 (Tag sibling) test/exgit/security/tag_malformed_hex_test.exs

Any future security fix MUST land with a regression test in test/exgit/security/ that would fail without the fix.

Known advisories

None yet. This file will list them with CVE IDs when applicable.

Dependency policy

  • req — network client. Minimum version pinned to one with known-good cross-origin auth-stripping default. Bumping Req's major version requires re-running the cross-origin leak test suite before merging. (Our host-bound %Exgit.Credentials{} is the primary enforcement; Req's behavior is a belt-and-suspenders layer.)
  • telemetry — BEAM-standard instrumentation. Low risk.
  • opentelemetry_* — dev/test only; not present in production runtime.
  • stream_data, dialyxir, credo — dev/test only.

A full SBOM is generated as part of the release process.

Cryptography

Exgit uses :crypto.hash(:sha, _) for git object SHA-1s. SHA-1 is not collision-resistant in the modern cryptographic sense, but git itself relies on SHA-1 and so does exgit. If you are working with a SHA-256 git repository (rare, opt-in at repo creation), exgit does not yet support it (tracked as a v0.2+ item).

Responsible disclosure

We follow coordinated disclosure. Reporters are credited in the CHANGELOG unless they request anonymity.

There aren't any published security advisories