Skip to content

fix(clone): resolve forge auth via configured *_URL env vars (fixes #1704)#1706

Merged
Wirasm merged 1 commit into
coleam00:devfrom
kagura-agent:fix/gitea-url-fallback-1704
May 19, 2026
Merged

fix(clone): resolve forge auth via configured *_URL env vars (fixes #1704)#1706
Wirasm merged 1 commit into
coleam00:devfrom
kagura-agent:fix/gitea-url-fallback-1704

Conversation

@kagura-agent
Copy link
Copy Markdown
Contributor

@kagura-agent kagura-agent commented May 17, 2026

Summary

  • Problem: resolveForgeAuth() ignores GITEA_TOKEN for self-hosted Gitea instances whose hostname does not contain "gitea" (e.g. git.example.com)
  • Why it matters: Users with custom-domain Gitea/GitLab/Forgejo instances cannot clone private repos even with correct *_TOKEN and *_URL env vars set
  • What changed: Added a third fallback step in resolveForgeAuth() that compares the clone URL hostname against configured GITEA_URL, GITLAB_URL, and FORGEJO_URL env vars
  • What did not change (scope boundary): Steps 1 (exact host match) and 2 (label match) are untouched; SSH URL conversion and clone logic unchanged

UX Journey

Before

User                        resolveForgeAuth              git clone
────                        ────────────────              ─────────
clone git.example.com ───▶  Step 1: hostname ≠ known      
                            Step 2: labels ["git","example","com"]
                              ≠ "gitea"/"gitlab"/"forgejo"
                            → token: undefined ──────────▶ fatal: could not read Username

After

User                        resolveForgeAuth              git clone
────                        ────────────────              ─────────
clone git.example.com ───▶  Step 1: hostname ≠ known
                            Step 2: labels ≠ forge name
                           [Step 3: GITEA_URL hostname     
                              === clone hostname ✓]
                            → token: gitea_tok ──────────▶ clone succeeds ✓

Architecture Diagram

Before

resolveForgeAuth(url)
  ├─ 1. FORGE_AUTH exact match (github.com, gitlab.com, gitea.com)
  ├─ 2. SELF_HOSTED_FORGE label match (hostname contains "gitea"/"gitlab"/"forgejo")
  └─ return { token: undefined }

After

resolveForgeAuth(url)
  ├─ 1. FORGE_AUTH exact match (unchanged)
  ├─ 2. SELF_HOSTED_FORGE label match (unchanged)
  ├─ [+] 3. URL_FORGE: compare hostname against GITEA_URL/GITLAB_URL/FORGEJO_URL
  └─ return { token: undefined }

Connection inventory:

From To Status Notes
resolveForgeAuth FORGE_AUTH unchanged Step 1
resolveForgeAuth SELF_HOSTED_FORGE unchanged Step 2
resolveForgeAuth URL_FORGE new Step 3: env var hostname comparison
cloneRepository resolveForgeAuth unchanged Caller unchanged

Label Snapshot

  • Risk: risk: low
  • Size: size: S
  • Scope: core
  • Module: core:clone

Change Metadata

  • Change type: bug
  • Primary scope: core

Linked Issue

Validation Evidence (required)

bun test packages/core/src/handlers/clone.test.ts
# 11 resolveForgeAuth tests pass (6 existing + 4 new + 1 security)
# lint-staged ran eslint + prettier on commit — clean

New tests added:

  1. returns GITEA_TOKEN when GITEA_URL hostname matches clone URL — the exact repro from resolveForgeAuth doesn't use GITEA_TOKEN for self-hosted Gitea instances with non-standard hostnames #1704
  2. returns GITLAB_TOKEN with oauth2: scheme when GITLAB_URL hostname matches — same pattern for GitLab
  3. does not leak GITEA_TOKEN when GITEA_URL is set but hostname differs — security: token isolation
  4. URL fallback does not activate when token env var is unset — graceful degradation

Security Impact

  • Token leakage risk: None — hostname comparison is strict equality (===), not substring or label matching. GITEA_TOKEN is only returned when the clone URL hostname is identical to the GITEA_URL hostname.
  • Regression test: Test doesn't know what o1-mini is, or how to route to openrouter.ai #3 explicitly verifies tokens are not leaked to unrelated hosts.

Compatibility/Migration

  • Fully backward-compatible: steps 1 and 2 run first and are unchanged
  • Step 3 only activates when *_URL env vars are set (opt-in by configuration)
  • No config format changes

Human Verification

Risks and Mitigations

Risk Mitigation
safeParseUrl returns null for malformed URL Checked with if (forgeParsed &&...)
Multiple *_URL vars pointing to same host First match wins (Gitea → GitLab → Forgejo order)

Side Effects/Blast Radius

  • Only resolveForgeAuth() is modified — no callers changed
  • Step 3 is additive; only reached when steps 1 and 2 find no match

Rollback Plan

Revert commit; steps 1 and 2 continue working as before.

Summary by CodeRabbit

  • Bug Fixes

    • Improved authentication resolution for self-hosted forge services by adding hostname matching verification against configured URLs.
    • Enhanced security by preventing token leakage to repositories with different hostnames.
  • Tests

    • Added comprehensive test coverage for hostname-scoped authentication resolution scenarios.

Review Change Stack

…oleam00#1704)

resolveForgeAuth() only matched forges by exact hostname or hostname
label. Self-hosted instances with non-standard hostnames (e.g.
git.example.com) were silently ignored even when GITEA_URL pointed to
the same host.

Add a third fallback step that compares the clone URL hostname against
configured GITEA_URL, GITLAB_URL, and FORGEJO_URL env vars. This uses
strict hostname equality so tokens are never leaked to unrelated hosts.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ad4fe21a-9cbd-42be-bfc9-9f89df2d1dba

📥 Commits

Reviewing files that changed from the base of the PR and between 7bdf931 and c110f67.

📒 Files selected for processing (2)
  • packages/core/src/handlers/clone.test.ts
  • packages/core/src/handlers/clone.ts

📝 Walkthrough

Walkthrough

resolveForgeAuth now falls back to matching repository clone URL hostnames against configured GITEA_URL, GITLAB_URL, and FORGEJO_URL environment variables when exact hostname and label-based patterns fail, returning the corresponding token only on hostname match.

Changes

URL-based auth token resolution for self-hosted forges

Layer / File(s) Summary
URL-hostname-scoped auth resolution with token tests
packages/core/src/handlers/clone.ts, packages/core/src/handlers/clone.test.ts
resolveForgeAuth is extended with an explicit URL-matching phase that parses GITEA_URL, GITLAB_URL, and FORGEJO_URL hostnames and compares them against the clone repository hostname, returning the matching token (if set) and scheme only on exact hostname match. Tests validate hostname-match behavior, mismatch prevention, and missing-token fallback suppression.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related issues

  • coleam00/Archon#1704: Directly addresses the root cause by implementing hostname-scoped GITEA_TOKEN resolution using configured GITEA_URL when exact hostname and label-based matching fail.

Possibly related PRs

  • coleam00/Archon#1658: Also modifies resolveForgeAuth in clone.ts to drive hostname-scoped token resolution for Gitea and GitLab, with this PR extending it to additionally match configured *_URL environment variables.

Poem

🐰 A rabbit parsed hostnames with care,
Matching URLs here and there,
Tokens now flow to the right forge host,
No more lost clones at the post! 🔑

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding URL environment variable-based forge auth resolution as a fix for issue #1704.
Description check ✅ Passed The PR description is comprehensive and follows the template well, covering problem, impact, changes, scope, UX journey, architecture, validation, security, and rollback.
Linked Issues check ✅ Passed The code changes fully implement the requirements from #1704: adds hostname matching against GITEA_URL/GITLAB_URL/FORGEJO_URL with strict equality, includes security tests preventing token leakage, and handles missing token env vars.
Out of Scope Changes check ✅ Passed All changes are in-scope and directly address #1704: modifications only to resolveForgeAuth() function and its tests, with no unrelated formatting or refactoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Wirasm
Copy link
Copy Markdown
Collaborator

Wirasm commented May 18, 2026

Review Summary

Verdict: ready-to-merge

The PR adds explicit hostname-based matching against *_URL env vars (step 3 in resolveForgeAuth()), enabling clone auth for self-hosted Gitea/Forgejo/GitLab instances whose hostname doesn't embed a forge identifier. Code is clean, tests are thorough, and the implementation is well-scoped. A couple of documentation gaps to address post-merge.

Minor / nice-to-have

  • docs: Add FORGEJO_URL to packages/docs-web/src/content/docs/reference/configuration.md (Platform Adapters section). It reuses GITEA_TOKEN for auth — worth noting.
  • docs: Document the hostname-matching behavior: when the clone URL hostname matches GITEA_URL/GITLAB_URL/FORGEJO_URL, the corresponding token is used for git auth. Relevant for users with custom domains on self-hosted forges.
  • docs: Add GITLAB_URL as an optional variable to configuration.md (.env.example has it; docs don't).
  • code (optional): Add a clarifying comment in packages/core/src/handlers/clone.ts above the URL-fallback block explaining that returning undefined when *_URL matches but *_TOKEN is unset is intentional (avoids silent auth fallback).

Compliments

  • The four new tests are well-scoped and cover the happy path, hostname isolation, and the unset-token edge case cleanly.
  • The section-label comment ("3. Explicit URL match: ...") captures the WHY — self-hosted forges without forge names in their hostname — which is exactly the context a future reader will need.

Reviewed via maintainer-review-pr workflow (Pi/Minimax). Aspects run: code-review, error-handling, test-coverage, comment-quality, docs-impact.

@Wirasm Wirasm merged commit 70c9e67 into coleam00:dev May 19, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

resolveForgeAuth doesn't use GITEA_TOKEN for self-hosted Gitea instances with non-standard hostnames

2 participants