Skip to content

Commit c65b0c8

Browse files
authored
safer gettreesha (#449)
* safer gettreesha The `gittreesha` method executes external commands with parameters that could be external inputs. This validates some of the inputs and changes the way `Cmd` is constructed to make it safer. Added tests. * rebased and bumped patch version
1 parent 558d318 commit c65b0c8

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Registrator"
22
uuid = "4418983a-e44d-11e8-3aec-9789530b3b3e"
33
authors = ["Stefan Karpinski <[email protected]>"]
4-
version = "1.9.4"
4+
version = "1.9.5"
55

66
[deps]
77
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"

src/webui/gitutils.jl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ macro gf_bool(ex::Expr)
4141
end
4242
end
4343

44+
# disallowed patterns
45+
# ../, ..\, /.., \.., ./, .\, /./, \.\
46+
const PATH_TRAVERSAL = r"(?:\.{2,}[\/\\]|\.{1,}[\/\\]|[\/\\]\.{2,}|[\/\\]\.{1,}[\/\\])"
47+
function is_safe_clone_url(s)
48+
if occursin(PATH_TRAVERSAL, s)
49+
return false
50+
end
51+
return true
52+
end
53+
4454
# Split a repo path into its owner and name.
4555
function splitrepo(url::AbstractString)
4656
url = replace(url, r"(.*).git$" => s"\1")
@@ -242,12 +252,17 @@ function gettreesha(
242252
)
243253
return try
244254
url = cloneurl(r)
255+
if !is_safe_clone_url(url)
256+
throw(ArgumentError("Invalid or unsafe clone URL"))
257+
end
245258
mktempdir() do dir
246259
dest = joinpath(dir, r.name)
247260
withpasswd(url) do url, env
248-
run(Cmd(`git clone --bare $url $dest`; env))
261+
# let Cmd interpolate strings safely
262+
run(Cmd(Cmd(String["git", "clone", "--bare", string(url), dest]); env))
249263
end
250-
readchomp(`git -C $dest rev-parse $ref:$subdir`), ""
264+
# let Cmd interpolate strings safely
265+
readchomp(Cmd(String["git", "-C", dest, "rev-parse", "$ref:$subdir"]))
251266
end
252267
catch ex
253268
@error "Exception while getting tree SHA" exception=(ex, catch_backtrace())

test/webui/gitutils.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,41 @@ end
1313

1414
restoreconfig!()
1515

16+
@testset "gittreesha" begin
17+
org = GitHub.User(login="JuliaLang")
18+
19+
public_repo_of_org = GitHub.Repo(name="Example.jl", private=false, owner=org, organization=org, permissions = GitHub.Permissions(admin = true, push = false, pull = true), clone_url="https://github.com/JuliaLang/Example.jl.git")
20+
example_master_treesha = Base.redirect_stderr(devnull) do
21+
Registrator.WebUI.gettreesha(public_repo_of_org, "master", "")
22+
end
23+
@test length(example_master_treesha) == 40
24+
25+
ret, err = Base.redirect_stderr(devnull) do
26+
Registrator.WebUI.gettreesha(public_repo_of_org, "mas ter", "")
27+
end
28+
@test ret === nothing
29+
@test err == "Exception while getting tree SHA"
30+
31+
ret, err = Base.redirect_stderr(devnull) do
32+
Registrator.WebUI.gettreesha(public_repo_of_org, "master", "src/../test")
33+
end
34+
@test ret === nothing
35+
@test err == "Exception while getting tree SHA"
36+
37+
ret, err = Base.redirect_stderr(devnull) do
38+
Registrator.WebUI.gettreesha(public_repo_of_org, "master", "src test")
39+
end
40+
@test ret === nothing
41+
@test err == "Exception while getting tree SHA"
42+
43+
unsafe_repo = GitHub.Repo(name="Example.jl", private=false, owner=org, organization=org, permissions = GitHub.Permissions(admin = true, push = false, pull = true), clone_url="https://github.com/JuliaLang/../unsafe/Example.jl.git")
44+
ret, err = Base.redirect_stderr(devnull) do
45+
Registrator.WebUI.gettreesha(unsafe_repo, "master", "")
46+
end
47+
@test ret === nothing
48+
@test err == "Exception while getting tree SHA"
49+
end
50+
1651
@testset "isauthorized" begin
1752
@test isauthorized("username", "reponame") == AuthFailure("Unkown user type or repo type")
1853
mock_provider!()

0 commit comments

Comments
 (0)