Security and limits

Network trust

The owned default transport permits HTTPS only, disables automatic redirects, cookies, and proxies, and validates DNS results. Its connection callback connects directly to validated addresses while TLS validates the repository hostname. Private/local/metadata addresses and non-global IPv6 are rejected. URL userinfo, queries, and fragments are rejected; the library itself adds the Git discovery query.

AllowPrivateHosts = true bypasses address restrictions for explicitly trusted internal hosts. It does not enable HTTP or redirects. Never enable it broadly for arbitrary user-supplied repository URLs.

An injected HttpClient is caller-owned and trusted. Configure its handler with AllowAutoRedirect = false, trusted headers/cookies, and equivalent proxy and connection-time DNS policy. The library performs DNS preflight and rejects changed response URLs it observes, but cannot inspect or override the handler or undo requests it already redirected. Prefer the default owned transport for built-in SSRF defenses.

Retries, secrets, and deadlines

Only transient HTTP statuses 429, 502, 503, and 504 are retried, with bounded exponential delays. MaxRetries counts retries after the initial attempt. The client does not retry response-stream consumption, pack processing, file callbacks, or access failures. Handler side effects are never replayed.

RequestTimeout covers each transport send operation, its retry loop, and response consumption. It is not an overall snapshot deadline. Cancellation propagates, and per-operation temporary stores are disposed on exit. Do not log authorization headers or secrets in application credential providers. HTTP access errors have sanitized messages; remote bodies/progress/error text are not logged.

Resource defaults

GitClientOptions.cs is the authoritative source. Budgets span all requests and packs in one public operation and reset for the next operation.

Option Default Meaning
MaxTransferBytes 2 GiB HTTP response bytes including framing
MaxBlobBytes 512 MiB One reconstructed blob
MaxDecompressedBytes 4 GiB Total inflated and reconstructed bytes
MaxTemporaryDiskBytes 8 GiB Cumulative temporary writes, including packs, duplicates, and delta intermediates
MaxMemoryBytes 64 MiB Accounted metadata and fixed-buffer budget
MaxObjectCount 100,000 Objects across packs
MaxTreeDepth 128 Directory nesting
MaxPathLength 4,096 Repository path characters
MaxDeltaDepth 64 Delta chain depth
BlobBatchSize 128 Wanted blob IDs per selective request
RequestTimeout 5 minutes Request deadline including consumption and retries
MaxRetries 2 Transient status retries
AllowPrivateHosts false Explicit trust for private network destinations
SkipUnsupportedEntries false Skip unsupported content and report warnings
TemporaryDirectory null Use system temporary storage as the parent

Numeric budgets must be positive; memory must be at least 1 MiB. Tree depth is restricted to 1–512, path length to 1–1,000,000, batch size to 1–4,096, and retries to 0–10.

Memory accounting excludes .NET runtime, HTTP handler, caller, and callback allocations. Metadata uses conservative per-object/per-path allowances; a large tree can exhaust the budget despite a small compressed pack. Temporary disk accounting is cumulative rather than peak live disk usage. Set TemporaryDirectory to a trusted volume with appropriate permissions and sufficient space. Pack data, inflated objects, and reconstructed deltas use per-operation temporary files rather than retaining full file contents in managed memory.

Input and disk validation

Pack processing checks PACK v2/v3 framing, SHA-1 object IDs and pack checksum, object sizes, zlib boundaries, OFS_DELTA and REF_DELTA chains (including forward references), missing bases, and malformed delta instructions. Trees are validated for malformed entries, unsupported modes, paths, and missing objects. SHA-256 repositories are rejected. Selective responses containing unrelated blobs and tree-only responses containing blobs are rejected; rejection cannot undo bytes already transmitted by a nonconforming server.

DiskFileHandler rejects traversal, rooted paths, backslashes, NUL, invalid/reserved Windows names, case collisions, and symlink/reparse-point ancestors. It cleans sibling temporary outputs when a write fails or is canceled. Managed path checks cannot eliminate races if another process swaps directories for links during a write. The destination must be exclusively controlled by a trusted process. Earlier successfully delivered files remain after later failure.

Unsupported content and providers

Symlinks and submodules appear in listings. Full snapshots reject them by default; filtered snapshots select regular/executable files only. Standard Git LFS pointer signatures cause failure rather than delivering incomplete LFS content. With SkipUnsupportedEntries = true, unsupported full-snapshot entries and selected LFS pointers produce warnings and an incomplete result.

There is no SSH, plain HTTP, LFS download, submodule recursion, history, write/push operation, hook/script execution, or checkout filter execution. No automatic full snapshot fallback follows selective OID refusal. GitHub, GitLab, and Azure DevOps endpoints are usable only when their protocol capabilities and OID policies permit the requested operation. The root README records prior live GitHub testing; authenticated/provider-specific coverage requires opt-in tests against authorized repositories.