Repository navigation
Conversation
Team code belongs in team organizations. Until 0c1c3bb, any repository whose provisioning failed was deleted, which is how personal repositories were kept out. That commit stopped deleting because the webhook was unauthenticated and the delete used the owner and name from the body, so a forged event could delete any repository. Since then people could create personal repositories, and those get no branch protection. Webhooks are now authenticated, and this brings the delete back for personal repositories only. The owner's kind comes from the API, since Gitea fills the body's `organization` with the owner even for personal repositories. The repository is deleted only when the API's copy has the event's id and owner, belongs to a user, and was created within 10 minutes; a replayed or forged event can't delete an older or different repository. Any failure, including not being able to tell whether the owner is an organization, logs and leaves the repository alone. Organization repositories go through provisioning exactly as before, and a failed provisioning still never deletes. Tests cover each guard with faked clients. End to end on Gitea 1.27.3: a new personal repository was deleted within seconds of creation, and a new team repository in the same run was provisioned as before.
Collaborator
Author
|
Closing: we're staying on Gitea 1.24.3, so this stacked PR is replaced by a standalone one against master that only restores personal-repo deletion. |
3 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings back the deletion of personal Gitea repositories on creation, with guards so a forged or mismatched webhook can't delete anything.
Stacked on #112 (base branch
gitea-1.27-upgrade), because both touch the webhook handler. Merge #112 first; this PR then retargets tomaster.Why it stopped
Until
0c1c3bb("authenticate Gitea webhooks and close two IDOR holes", Sept 5),handleRepoCreationdeleted any repository whose provisioning failed. A personal repo always fails (no Authentik team with that name), so personal repos were removed automatically. That commit replaced the delete with "leave untouched" because the endpoint was unauthenticated and the delete used the owner/name from the request body: a forged event could delete any repository. Since then, personal repositories stay, without branch protection.What this does
The webhooks now require the bearer secret, and the handlers re-fetch from the API. On a
createdevent:GET /orgs/{owner}; only a 404 means "user", any other error leaves the repo alone). The body can't be used: Gitea fillsorganizationwith the owner even for personal repos.PERSONAL_REPO_DELETE_WINDOW_MS). A replayed or forged event can't delete an older or different repository. Every refusal is logged.Also adds
GiteaClient.isOrganizationand URL-encodesdeleteRepository's path.Behaviour to be aware of
createdtoo, so they are deleted as well.Test plan
gitea-personal-repos.test.js(faked clients): fresh personal repo deleted; org repo provisioned and never deleted; no delete on id mismatch, owner mismatch, repo older than the window, unparseablecreated_at, or when the org lookup errors; non-createdactions never deleteprettier@3.9.10 --check;nx builddevadmin/scratch-personaldeleted within seconds (Deleted personal repository ...logged); newTechOps/hook-test-4provisioned as before (public, default branchmain)