Compare commits

...

21 Commits

Author SHA1 Message Date
Joe Chen
c9fba3cb30 release: update version to 0.12.11 2023-02-25 13:39:54 +08:00
Joe Chen
0d4cb74077 Fix failing tests 2023-02-25 13:35:28 +08:00
Joe Chen
01917975f9 Fix compile error 2023-02-25 13:05:41 +08:00
Joe Chen
b1576d5a1f fix(db): correctly check Git path on case-insensitive file system (#7359) 2023-02-25 13:02:31 +08:00
Joe Chen
ced66de44a fix(db): sanitize user full name after find (#7353)
# Conflicts:
#	internal/db/issue.go
#	internal/db/users.go
#	internal/db/users_test.go
2023-02-25 13:00:55 +08:00
Joe Chen
5a3914cfca fix(repo): be tolerant to implicit submodules (#7352)
# Conflicts:
#	CHANGELOG.md
#	go.mod
#	go.sum
2023-02-25 12:56:56 +08:00
Joe Chen
4795575fac gofmt 2022-08-08 14:01:52 +08:00
Joe Chen
e4f9251e54 ci: drop Go < 1.17 and add 1.19 2022-08-08 14:01:43 +08:00
Joe Chen
1ce5171ae1 Do not run tests with race detection on Windows 2022-08-02 11:01:04 +08:00
Joe Chen
47297c0510 gofmt 2022-08-02 10:44:36 +08:00
Joe Chen
a2113bd13a release: update version to 0.12.10 2022-08-02 10:42:47 +08:00
Joe Chen
7be49a8f2f netutil: allow using * to match any hostname (#7111)
# Conflicts:
#	internal/netutil/netutil_test.go
2022-08-02 10:38:46 +08:00
Joe Chen
7f147eb573 webhook: validate against hostname instead of full URL (#7075)
# Conflicts:
#	CHANGELOG.md
2022-08-02 10:37:45 +08:00
Joe Chen
012a1ba19e release: update version to 0.12.9 2022-06-07 21:29:32 +08:00
Joe Chen
a24b22c909 http: clean request path from Git endpoints (#7022) 2022-06-07 21:26:15 +08:00
Joe Chen
20923a8829 pathutil: check both styles of os.PathSeparator (#7020) 2022-06-07 21:25:51 +08:00
E99p1ant
4c02b480dc issues: sanitize DisplayName (#7009)
* issues: display issue poster’s `Name` instead of `DisplayName`

* sanitize display name

* update changelog
2022-06-07 21:24:56 +08:00
Joe Chen
deeb3f73e4 repo_editor: check both styles of os.PathSeparator in all systems (#7005)
# Conflicts:
#	CHANGELOG.md
2022-06-07 21:24:37 +08:00
Joe Chen
1bc379f4d4 pull: ignore PR status check if head repository is missing (#7004)
# Conflicts:
#	internal/db/pull.go
2022-06-07 21:23:38 +08:00
Joe Chen
8e8b185ea1 http: fix non-sense NotFound call (#7003) 2022-06-07 21:21:29 +08:00
Joe Chen
42ad18a245 repo: remove hard-coded branch name in init (#6999) 2022-06-07 21:20:54 +08:00
22 changed files with 258 additions and 82 deletions

View File

@@ -53,8 +53,8 @@ jobs:
name: Test
strategy:
matrix:
go-version: [ 1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.18.x ]
platform: [ ubuntu-latest, macos-latest, windows-latest ]
go-version: [ 1.17.x, 1.18.x, 1.19.x ]
platform: [ ubuntu-latest, macos-latest ]
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
@@ -86,3 +86,43 @@ jobs:
The job "${{ github.job }}" of ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} completed with "${{ job.status }}".
View the job run at: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
# Running tests with race detection consumes too much memory on Windows,
# see https://github.com/golang/go/issues/46099 for details.
test-windows:
name: Test
strategy:
matrix:
go-version: [ 1.17.x, 1.18.x, 1.19.x ]
platform: [ windows-latest ]
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with coverage
run: go test -v -coverprofile=coverage -covermode=atomic ./...
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v1.5.0
with:
file: ./coverage
flags: unittests
- name: Send email on failure
uses: dawidd6/action-send-mail@v3
if: ${{ failure() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
with:
server_address: smtp.mailgun.org
server_port: 465
username: ${{ secrets.SMTP_USERNAME }}
password: ${{ secrets.SMTP_PASSWORD }}
subject: GitHub Actions (${{ github.repository }}) job result
to: github-actions-8ce6454@unknwon.io
from: GitHub Actions (${{ github.repository }})
reply_to: noreply@unknwon.io
body: |
The job "${{ github.job }}" of ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} completed with "${{ job.status }}".
View the job run at: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

View File

@@ -6,26 +6,34 @@ All notable changes to Gogs are documented in this file.
### Added
- Support using personal access token in the password field. [#3866](https://github.com/gogs/gogs/issues/3866)
- An unlisted option is added when create or migrate a repository. Unlisted repositories are public but not being listed for users without direct access in the UI. [#5733](https://github.com/gogs/gogs/issues/5733)
- New API endpoint `PUT /repos/:owner/:repo/contents/:path` for creating and update repository contents. [#5967](https://github.com/gogs/gogs/issues/5967)
- New configuration option `[git.timeout] DIFF` for customizing operation timeout of `git diff`. [#6315](https://github.com/gogs/gogs/issues/6315)
- New configuration option `[server] SSH_SERVER_MACS` for setting list of accepted MACs for connections to builtin SSH server. [#6434](https://github.com/gogs/gogs/issues/6434)
- New configuration option `[repository] DEFAULT_BRANCH` for setting default branch name for new repositories. [#7291](https://github.com/gogs/gogs/issues/7291)
- New configuration option `[server] SSH_SERVER_ALGORITHMS` for specifying the list of accepted key exchange algorithms for connections to builtin SSH server. [#7345](https://github.com/gogs/gogs/pull/7345)
- Support specifying custom schema for PostgreSQL. [#6695](https://github.com/gogs/gogs/pull/6695)
- Support rendering Mermaid diagrams in Markdown. [#6776](https://github.com/gogs/gogs/pull/6776)
- New languages support: Mongolian. [#6510](https://github.com/gogs/gogs/pull/6510)
- Docker: Allow passing extra arguments to the `backup` command. [#7060](https://github.com/gogs/gogs/pull/7060)
- New languages support: Mongolian, Romanian. [#6510](https://github.com/gogs/gogs/pull/6510) [#7082](https://github.com/gogs/gogs/pull/7082)
### Changed
- The default branch has been changed to `main`. [#6285](https://github.com/gogs/gogs/pull/6285)
- MSSQL as database backend is deprecated, installation page no longer shows it as an option. Existing installations and manually craft configuration file continue to work. [#6295](https://github.com/gogs/gogs/pull/6295)
- Use [Task](https://github.com/go-task/task) as the build tool. [#6297](https://github.com/gogs/gogs/pull/6297)
- The required Go version to compile source code changed to 1.16.
- The required Go version to compile source code changed to 1.18.
- Access tokens are now stored using their SHA256 hashes instead of raw values. [#7008](https://github.com/gogs/gogs/pull/7008)
### Fixed
- _Security:_ XSS in cookies. [#6953](https://github.com/gogs/gogs/issues/6953)
- _Security:_ OS Command Injection in file uploading. [#6968](https://github.com/gogs/gogs/issues/6968)
- _Security:_ Remote Command Execution in file editing. [#6555](https://github.com/gogs/gogs/issues/6555)
- _Security:_ Stored XSS for issue assignees. [#7145](https://github.com/gogs/gogs/issues/7145)
- _Security:_ OS Command Injection in repo editor on case-insensitive file systems. [#7030](https://github.com/gogs/gogs/issues/7030)
- Unable to use LDAP authentication on ARM machines. [#6761](https://github.com/gogs/gogs/issues/6761)
- Unable to choose "Lookup Avatar by mail" in user settings without deleting custom avatar. [#7267](https://github.com/gogs/gogs/pull/7267)
- Mistakenly include the "data" directory under the custom directory in the Docker setup. [#7343](https://github.com/gogs/gogs/pull/7343)
- Unable to render repository pages with implicit submodules (e.g. `get submodule "REDACTED": revision does not exist`). [#6436](https://github.com/gogs/gogs/issues/6436)
### Removed
@@ -47,6 +55,40 @@ All notable changes to Gogs are documented in this file.
- Configuration option `[database] PASSWD` is no longer used, please use `[database] PASSWORD`.
- Remove option to use Makefile as the build tool. [#6980](https://github.com/gogs/gogs/pull/6980)
## 0.12.10
### Changed
- Support using `[security] LOCAL_NETWORK_ALLOWLIST = *` to allow all hostnames. [#7111](https://github.com/gogs/gogs/pull/7111)
### Fixed
- Unable to send webhooks to local network addresses after configured `[security] LOCAL_NETWORK_ALLOWLIST`. [#7074](https://github.com/gogs/gogs/issues/7074)
## 0.12.9
### Fixed
- _Security:_ OS Command Injection in file editor. [#7000](https://github.com/gogs/gogs/issues/7000)
- _Security:_ Sanitize `DisplayName` in repository issue list. [#7009](https://github.com/gogs/gogs/pull/7009)
- _Security:_ Path Traversal in file editor on Windows. [#7001](https://github.com/gogs/gogs/issues/7001)
- _Security:_ Path Traversal in Git HTTP endpoints. [#7002](https://github.com/gogs/gogs/issues/7002)
- Unable to init repository during creation on Windows. [#6967](https://github.com/gogs/gogs/issues/6967)
- Mysterious panic on `Value not found for type *repo.HTTPContext`. [#6963](https://github.com/gogs/gogs/issues/6963)
## 0.12.8
### Changed
- All users (including admins) need to use the configuration option `[security] LOCAL_NETWORK_ALLOWLIST` to allow repository migration and webhooks to be able to access local network addresses, which is a comma separated list of hostnames. [#6988](https://github.com/gogs/gogs/pull/6988)
### Fixed
- _Security:_ SSRF in webhook. [#6901](https://github.com/gogs/gogs/issues/6901)
- _Security:_ XSS in cookies. [#6953](https://github.com/gogs/gogs/issues/6953)
- _Security:_ OS Command Injection in file uploading. [#6968](https://github.com/gogs/gogs/issues/6968)
- _Security:_ Remote Command Execution in file editing. [#6555](https://github.com/gogs/gogs/issues/6555)
## 0.12.7
### Fixed

View File

@@ -170,6 +170,7 @@ ENABLE_LOGIN_STATUS_COOKIE = false
; The cookie name to store user login status.
LOGIN_STATUS_COOKIE_NAME = login_status
; A comma separated list of hostnames that are explicitly allowed to be accessed within the local network.
; Use "*" to allow all hostnames.
LOCAL_NETWORK_ALLOWLIST =
[email]

4
go.mod
View File

@@ -19,7 +19,7 @@ require (
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/gogs/git-module v1.1.2
github.com/gogs/git-module v1.8.1
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a
@@ -49,7 +49,7 @@ require (
github.com/satori/go.uuid v1.2.0
github.com/sergi/go-diff v1.1.0
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/stretchr/testify v1.6.1
github.com/stretchr/testify v1.8.1
github.com/t-tiger/gorm-bulk-insert v1.3.0
github.com/unknwon/cae v1.0.2
github.com/unknwon/com v1.0.1

15
go.sum
View File

@@ -88,8 +88,8 @@ github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561 h1:aBzukfDxQlCTVS0NBU
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 h1:yXtpJr/LV6PFu4nTLgfjQdcMdzjbqqXMEnHfq0Or6p8=
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3G5amEoiNbhVrmM+ZQEcnQvNQ2KaZk=
github.com/gogs/git-module v1.1.2 h1:30jO+rKEmCDk/O6Mnl7MVrw6rI1qLDByXpkRB+bpYwM=
github.com/gogs/git-module v1.1.2/go.mod h1:oN37FFStFjdnTJXsSbhIHKJXh2YeDsEcXPATVz/oeuQ=
github.com/gogs/git-module v1.8.1 h1:yC5BZ3unJOXC8N6/FgGQ8EtJXpOd217lgDcd2aPOxkc=
github.com/gogs/git-module v1.8.1/go.mod h1:Y3rsSqtFZEbn7lp+3gWf42GKIY1eNTtLt7JrmOy0yAQ=
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4 h1:C7NryI/RQhsIWwC2bHN601P1wJKeuQ6U/UCOYTn3Cic=
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0 h1:K02vod+sn3M1OOkdqi2tPxN2+xESK4qyITVQ3JkGEv4=
@@ -281,11 +281,15 @@ github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cma
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/t-tiger/gorm-bulk-insert v1.3.0 h1:9k7BaVEhw/3fsvh6GTOBwJ2RXk3asc5xs5m6hwozq20=
github.com/t-tiger/gorm-bulk-insert v1.3.0/go.mod h1:ruDlk8xDl+8sX4bA7PQuYly9YEb3pbp1eP2LCyeRrFY=
@@ -433,8 +437,9 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -19,7 +19,7 @@ import (
)
func init() {
conf.App.Version = "0.12.8"
conf.App.Version = "0.12.11"
}
func main() {

View File

@@ -621,11 +621,6 @@ func (pr *PullRequest) UpdateCols(cols ...string) error {
// UpdatePatch generates and saves a new patch.
func (pr *PullRequest) UpdatePatch() (err error) {
if pr.HeadRepo == nil {
log.Trace("PullRequest[%d].UpdatePatch: ignored cruppted data", pr.ID)
return nil
}
headGitRepo, err := git.Open(pr.HeadRepo.RepoPath())
if err != nil {
return fmt.Errorf("open repository: %v", err)
@@ -759,6 +754,11 @@ func (prs PullRequestList) LoadAttributes() error {
func addHeadRepoTasks(prs []*PullRequest) {
for _, pr := range prs {
if pr.HeadRepo == nil {
log.Trace("addHeadRepoTasks[%d]: missing head repository", pr.ID)
continue
}
log.Trace("addHeadRepoTasks[%d]: composing new test task", pr.ID)
if err := pr.UpdatePatch(); err != nil {
log.Error("UpdatePatch: %v", err)

View File

@@ -483,6 +483,11 @@ func (repo *Repository) getUsersWithAccesMode(e Engine, mode AccessMode) (_ []*U
if err = e.In("id", userIDs).Find(&users); err != nil {
return nil, err
}
// TODO(unknwon): Rely on AfterFind hook to sanitize user full name.
for _, u := range users {
u.FullName = markup.Sanitize(u.FullName)
}
}
if !repo.Owner.IsOrganization() {
users = append(users, repo.Owner)
@@ -727,8 +732,8 @@ type MigrateRepoOptions struct {
}
/*
GitHub, GitLab, Gogs: *.wiki.git
BitBucket: *.git/wiki
- GitHub, GitLab, Gogs: *.wiki.git
- BitBucket: *.git/wiki
*/
var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"}
@@ -912,7 +917,7 @@ func initRepoCommit(tmpPath string, sig *git.Signature) (err error) {
if _, stderr, err = process.ExecDir(-1,
tmpPath, fmt.Sprintf("initRepoCommit (git push): %s", tmpPath),
"git", "push", "origin", "master"); err != nil {
"git", "push"); err != nil {
return fmt.Errorf("git push: %s", stderr)
}
return nil
@@ -1965,7 +1970,9 @@ func GitFsck() {
repo := bean.(*Repository)
repoPath := repo.RepoPath()
err := git.RepoFsck(repoPath, git.FsckOptions{
Args: conf.Cron.RepoHealthCheck.Args,
CommandOptions: git.CommandOptions{
Args: conf.Cron.RepoHealthCheck.Args,
},
Timeout: conf.Cron.RepoHealthCheck.Timeout,
})
if err != nil {

View File

@@ -197,7 +197,7 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
RepoName: repo.Name,
RepoPath: repo.RepoPath(),
})
if err = git.RepoPush(localPath, "origin", opts.NewBranch, git.PushOptions{Envs: envs}); err != nil {
if err = git.RepoPush(localPath, "origin", opts.NewBranch, git.PushOptions{CommandOptions: git.CommandOptions{Envs: envs}}); err != nil {
return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err)
}
return nil
@@ -302,7 +302,7 @@ func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (
RepoName: repo.Name,
RepoPath: repo.RepoPath(),
})
if err = git.RepoPush(localPath, "origin", opts.NewBranch, git.PushOptions{Envs: envs}); err != nil {
if err = git.RepoPush(localPath, "origin", opts.NewBranch, git.PushOptions{CommandOptions: git.CommandOptions{Envs: envs}}); err != nil {
return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err)
}
return nil
@@ -453,12 +453,17 @@ type UploadRepoFileOptions struct {
// isRepositoryGitPath returns true if given path is or resides inside ".git"
// path of the repository.
//
// TODO(unknwon): Move to repoutil during refactoring for this file.
func isRepositoryGitPath(path string) bool {
path = strings.ToLower(path)
return strings.HasSuffix(path, ".git") ||
strings.Contains(path, ".git"+string(os.PathSeparator)) ||
strings.Contains(path, ".git/") ||
strings.Contains(path, `.git\`) ||
// Windows treats ".git." the same as ".git"
strings.HasSuffix(path, ".git.") ||
strings.Contains(path, ".git."+string(os.PathSeparator))
strings.Contains(path, ".git./") ||
strings.Contains(path, `.git.\`)
}
func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) error {
@@ -531,7 +536,7 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
RepoName: repo.Name,
RepoPath: repo.RepoPath(),
})
if err = git.RepoPush(localPath, "origin", opts.NewBranch, git.PushOptions{Envs: envs}); err != nil {
if err = git.RepoPush(localPath, "origin", opts.NewBranch, git.PushOptions{CommandOptions: git.CommandOptions{Envs: envs}}); err != nil {
return fmt.Errorf("git push origin %s: %v", opts.NewBranch, err)
}

View File

@@ -5,34 +5,54 @@
package db
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_isRepositoryGitPath(t *testing.T) {
func TestIsRepositoryGitPath(t *testing.T) {
tests := []struct {
path string
wantVal bool
}{
{path: filepath.Join(".", ".git"), wantVal: true},
{path: filepath.Join(".", ".git", ""), wantVal: true},
{path: filepath.Join(".", ".git", "hooks", "pre-commit"), wantVal: true},
{path: filepath.Join(".git", "hooks"), wantVal: true},
{path: filepath.Join("dir", ".git"), wantVal: true},
{path: ".git", wantVal: true},
{path: "./.git", wantVal: true},
{path: ".git/hooks/pre-commit", wantVal: true},
{path: ".git/hooks", wantVal: true},
{path: "dir/.git", wantVal: true},
{path: filepath.Join(".", ".git."), wantVal: true},
{path: filepath.Join(".", ".git.", ""), wantVal: true},
{path: filepath.Join(".", ".git.", "hooks", "pre-commit"), wantVal: true},
{path: filepath.Join(".git.", "hooks"), wantVal: true},
{path: filepath.Join("dir", ".git."), wantVal: true},
// Case-insensitive file system
{path: ".Git", wantVal: true},
{path: "./.Git", wantVal: true},
{path: ".Git/hooks/pre-commit", wantVal: true},
{path: ".Git/hooks", wantVal: true},
{path: "dir/.Git", wantVal: true},
{path: filepath.Join(".gitignore"), wantVal: false},
{path: filepath.Join("dir", ".gitkeep"), wantVal: false},
{path: ".gitignore", wantVal: false},
{path: "dir/.gitkeep", wantVal: false},
// Windows-specific
{path: `.git\`, wantVal: true},
{path: `.git\hooks\pre-commit`, wantVal: true},
{path: `.git\hooks`, wantVal: true},
{path: `dir\.git`, wantVal: true},
{path: `.\.git.`, wantVal: true},
{path: `.\.git.\`, wantVal: true},
{path: `.git.\hooks\pre-commit`, wantVal: true},
{path: `.git.\hooks`, wantVal: true},
{path: `dir\.git.`, wantVal: true},
{path: "./.git.", wantVal: true},
{path: "./.git./", wantVal: true},
{path: ".git./hooks/pre-commit", wantVal: true},
{path: ".git./hooks", wantVal: true},
{path: "dir/.git.", wantVal: true},
{path: `dir\.gitkeep`, wantVal: false},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
t.Run(test.path, func(t *testing.T) {
assert.Equal(t, test.wantVal, isRepositoryGitPath(test.path))
})
}

View File

@@ -32,6 +32,7 @@ import (
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/db/errors"
"gogs.io/gogs/internal/errutil"
"gogs.io/gogs/internal/markup"
"gogs.io/gogs/internal/strutil"
"gogs.io/gogs/internal/tool"
)
@@ -920,14 +921,18 @@ func GetUserByKeyID(keyID int64) (*User, error) {
return user, nil
}
// Deprecated: Use Users.GetByID instead.
func getUserByID(e Engine, id int64) (*User, error) {
u := new(User)
has, err := e.ID(id).Get(u)
if err != nil {
return nil, err
} else if !has {
return nil, ErrUserNotExist{args: map[string]interface{}{"userID": id}}
return nil, ErrUserNotExist{args: errutil.Args{"userID": id}}
}
// TODO(unknwon): Rely on AfterFind hook to sanitize user full name.
u.FullName = markup.Sanitize(u.FullName)
return u, nil
}

View File

@@ -49,7 +49,7 @@ func Test_users(t *testing.T) {
}
// TODO: Only local account is tested, tests for external account will be added
// along with addressing https://github.com/gogs/gogs/issues/6115.
// along with addressing https://github.com/gogs/gogs/issues/6115.
func test_users_Authenticate(t *testing.T, db *users) {
password := "pa$$word"
alice, err := db.Create(CreateUserOpts{

View File

@@ -11,6 +11,7 @@ import (
"encoding/hex"
"fmt"
"io/ioutil"
"net/url"
"strings"
"time"
@@ -689,8 +690,13 @@ func TestWebhook(repo *Repository, event HookEventType, p api.Payloader, webhook
}
func (t *HookTask) deliver() {
if netutil.IsBlockedLocalHostname(t.URL, conf.Security.LocalNetworkAllowlist) {
t.ResponseContent = "Payload URL resolved to a local network address that is implicitly blocked."
payloadURL, err := url.Parse(t.URL)
if err != nil {
t.ResponseContent = fmt.Sprintf(`{"body": "Cannot parse payload URL: %v"}`, err)
return
}
if netutil.IsBlockedLocalHostname(payloadURL.Hostname(), conf.Security.LocalNetworkAllowlist) {
t.ResponseContent = `{"body": "Payload URL resolved to a local network address that is implicitly blocked."}`
return
}

View File

@@ -197,9 +197,9 @@ func (r *Request) SetTransport(transport http.RoundTripper) *Request {
// example:
//
// func(req *http.Request) (*url.URL, error) {
// u, _ := url.ParseRequestURI("http://127.0.0.1:8118")
// return u, nil
// }
// u, _ := url.ParseRequestURI("http://127.0.0.1:8118")
// return u, nil
// }
func (r *Request) SetProxy(proxy func(*http.Request) (*url.URL, error)) *Request {
r.setting.Proxy = proxy
return r

View File

@@ -52,7 +52,7 @@ func init() {
// allowlist).
func IsBlockedLocalHostname(hostname string, allowlist []string) bool {
for _, allow := range allowlist {
if hostname == allow {
if hostname == allow || allow == "*" {
return false
}
}

View File

@@ -20,7 +20,6 @@ func TestIsLocalHostname(t *testing.T) {
{hostname: "127.0.0.1", want: true},
{hostname: "::1", want: true},
{hostname: "0:0:0:0:0:0:0:1", want: true},
{hostname: "fuf.me", want: true},
{hostname: "127.0.0.95", want: true},
{hostname: "0.0.0.0", want: true},
{hostname: "192.168.123.45", want: true},
@@ -29,8 +28,10 @@ func TestIsLocalHostname(t *testing.T) {
{hostname: "google.com", want: false},
{hostname: "165.232.140.255", want: false},
{hostname: "192.168.123.45", allowlist: []string{"10.0.0.17"}, want: true},
{hostname: "gogs.local", allowlist: []string{"gogs.local"}, want: false},
{hostname: "192.168.123.45", allowlist: []string{"10.0.0.17"}, want: true}, // #11
{hostname: "gogs.local", allowlist: []string{"gogs.local"}, want: false}, // #12
{hostname: "192.168.123.45", allowlist: []string{"*"}, want: false}, // #13
}
for _, test := range tests {
t.Run("", func(t *testing.T) {

View File

@@ -9,7 +9,9 @@ import (
"strings"
)
// Clean cleans up given path and returns a relative path that goes straight down.
// Clean cleans up given path and returns a relative path that goes straight
// down to prevent path traversal.
func Clean(p string) string {
p = strings.ReplaceAll(p, `\`, "/")
return strings.Trim(path.Clean("/"+p), "/")
}

View File

@@ -12,38 +12,73 @@ import (
func TestClean(t *testing.T) {
tests := []struct {
path string
expVal string
path string
wantVal string
}{
{
path: "../../../readme.txt",
expVal: "readme.txt",
path: "../../../readme.txt",
wantVal: "readme.txt",
},
{
path: "a/../../../readme.txt",
expVal: "readme.txt",
path: "a/../../../readme.txt",
wantVal: "readme.txt",
},
{
path: "/../a/b/../c/../readme.txt",
expVal: "a/readme.txt",
path: "/../a/b/../c/../readme.txt",
wantVal: "a/readme.txt",
},
{
path: "/a/readme.txt",
expVal: "a/readme.txt",
path: "../../objects/info/..",
wantVal: "objects",
},
{
path: "/",
expVal: "",
path: "/a/readme.txt",
wantVal: "a/readme.txt",
},
{
path: "/",
wantVal: "",
},
{
path: "/a/b/c/readme.txt",
expVal: "a/b/c/readme.txt",
path: "/a/b/c/readme.txt",
wantVal: "a/b/c/readme.txt",
},
// Windows-specific
{
path: `..\..\..\readme.txt`,
wantVal: "readme.txt",
},
{
path: `a\..\..\..\readme.txt`,
wantVal: "readme.txt",
},
{
path: `\..\a\b\..\c\..\readme.txt`,
wantVal: "a/readme.txt",
},
{
path: `\a\readme.txt`,
wantVal: "a/readme.txt",
},
{
path: `..\..\..\../README.md`,
wantVal: "README.md",
},
{
path: `\`,
wantVal: "",
},
{
path: `\a\b\c\readme.txt`,
wantVal: `a/b/c/readme.txt`,
},
}
for _, test := range tests {
t.Run("", func(t *testing.T) {
assert.Equal(t, test.expVal, Clean(test.path))
t.Run(test.path, func(t *testing.T) {
assert.Equal(t, test.wantVal, Clean(test.path))
})
}
}

View File

@@ -23,6 +23,7 @@ import (
"gogs.io/gogs/internal/conf"
"gogs.io/gogs/internal/db"
"gogs.io/gogs/internal/lazyregexp"
"gogs.io/gogs/internal/pathutil"
"gogs.io/gogs/internal/tool"
)
@@ -99,7 +100,7 @@ func HTTPContexter() macaron.Handler {
!strings.Contains(action, "info/") &&
!strings.Contains(action, "HEAD") &&
!strings.Contains(action, "objects/") {
c.NotFound()
c.Error(http.StatusBadRequest, fmt.Sprintf("Unrecognized action %q", action))
return
}
@@ -402,15 +403,21 @@ func HTTP(c *HTTPContext) {
}
if route.method != c.Req.Method {
c.NotFound()
c.Error(http.StatusNotFound)
return
}
file := strings.TrimPrefix(reqPath, m[1]+"/")
dir, err := getGitRepoPath(m[1])
cleaned := pathutil.Clean(m[1])
if m[1] != "/"+cleaned {
c.Error(http.StatusBadRequest, "Request path contains suspicious characters")
return
}
file := strings.TrimPrefix(reqPath, cleaned)
dir, err := getGitRepoPath(cleaned)
if err != nil {
log.Warn("HTTP.getGitRepoPath: %v", err)
c.NotFound()
c.Error(http.StatusNotFound)
return
}
@@ -429,5 +436,5 @@ func HTTP(c *HTTPContext) {
return
}
c.NotFound()
c.Error(http.StatusNotFound)
}

View File

@@ -16,8 +16,8 @@ import (
// It is useful to mock "os/exec" functions in tests. When succeeded, it returns
// the result produced by the test helper.
// The test helper should:
// 1. Use WantHelperProcess function to determine if it is being called in helper mode.
// 2. Call fmt.Fprintln(os.Stdout, ...) to print results for the main test to collect.
// 1. Use WantHelperProcess function to determine if it is being called in helper mode.
// 2. Call fmt.Fprintln(os.Stdout, ...) to print results for the main test to collect.
func Exec(helper string, envs ...string) (string, error) {
cmd := exec.Command(os.Args[0], "-test.run="+helper, "--")
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}

View File

@@ -113,7 +113,7 @@
{{end}}
<p class="desc">
{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.HomeLink .Poster.DisplayName | Safe}}
{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.HomeLink .Poster.DisplayName | Sanitize | Safe}}
{{if .Milestone}}
<a class="milestone" href="{{$.Link}}?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{.Milestone.ID}}&assignee={{$.AssigneeID}}">
<span class="octicon octicon-milestone"></span> {{.Milestone.Name | Sanitize}}

View File

@@ -28,7 +28,7 @@
{{if .Submodule}}
<td>
<span class="octicon octicon-file-submodule"></span>
<a href="{{InferSubmoduleURL $.RepoLink .Submodule}}">{{.Entry.Name}} @ {{ShortSHA1 .Submodule.Commit}}</a>
<a href="{{InferSubmoduleURL $.RepoLink .Submodule}}">{{.Entry.Name}} {{if .Submodule.Commit}}@ {{ShortSHA1 .Submodule.Commit}}{{end}}</a>
</td>
{{else}}
<td class="name">