Skip to content

Correct forge_id and org handling on user/repo#6820

Merged
lafriks merged 6 commits into
woodpecker-ci:mainfrom
6543-forks:multi-forge-fixes
Jul 8, 2026
Merged

Correct forge_id and org handling on user/repo#6820
lafriks merged 6 commits into
woodpecker-ci:mainfrom
6543-forks:multi-forge-fixes

Conversation

@6543

@6543 6543 commented Jul 7, 2026

Copy link
Copy Markdown
Member

What

Fixes a set of multi-forge bugs where Woodpecker treats org names, user
logins and forge-local IDs as globally unique. With more than one forge
configured these collide, leaking permissions across forges and creating
unresolvable records.

Fixes

  • Anonymous permission crashGetOrgPermissions resolved the forge
    from the user before the nil-user guard, so an unauthenticated call to
    /orgs/{id}/permissions (no MustUser on the route) paniced.

  • Cross-forge org accessMustOrgMember and GetOrgPermissions
    compared org names and user logins without checking the forge. A user
    could gain member or admin access (incl. org secrets and registries) to
    a same-named org on a foreign forge. Now scoped to the org's forge;
    instance admins keep cross-forge access.

  • Membership cache leak — the cache key used ForgeRemoteID, which is
    only unique per forge, so two users sharing a remote id leaked
    membership across forges for the TTL. Keyed by the global user id.

  • Foreign-forge permission syncSetPerm resolved the forge from the
    repo but synced with the session user, sending that user's OAuth token to
    a different forge's API and mislabeling the fetched repo. Skipped when
    user and repo differ in forge.

  • Zero forge id on user creationPostUser stored forge_id: 0 when
    omitted, producing users and orgs no forge resolves. Clamped to the
    default forge, matching PatchUser.

  • Stale org link on repo moveMoveRepo changed the owner but kept
    OrgID, so the old owner's org secrets/registries kept applying. Relinks
    to the new owner's org (reusing the activation-time resolution).


    in peer work with claude fable5

claude added 6 commits July 7, 2026 21:37
…rmissions

ForgeFromUser dereferences user.ForgeID, but the nil-user guard ran only
after that call. GET /orgs/{org_id}/permissions has no MustUser middleware,
so an unauthenticated request crashed the handler with a nil pointer
dereference instead of returning empty permissions.
Org names and user logins are only unique per forge. MustOrgMember and
GetOrgPermissions compared names without checking the forge, so with
multiple forges configured a user could gain member or even admin access
(including org secrets and registries) to a foreign forge's org in two
ways: a login matching a foreign user-org's name, or a membership in a
same-named org on the user's own forge being credited to the foreign org.

Deny access when the org belongs to a different forge than the user; only
instance admins keep cross-forge access.
…mote id

The cache key was ForgeRemoteID-org, but forge remote ids are only unique
per forge. With multiple forges, two different users sharing a numeric
remote id and an org name would hit the same cache entry, so one user's
membership (including admin) leaked to a user of another forge for up to
the cache TTL. Key by the globally unique user ID instead.
SetPerm resolved the forge from the repo but synced stale permissions
with whatever user is in the session. With multiple forges a user of
forge A visiting a repo of forge B caused their forge-A OAuth token to
be sent to forge B's API, and the fetched repo was mislabeled with the
user's forge id. Skip the sync when user and repo belong to different
forges; such users keep the zero permission set.
PostUser stored whatever forge id the request body carried, including the
zero value when the field was omitted. Users and their orgs then ended up
with forge_id 0, which no forge resolves, breaking every forge lookup for
them; migration 025 exists solely to clean up such rows. Clamp to the
default forge like PatchUser already does.
MoveRepo updated owner and full name but kept the old OrgID, so org-level
secrets and registries of the previous owner kept applying to the moved
repo while the new owner's never did. Resolve (or create) the org of the
new owner on the repo's forge and relink, reusing the org resolution
already done during repo activation.
@6543 6543 added bug Something isn't working server labels Jul 7, 2026
@woodpecker-bot

woodpecker-bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Surge PR preview deployment was removed

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.07143% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.74%. Comparing base (adbc365) to head (7535005).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
server/api/repo.go 42.42% 14 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6820      +/-   ##
==========================================
+ Coverage   47.30%   47.74%   +0.43%     
==========================================
  Files         440      440              
  Lines       29726    29757      +31     
==========================================
+ Hits        14062    14207     +145     
+ Misses      14496    14340     -156     
- Partials     1168     1210      +42     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lafriks lafriks merged commit 8a9c45a into woodpecker-ci:main Jul 8, 2026
9 checks passed
@woodpecker-bot woodpecker-bot mentioned this pull request Jul 8, 2026
1 task
@6543 6543 deleted the multi-forge-fixes branch July 8, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants