Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/admin_user_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func runCreateUser(ctx context.Context, c *cli.Command) error {
if err != nil {
return err
}
// codeql[disable-next-line=go/clear-text-logging]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a shame that CodeQL doesn't support such inline-disabling. I was cheated by AI.

CodeQL is missing an inline mechanism to suppress warnings #11427

Copy link
Member

@silverwind silverwind Oct 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never blindly trust AI, always verify 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I never blindly trust AI. But at the moment I don't have a way to test the CodeQL related changes locally. So after the merge, I checked the result immediately .....

If anyone knows to how to test CodeQL locally, please suggest. 🙏

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems there is a codeql cli, but it requires some setup and a "database" being generated:

https://medium.com/@arjun_zs/codeql-cli-running-in-local-the-how-5817175300c6

Maybe we can add a make codeql that does it all.

fmt.Printf("generated random password is '%s'\n", password)
} else if userType == user_model.UserTypeIndividual {
return errors.New("must set either password or random-password flag")
Expand Down
1 change: 1 addition & 0 deletions cmd/admin_user_must_change_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func runMustChangePassword(ctx context.Context, c *cli.Command) error {
return err
}

// codeql[disable-next-line=go/clear-text-logging]
fmt.Printf("Updated %d users setting MustChangePassword to %t\n", n, mustChangePassword)
return nil
}
1 change: 1 addition & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func runGenerateSecretKey(_ context.Context, c *cli.Command) error {
return err
}

// codeql[disable-next-line=go/clear-text-logging]
fmt.Printf("%s", secretKey)

if isatty.IsTerminal(os.Stdout.Fd()) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ Gitea or set your environment appropriately.`, "")
userID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
deployKeyID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvDeployKeyID), 10, 64)
actionPerm, _ := strconv.ParseInt(os.Getenv(repo_module.EnvActionPerm), 10, 64)
actionPerm, _ := strconv.Atoi(os.Getenv(repo_module.EnvActionPerm))

hookOptions := private.HookOptions{
UserID: userID,
Expand All @@ -196,7 +196,7 @@ Gitea or set your environment appropriately.`, "")
GitPushOptions: pushOptions(),
PullRequestID: prID,
DeployKeyID: deployKeyID,
ActionPerm: int(actionPerm),
ActionPerm: actionPerm,
}

scanner := bufio.NewScanner(os.Stdin)
Expand Down
2 changes: 1 addition & 1 deletion models/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ func (repo *Repository) IsGenerated() bool {

// RepoPath returns repository path by given user and repository name.
func RepoPath(userName, repoName string) string { //revive:disable-line:exported
return filepath.Join(user_model.UserPath(userName), strings.ToLower(repoName)+".git")
return filepath.Join(setting.RepoRootPath, filepath.Clean(strings.ToLower(userName)), filepath.Clean(strings.ToLower(repoName)+".git"))
}

// RepoPath returns the repository path
Expand Down
2 changes: 1 addition & 1 deletion models/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, er

// UserPath returns the path absolute path of user repositories.
func UserPath(userName string) string { //revive:disable-line:exported
return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
return filepath.Join(setting.RepoRootPath, filepath.Clean(strings.ToLower(userName)))
}

// GetUserByID returns the user object by given ID if exists.
Expand Down
16 changes: 5 additions & 11 deletions modules/auth/password/hash/argon2.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,11 @@ func NewArgon2Hasher(config string) *Argon2Hasher {
return nil
}

parsed, err := parseUIntParam(vals[0], "time", "argon2", config, nil)
hasher.time = uint32(parsed)

parsed, err = parseUIntParam(vals[1], "memory", "argon2", config, err)
hasher.memory = uint32(parsed)

parsed, err = parseUIntParam(vals[2], "threads", "argon2", config, err)
hasher.threads = uint8(parsed)

parsed, err = parseUIntParam(vals[3], "keyLen", "argon2", config, err)
hasher.keyLen = uint32(parsed)
var err error
hasher.time, err = parseUintParam[uint32](vals[0], "time", "argon2", config, nil)
hasher.memory, err = parseUintParam[uint32](vals[1], "memory", "argon2", config, err)
hasher.threads, err = parseUintParam[uint8](vals[2], "threads", "argon2", config, err)
hasher.keyLen, err = parseUintParam[uint32](vals[3], "keyLen", "argon2", config, err)
if err != nil {
return nil
}
Expand Down
8 changes: 5 additions & 3 deletions modules/auth/password/hash/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strconv"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
)

