fix(engine): a folder's own configuration names no proxy for the fetch, and git's own folder name is not a repository name #198

Merged
james.maes merged 4 commits from fix/184-folder-proxy-and-git-folder-name into main 2026-11-11 06:26:58 +00:00
Owner

What

  • A proxy named in a folder's own git configuration (http.proxy, http.<url>.proxy, remote.<name>.proxy) is refused before anything is fetched, like a URL rewrite in the same place.
  • RepositoryPathResolver.TryValidateName refuses git's own folder name (.git, git~1, with trailing dots or spaces, in any case) on every platform.

Why

Closes #184. Two hardening items from the security review of the 1.1.1 candidate. Neither exposed a token. The first makes the rule of #139 (a folder's own configuration does not decide where a fetch goes) hold for the one setting it missed; the second makes a check that existed only on the Windows sync path the answer every caller gets.

How it was tested

  • OriginVerificationTests.Pull_FolderConfigurationNamesAProxy_IsRefused_BeforeAnythingIsFetched (five spellings of the key): refused, tracking branch unchanged, nothing written.
  • RepositoryPathResolverTests: five spellings of the name refused with the reason.
  • Gates, started from PowerShell: build with warnings as errors 0, engine 1,151, CLI 212, line coverage 100% on the three gated assemblies, format clean, UI suite 13 of 13.

Checklist

  • Commits are signed and signed off (git commit -S -s)
  • Zero build warnings; format and lint are clean
  • Tests added or updated; the 100% coverage gate still passes
  • Docs updated for user-visible changes; threat model updated if the attack surface changed (T3, T4, revision row)
  • No secrets, credentials, or personal data
  • New dependencies are justified below, or none were added (none)
  • Substantial AI assistance, if any, is noted here: written with Claude Code, from findings of an independent review agent.

🤖 Generated with Claude Code

## What - A proxy named in a folder's own git configuration (`http.proxy`, `http.<url>.proxy`, `remote.<name>.proxy`) is refused before anything is fetched, like a URL rewrite in the same place. - `RepositoryPathResolver.TryValidateName` refuses git's own folder name (`.git`, `git~1`, with trailing dots or spaces, in any case) on every platform. ## Why Closes #184. Two hardening items from the security review of the 1.1.1 candidate. Neither exposed a token. The first makes the rule of #139 (a folder's own configuration does not decide where a fetch goes) hold for the one setting it missed; the second makes a check that existed only on the Windows sync path the answer every caller gets. ## How it was tested - `OriginVerificationTests.Pull_FolderConfigurationNamesAProxy_IsRefused_BeforeAnythingIsFetched` (five spellings of the key): refused, tracking branch unchanged, nothing written. - `RepositoryPathResolverTests`: five spellings of the name refused with the reason. - Gates, started from PowerShell: build with warnings as errors 0, engine 1,151, CLI 212, line coverage 100% on the three gated assemblies, format clean, UI suite 13 of 13. ## Checklist - [x] Commits are signed and signed off (`git commit -S -s`) - [x] Zero build warnings; format and lint are clean - [x] Tests added or updated; the 100% coverage gate still passes - [x] Docs updated for user-visible changes; threat model updated if the attack surface changed (T3, T4, revision row) - [x] No secrets, credentials, or personal data - [x] New dependencies are justified below, or none were added (none) - [x] Substantial AI assistance, if any, is noted here: written with Claude Code, from findings of an independent review agent. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes added 1 commit 2026-11-11 06:01:37 +00:00
Two small hardening items from the security review of 1.1.1. Neither exposed
a token; both make a rule that is already stated hold everywhere.

- A folder's own git configuration must not decide where a sync's fetch goes
  (#139). That was enforced for URL rewrites and the SSH program; a proxy
  named there (http.proxy, http.<url>.proxy, remote.<name>.proxy) was still
  honored. It is refused now, with a message that names the setting. A proxy
  in the user's global configuration is theirs and still applies.
- RepositoryPathResolver.TryValidateName refuses git's own folder name, in any
  spelling Windows opens as that folder, on every platform. Until now only the
  Windows sync path refused it, so the WSL clone and the library elsewhere
  did not.

Threat model: T3 and T4 say so.

Closes #184

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
james.maes added 1 commit 2026-11-11 06:19:55 +00:00
- The first version refused the name in RepositoryPathResolver, which made the
  whole sync throw where on Windows only that row failed before. The resolver
  is as it was; the sync fails that row on every platform, and the WSL clone
  refuses the name.
- A folder's own http.followRedirects is refused with its proxy settings; the
  message names the setting found.

Refs #184

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
james.maes added 2 commits 2026-11-11 06:26:55 +00:00
Refs #184

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
It failed once in a full run: a token change also starts the organization
lookup, whose changes arrive from another thread, and the test collected the
names in a plain list.

Refs #182

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
Author
Owner

Second review by the release reviewers: the first version refused the name in RepositoryPathResolver, which made a whole sync throw where on Windows only that row had failed. Reworked in 9ab4756: the resolver is as it was, the sync fails that row on every platform, the WSL clone refuses the name. A folder's own http.followRedirects is refused with its proxy settings, and the message names the setting found.

The branch has main merged in (the threat model keeps the rows of #183 and of this change), so it is the state main will have. Gates on it, started from PowerShell: build with warnings as errors 0, engine 1,166, CLI 212, line coverage 100% on the three gated assemblies, format clean, UI suite 13 of 13, PSScriptAnalyzer clean.

Also in this branch, not part of #184: one test added with #185 collected property changes in a plain list while another thread could raise them; it failed once in a full run and is repaired here (Refs #182).

🤖 Generated with Claude Code

Second review by the release reviewers: the first version refused the name in `RepositoryPathResolver`, which made a whole sync throw where on Windows only that row had failed. Reworked in 9ab4756: the resolver is as it was, the sync fails that row on every platform, the WSL clone refuses the name. A folder's own `http.followRedirects` is refused with its proxy settings, and the message names the setting found. The branch has `main` merged in (the threat model keeps the rows of #183 and of this change), so it is the state `main` will have. Gates on it, started from PowerShell: build with warnings as errors 0, engine 1,166, CLI 212, line coverage 100% on the three gated assemblies, format clean, UI suite 13 of 13, PSScriptAnalyzer clean. Also in this branch, not part of #184: one test added with #185 collected property changes in a plain list while another thread could raise them; it failed once in a full run and is repaired here (Refs #182). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes merged commit e9f8377b13 into main 2026-11-11 06:26:58 +00:00
Sign in to join this conversation.