Skip to content

fix(git): open absolute-path files via osfs root "/" (fixes "public key is not configured")#348

Merged
universe-ops merged 1 commit into
mainfrom
fix/abs-path-key-open
Jun 28, 2026
Merged

fix(git): open absolute-path files via osfs root "/" (fixes "public key is not configured")#348
universe-ops merged 1 commit into
mainfrom
fix/abs-path-key-open

Conversation

@universe-ops

Copy link
Copy Markdown
Contributor

Problem

sc secrets reveal (and secrets add / secrets allow) fails with:

Error: public key is not configured

even when the profile is correctly configured and the key files exist. It reproduces with any profile that references keys by path, e.g. .sc/cfg.default.yaml:

projectName: my-project
privateKeyPath: ~/.ssh/id_rsa
publicKeyPath: ~/.ssh/id_rsa.pub

Root cause

git.repo.OpenFile delegates absolute paths to osfs.New("").OpenFile(...). Under go-billy v5.9.0, the default ChrootOS resolves symlinks relative to its root via filepath.Rel. With an empty
root (which cleans to "."), filepath.Rel(".", "/abs/path") always errors, so every absolute open returns chroot boundary crossed.

The failure cascades into the misleading error:

  1. WithKeysFromScConfig loads the private key first (~/.ssh/id_rsa → absolute after tilde expansion), so the failed open aborts the entire profile load.
  2. That error is swallowed at command bootstrap by IgnoreConfigDirError: true (root.go).
  3. The public key is therefore never set, and DecryptAll later reports public key is not configured.

This was a latent regression introduced with the go-billy v5.9.0 upgrade — there was even a unit test that had codified the broken chroot boundary behavior as a "QUIRK."

Fix

Root the OS filesystem at "/" (not "") for absolute paths, so filepath.Rel("/", "/abs/path") is well-defined:

if path.IsAbs(rPath) {
return osfs.New("/").OpenFile(rPath, flag, perm)
}

The relative-path fallback (wdFs = osfs.New("") in initRepo) is intentionally left rooted at "" so it keeps resolving against the process cwd.

Updated the unit test that asserted the broken behavior to instead assert that absolute-path opens succeed and read content back.

Verification

  • Reproduced the failure, then confirmed sc secrets reveal reveals all secret files after the fix.
  • Verified empirically: osfs.New("") → "chroot boundary crossed"; osfs.New("/") → opens correctly.
  • go test ./pkg/api/git/... and ./pkg/api/secrets/... pass.

Impact

Restores key-by-path / ~/.ssh-style profile configs for all secrets operations. No behavior change for inline-key profiles or relative-path resolution.

@smecsia smecsia added the ci-run label Jun 27, 2026
@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown

Semgrep Scan Results

Repository: api | Commit: c0d5586

Check Status Details
⚠️ Semgrep Warning 1 warning(s), 1 total

Scanned at 2026-06-28 07:43 UTC

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown

Security Scan Results

Repository: api | Commit: c0d5586

Check Status Details
✅ Secret Scan Pass No secrets detected
✅ Dependencies (Trivy) Pass 0 total (no critical/high)
✅ Dependencies (Grype) Pass 0 total (no critical/high)
📦 SBOM Generated 523 components (CycloneDX)

Scanned at 2026-06-28 07:43 UTC

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown

📊 Statement coverage

Measured on the documented included set (see docs/TESTING.md → Coverage scope). Observe-only — no regression gate is enforced yet.

Scope This PR main baseline Δ
Included set (Gold-tier denominator) 90.3% 90.3% +0.0 pp
Full set (whole repo, transparency) 27.9% 27.9% +0.0 pp

Baseline: main @ 842404b

@universe-ops universe-ops force-pushed the fix/abs-path-key-open branch from 163562c to 3b28c19 Compare June 27, 2026 20:04
…eveal)

OpenFile delegated absolute paths to osfs.New("").OpenFile(...). Under go-billy
v5.9.0 the default ChrootOS resolves symlinks relative to its root via filepath.Rel;
with an empty root (which cleans to "."), filepath.Rel(".", "/abs/path") always errors,
so every absolute open returned "chroot boundary crossed".

This broke profile configs that reference keys by absolute/tilde path (e.g.
privateKeyPath: ~/.ssh/id_rsa). WithKeysFromScConfig loads the private key first, so the
failed open aborted the whole profile load. The error is swallowed by IgnoreConfigDirError
at command bootstrap, leaving the public key unset — surfacing later as the misleading
"public key is not configured" on `sc secrets reveal` / `add` / `allow`.

Root the OS filesystem at "/" for absolute paths so Rel("/", "/abs/path") is well-defined.
The relative-path fallback (wdFs) stays rooted at "" so it keeps resolving against cwd.

Updated the unit test that had codified the broken "chroot boundary" behavior to assert
absolute-path opens now succeed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Ilya Sadykov <smecsia@gmail.com>
@universe-ops universe-ops force-pushed the fix/abs-path-key-open branch from 3b28c19 to 4095c51 Compare June 28, 2026 07:42
@universe-ops universe-ops merged commit 76b0ba9 into main Jun 28, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants