problem: Actions runner token is stored with password hash #12443

Open
opened 2026-05-07 00:09:25 +02:00 by Gusted · 2 comments
Gusted commented 2026-05-07 00:09:25 +02:00 (Migrated from codeberg.org)

Does your problem still exist on the latest Forgejo version?

Yes, the problem still exists (tested locally with the latest development version)

About your usage of Forgejo

Co-maintainer of Codeberg.org's Forgejo instance.

Problem description

I took a CPU and trace profile on codeberg.org to check for a weird performance bug, while doing that there was something that caught my eye:
image

Text Version
             crypto/internal/fips140/sha256.blockAVX2 /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256block_amd64.s:57
             crypto/internal/fips140/sha256.block /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256block_amd64.go:32
             crypto/internal/fips140/sha256.(*Digest).Write /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256.go:179
             crypto/internal/fips140/sha256.(*Digest).checkSum /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256.go:227
             crypto/internal/fips140/sha256.(*Digest).Sum /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256.go:204
             crypto/internal/fips140/hmac.(*HMAC).Sum /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/hmac/hmac.go:61
             golang.org/x/crypto/pbkdf2.Key /home/build/go/pkg/mod/golang.org/x/crypto@v0.49.0/pbkdf2/pbkdf2.go:70
             forgejo.org/models/auth.HashToken /home/build/deploy-15/build/forgejo/models/auth/twofactor.go:127
             forgejo.org/routers/api/actions/runner.init.func1.1 /home/build/deploy-15/build/forgejo/routers/api/actions/runner/interceptor.go:44
             connectrpc.com/connect.NewUnaryHandler[go.shape.8af9c1988d9803e1dd8b92b31ba7697627b6cb5474044bf26f47a0f4bb25d16f,go.shape.3513d525dd26f2821679c3ec21b8318c9b98590927603d0b4814493c1c45df1d].func2 /home/build/go/pkg/mod/connectrpc.com/connect@v1.19.1/handler.go:78
             connectrpc.com/connect.(*Handler).ServeHTTP /home/build/go/pkg/mod/connectrpc.com/connect@v1.19.1/handler.go:333
             code.forgejo.org/forgejo/actions-proto/runner/v1/runnerv1connect.NewRunnerServiceHandler.func1 /home/build/go/pkg/mod/code.forgejo.org/forgejo/actions-proto@v0.7.0/runner/v1/runnerv1connect/services.connect.go:233
[...]

That's way more than it should be.

The relevant code show painfully why it was showing up as taking that much time in the CPU profile:

codeberg.org/forgejo/forgejo@69cf1f3333/routers/api/actions/runner/interceptor.go (L43)

It's run in the interceptor! Thus on every request from the Forgejo Runner to the Forgejo instance, the token is hashed and checked. But hashing is not expensive! But the hash used is pbkdf, which is a hash for passwords (low entropy) and thus slow on purpose:

codeberg.org/forgejo/forgejo@69cf1f3333/models/auth/twofactor.go (L73-L77)

The token has enough entropy to be hashed via SHA256 or blake even.

Potential workarounds

Forgejo Version

v15.0.1

Other details about your environment (software names and versions)

Codeberg runs a soft fork of Forgejo, https://codeberg.org/Codeberg-Infrastructure/forgejo

Solutions

Accepted solutions to address this problem will go here

### Does your problem still exist on the latest Forgejo version? Yes, the problem still exists (tested locally with the latest development version) ### About your usage of Forgejo Co-maintainer of Codeberg.org's Forgejo instance. ### Problem description I took a CPU and trace profile on codeberg.org to check for a weird performance bug, while doing that there was something that caught my eye: ![image](/attachments/ac7fac11-037a-4ac5-954d-aa7989ef38cd) <details><summary>Text Version</summary> ``` crypto/internal/fips140/sha256.blockAVX2 /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256block_amd64.s:57 crypto/internal/fips140/sha256.block /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256block_amd64.go:32 crypto/internal/fips140/sha256.(*Digest).Write /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256.go:179 crypto/internal/fips140/sha256.(*Digest).checkSum /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256.go:227 crypto/internal/fips140/sha256.(*Digest).Sum /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/sha256/sha256.go:204 crypto/internal/fips140/hmac.(*HMAC).Sum /home/build/deploy-15/build/go-1.26.2/go/src/crypto/internal/fips140/hmac/hmac.go:61 golang.org/x/crypto/pbkdf2.Key /home/build/go/pkg/mod/golang.org/x/crypto@v0.49.0/pbkdf2/pbkdf2.go:70 forgejo.org/models/auth.HashToken /home/build/deploy-15/build/forgejo/models/auth/twofactor.go:127 forgejo.org/routers/api/actions/runner.init.func1.1 /home/build/deploy-15/build/forgejo/routers/api/actions/runner/interceptor.go:44 connectrpc.com/connect.NewUnaryHandler[go.shape.8af9c1988d9803e1dd8b92b31ba7697627b6cb5474044bf26f47a0f4bb25d16f,go.shape.3513d525dd26f2821679c3ec21b8318c9b98590927603d0b4814493c1c45df1d].func2 /home/build/go/pkg/mod/connectrpc.com/connect@v1.19.1/handler.go:78 connectrpc.com/connect.(*Handler).ServeHTTP /home/build/go/pkg/mod/connectrpc.com/connect@v1.19.1/handler.go:333 code.forgejo.org/forgejo/actions-proto/runner/v1/runnerv1connect.NewRunnerServiceHandler.func1 /home/build/go/pkg/mod/code.forgejo.org/forgejo/actions-proto@v0.7.0/runner/v1/runnerv1connect/services.connect.go:233 [...] ``` </details> That's way more than it should be. The relevant code show painfully why it was showing up as taking that much time in the CPU profile: https://codeberg.org/forgejo/forgejo/src/commit/69cf1f3333cdb420dca6d07d74b5e0269c428057/routers/api/actions/runner/interceptor.go#L43 It's run in the interceptor! Thus on every request from the Forgejo Runner to the Forgejo instance, the token is hashed and checked. But hashing is not expensive! But the hash used is pbkdf, which is a hash for passwords (low entropy) and thus slow on purpose: https://codeberg.org/forgejo/forgejo/src/commit/69cf1f3333cdb420dca6d07d74b5e0269c428057/models/auth/twofactor.go#L73-L77 The token has enough entropy to be hashed via SHA256 or blake even. ### Potential workarounds - Deploy https://codeberg.org/Codeberg-Infrastructure/forgejo/commit/fb4a64f0ac26d337f783acc147e8026424aa4aad, although seems to not be sufficient with a cache size of 1024 on the scale of Codeberg. ### Forgejo Version v15.0.1 ### Other details about your environment (software names and versions) Codeberg runs a soft fork of Forgejo, https://codeberg.org/Codeberg-Infrastructure/forgejo ### Solutions *Accepted solutions to address this problem will go here*
Gusted commented 2026-05-07 00:13:55 +02:00 (Migrated from codeberg.org)

Tagging this as good first issue, and loosely related to actions. The way to fix this is straight forward IMO and happy to take a new contributor as a way to explore the codebase.

Tagging this as good first issue, and loosely related to actions. The way to fix this is straight forward IMO and happy to take a new contributor as a way to explore the codebase.
vagonzal commented 2026-05-07 17:15:32 +02:00 (Migrated from codeberg.org)

Happy to take this issue

Happy to take this issue
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sleepy/forgejo#12443
No description provided.