func parseIntParam(value, param, algorithmName, config string, previousErr error) (int, error) {
Expand All @@ -18,11 +19,12 @@ func parseIntParam(value, param, algorithmName, config string, previousErr error
return parsed, previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed
}

func parseUIntParam(value, param, algorithmName, config string, previousErr error) (uint64, error) { //nolint:unparam // algorithmName is always argon2
parsed, err := strconv.ParseUint(value, 10, 64)
func parseUintParam[T uint32 | uint8](value, param, algorithmName, config string, previousErr error) (ret T, _ error) {
_, isUint32 := any(ret).(uint32)
parsed, err := strconv.ParseUint(value, 10, util.Iif(isUint32, 32, 8))
if err != nil {
log.Error("invalid integer for %s representation in %s hash spec %s", param, algorithmName, config)
return 0, err
}
return parsed, previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed
return T(parsed), previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed
}
4 changes: 2 additions & 2 deletions modules/auth/password/pwn/pwn.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func newRequest(ctx context.Context, method, url string, body io.ReadCloser) (*h
// Adding padding will make requests more secure, however is also slower
// because artificial responses will be added to the response
// For more information, see https://www.troyhunt.com/enhancing-pwned-passwords-privacy-with-padding/
func (c *Client) CheckPassword(pw string, padding bool) (int, error) {
func (c *Client) CheckPassword(pw string, padding bool) (int64, error) {
if pw == "" {
return -1, ErrEmptyPassword
}
Expand Down Expand Up @@ -111,7 +111,7 @@ func (c *Client) CheckPassword(pw string, padding bool) (int, error) {
if err != nil {
return -1, err
}
return int(count), nil
return count, nil
}
}
return 0, nil
Expand Down
12 changes: 6 additions & 6 deletions modules/auth/password/pwn/pwn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@ func TestPassword(t *testing.T) {

count, err := client.CheckPassword("", false)
assert.ErrorIs(t, err, ErrEmptyPassword, "blank input should return ErrEmptyPassword")
assert.Equal(t, -1, count)
assert.EqualValues(t, -1, count)

count, err = client.CheckPassword("pwned", false)
assert.NoError(t, err)
assert.Equal(t, 1, count)
assert.EqualValues(t, 1, count)

count, err = client.CheckPassword("notpwned", false)
assert.NoError(t, err)
assert.Equal(t, 0, count)
assert.EqualValues(t, 0, count)

count, err = client.CheckPassword("paddedpwned", true)
assert.NoError(t, err)
assert.Equal(t, 1, count)
assert.EqualValues(t, 1, count)

count, err = client.CheckPassword("paddednotpwned", true)
assert.NoError(t, err)
assert.Equal(t, 0, count)
assert.EqualValues(t, 0, count)

count, err = client.CheckPassword("paddednotpwnedzero", true)
assert.NoError(t, err)
assert.Equal(t, 0, count)
assert.EqualValues(t, 0, count)
}
2 changes: 1 addition & 1 deletion modules/git/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func GetHook(repoPath, name string) (*Hook, error) {
}
h := &Hook{
name: name,
path: filepath.Join(repoPath, "hooks", name+".d", name),
path: filepath.Join(repoPath, filepath.Join("hooks", name+".d", name)),
}
isFile, err := util.IsFile(h.path)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions modules/log/logger_global.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func GetLevel() Level {
}

func Log(skip int, level Level, format string, v ...any) {
// codeql[disable-next-line=go/clear-text-logging]
GetLogger(DEFAULT).Log(skip+1, &Event{Level: level}, format, v...)
}

Expand Down
1 change: 1 addition & 0 deletions modules/log/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func BaseLoggerToGeneralLogger(b BaseLogger) Logger {
var _ Logger = (*baseToLogger)(nil)

func (s *baseToLogger) Log(skip int, event *Event, format string, v ...any) {
// codeql[disable-next-line=go/clear-text-logging]
s.base.Log(skip+1, event, format, v...)
}

Expand Down
2 changes: 1 addition & 1 deletion modules/setting/config_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func decodeEnvSectionKey(encoded string) (ok bool, section, key string) {
decodedBytes := make([]byte, len(toDecode)/2)
for i := 0; i < len(toDecode)/2; i++ {
// Can ignore error here as we know these should be hexadecimal from the regexp
byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 0)
byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 8)
decodedBytes[i] = byte(byteInt)
}
if inKey {
Expand Down
2 changes: 1 addition & 1 deletion modules/tempdir/tempdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type TempDir struct {
}

func (td *TempDir) JoinPath(elems ...string) string {
return filepath.Join(append([]string{td.base, td.sub}, elems...)...)
return filepath.Join(append([]string{td.base, td.sub}, filepath.Join(elems...))...)
}

// MkdirAllSub works like os.MkdirAll, but the base directory must exist
Expand Down
3 changes: 3 additions & 0 deletions modules/translation/i18n/i18n_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ sub = Changed Sub String
found := lang1.HasKey("no-such")
assert.False(t, found)
assert.NoError(t, ls.Close())

res := lang1.TrHTML("<no-such>")
assert.Equal(t, "&lt;no-such&gt;", string(res))
}

func TestLocaleStoreMoreSource(t *testing.T) {
Expand Down
8 changes: 5 additions & 3 deletions modules/translation/i18n/localestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package i18n
import (
"errors"
"fmt"
"html"
"html/template"
"slices"

Expand Down Expand Up @@ -109,8 +110,7 @@ func (store *localeStore) Close() error {
}

func (l *locale) TrString(trKey string, trArgs ...any) string {
format := trKey

var format string
idx, ok := l.store.trKeyToIdxMap[trKey]
if ok {
if msg, ok := l.idxToMsgMap[idx]; ok {
Expand All @@ -122,7 +122,9 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
}
}
}

if format == "" {
format = html.EscapeString(trKey)
}
msg, err := Format(format, trArgs...)
if err != nil {
log.Error("Error whilst formatting %q in %s: %v", trKey, l.langName, err)
Expand Down
9 changes: 5 additions & 4 deletions modules/util/color.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ func HexToRBGColor(colorString string) (float64, float64, float64) {
if len(hexString) == 8 {
hexString = hexString[0:6]
}
color, err := strconv.ParseUint(hexString, 16, 64)
color, err := strconv.ParseUint(hexString, 16, 32)
color32 := uint32(color)
if err != nil {
return 0, 0, 0
}
r := float64(uint8(0xFF & (uint32(color) >> 16)))
g := float64(uint8(0xFF & (uint32(color) >> 8)))
b := float64(uint8(0xFF & uint32(color)))
r := float64(uint8(0xFF & (color32 >> 16)))
g := float64(uint8(0xFF & (color32 >> 8)))
b := float64(uint8(0xFF & color32))
return r, g, b
}

Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/repo/issue_pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func MoveIssuePin(ctx *context.APIContext) {
return
}

err = issues_model.MovePin(ctx, issue, int(ctx.PathParamInt64("position")))
err = issues_model.MovePin(ctx, issue, ctx.PathParamInt("position"))
if err != nil {
ctx.APIErrorInternal(err)
return
Expand Down
2 changes: 1 addition & 1 deletion routers/web/explore/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type RepoSearchOptions struct {
// This function is also used to render the Admin Repository Management page.
func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
// Sitemap index for sitemap paths
page := int(ctx.PathParamInt64("idx"))
page := ctx.PathParamInt("idx")
isSitemap := ctx.PathParam("idx") != ""
if page <= 1 {
page = ctx.FormInt("page")
Expand Down
2 changes: 1 addition & 1 deletion routers/web/explore/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func isKeywordValid(keyword string) bool {
// RenderUserSearch render user search page
func RenderUserSearch(ctx *context.Context, opts user_model.SearchUserOptions, tplName templates.TplName) {
// Sitemap index for sitemap paths
opts.Page = int(ctx.PathParamInt64("idx"))
opts.Page = ctx.PathParamInt("idx")
isSitemap := ctx.PathParam("idx") != ""
if opts.Page <= 1 {
opts.Page = ctx.FormInt("page")
Expand Down
27 changes: 11 additions & 16 deletions routers/web/repo/activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,28 @@ func Activity(ctx *context.Context) {

ctx.Data["PageIsPulse"] = true

ctx.Data["Period"] = ctx.PathParam("period")

timeUntil := time.Now()
var timeFrom time.Time

switch ctx.Data["Period"] {
period, timeFrom := "weekly", timeUntil.Add(-time.Hour*168)
switch ctx.PathParam("period") {
case "daily":
timeFrom = timeUntil.Add(-time.Hour * 24)
period, timeFrom = "daily", timeUntil.Add(-time.Hour*24)
case "halfweekly":
timeFrom = timeUntil.Add(-time.Hour * 72)
period, timeFrom = "halfweekly", timeUntil.Add(-time.Hour*72)
case "weekly":
timeFrom = timeUntil.Add(-time.Hour * 168)
period, timeFrom = "weekly", timeUntil.Add(-time.Hour*168)
case "monthly":
timeFrom = timeUntil.AddDate(0, -1, 0)
period, timeFrom = "monthly", timeUntil.AddDate(0, -1, 0)
case "quarterly":
timeFrom = timeUntil.AddDate(0, -3, 0)
period, timeFrom = "quarterly", timeUntil.AddDate(0, -3, 0)
case "semiyearly":
timeFrom = timeUntil.AddDate(0, -6, 0)
period, timeFrom = "semiyearly", timeUntil.AddDate(0, -6, 0)
case "yearly":
timeFrom = timeUntil.AddDate(-1, 0, 0)
default:
ctx.Data["Period"] = "weekly"
timeFrom = timeUntil.Add(-time.Hour * 168)
period, timeFrom = "yearly", timeUntil.AddDate(-1, 0, 0)
}
ctx.Data["DateFrom"] = timeFrom
ctx.Data["DateUntil"] = timeUntil
ctx.Data["PeriodText"] = ctx.Tr("repo.activity.period." + ctx.Data["Period"].(string))
ctx.Data["Period"] = period
ctx.Data["PeriodText"] = ctx.Tr("repo.activity.period." + period)

canReadCode := ctx.Repo.CanRead(unit.TypeCode)
if canReadCode {
Expand Down
30 changes: 18 additions & 12 deletions routers/web/repo/githttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
ctx.Resp.WriteHeader(http.StatusBadRequest)
return
}
reqFile := filepath.Join(h.getRepoDir(), file)
reqFile := filepath.Join(h.getRepoDir(), filepath.Clean(file))

fi, err := os.Stat(reqFile)
if os.IsNotExist(err) {
Expand All @@ -395,13 +395,12 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`)

func prepareGitCmdWithAllowedService(service string) (*gitcmd.Command, error) {
if service == "receive-pack" {
return gitcmd.NewCommand("receive-pack"), nil
if service == ServiceTypeReceivePack {
return gitcmd.NewCommand(ServiceTypeReceivePack), nil
}
if service == "upload-pack" {
return gitcmd.NewCommand("upload-pack"), nil
if service == ServiceTypeUploadPack {
return gitcmd.NewCommand(ServiceTypeUploadPack), nil
}

return nil, fmt.Errorf("service %q is not allowed", service)
}

Expand Down Expand Up @@ -464,28 +463,35 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
}
}

const (
ServiceTypeUploadPack = "upload-pack"
ServiceTypeReceivePack = "receive-pack"
)

// ServiceUploadPack implements Git Smart HTTP protocol
func ServiceUploadPack(ctx *context.Context) {
h := httpBase(ctx)
if h != nil {
serviceRPC(ctx, h, "upload-pack")
serviceRPC(ctx, h, ServiceTypeUploadPack)
}
}

// ServiceReceivePack implements Git Smart HTTP protocol
func ServiceReceivePack(ctx *context.Context) {
h := httpBase(ctx)
if h != nil {
serviceRPC(ctx, h, "receive-pack")
serviceRPC(ctx, h, ServiceTypeReceivePack)
}
}

func getServiceType(ctx *context.Context) string {
serviceType := ctx.Req.FormValue("service")
if !strings.HasPrefix(serviceType, "git-") {
return ""
switch ctx.Req.FormValue("service") {
case "git-" + ServiceTypeUploadPack:
return ServiceTypeUploadPack
case "git-" + ServiceTypeReceivePack:
return ServiceTypeReceivePack
}
return strings.TrimPrefix(serviceType, "git-")
return ""
}

func updateServerInfo(ctx gocontext.Context, dir string) []byte {
Expand Down
Loading