Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Drop the refs/vole rule, which has nothing left to guard

592710c296c678e21bc1dc89341ad71606316500 · Keenan Nemetz · 17d ago · parent ec5c519c

Drop the refs/vole rule, which has nothing left to guard

The namespace held the ACL and needed a rule of its own: a client who could write
refs/vole/acl could have granted itself admin. The rules live in data/users.db now,
so the namespace is empty and the special case only made refusals inconsistent —
an owner pushing refs/vole/x got "server-owned", which is no longer true.

Only branches and tags are writable, and that rule already refuses everything else,
refs/vole/* included. The test now pins that: refs/notes/commits and refs/vole/acl
are refused with the same message.

internal/hook/hook_test.go +11−21

@@ -142,21 +142,6 @@ func TestAnonymousCannotPush(t *testing.T) {
142 142 }
143 143 }
144 144
145 // TestMetadataRefsAreServerOwned is the one that matters most: refs/vole/* holds
146 // the ACL itself, so a client that can write it can grant itself admin.
147 func TestMetadataRefsAreServerOwned(t *testing.T) {
148 f := newFixture(t, "hello\n")
149 for _, ref := range []string{"refs/vole/acl", "refs/vole/issues/000"} {
150 code, out := f.run("owner", ref, 0)
151 if code == 0 {
152 t.Fatalf("owner was allowed to push %s", ref)
153 }
154 if !strings.Contains(out, "server-owned") {
155 t.Fatalf("message for %s should explain ownership, got: %s", ref, out)
156 }
157 }
158 }
159
160 145 func TestProtectedBranch(t *testing.T) {
161 146 f := newFixture(t, "hello\n")
162 147 f.setACL(func(a *acl.ACL) { a.Protected = []string{"refs/heads/main"} })
@@ -190,11 +175,16 @@ func TestOversizedBlobRejected(t *testing.T) {
190 175
191 176 func TestArbitraryRefsRejected(t *testing.T) {
192 177 f := newFixture(t, "hello\n")
193 code, out := f.run("owner", "refs/notes/commits", 0)
194 if code == 0 {
195 t.Fatal("push to an unrelated ref namespace was allowed")
196 }
197 if !strings.Contains(out, "only refs/heads") {
198 t.Fatalf("unclear message: %s", out)
178 // refs/vole is no longer server state (access rules moved into the database), but it
179 // is still not a branch or a tag, so it is refused by the same rule as any other
180 // namespace rather than by a rule of its own.
181 for _, ref := range []string{"refs/notes/commits", "refs/vole/acl", "refs/vole/anything"} {
182 code, out := f.run("owner", ref, 0)
183 if code == 0 {
184 t.Fatalf("push to %s was allowed", ref)
185 }
186 if !strings.Contains(out, "only refs/heads/*") {
187 t.Fatalf("%s: unclear message: %s", ref, out)
188 }
199 189 }
200 190 }