Skip to content

Commit cbfa15f

Browse files
committed
Merge branch 'safe-PATH-lookup-in-gitk-on-Windows'
This topic branch extends the protections introduced for Git GUI's CVE-2022-41953 to cover `gitk`, too. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 2f66709 + 26550a9 commit cbfa15f

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

gitk-git/gitk

+135
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,141 @@ exec wish "$0" -- "$@"
99

1010
package require Tk
1111

12+
######################################################################
13+
##
14+
## Enabling platform-specific code paths
15+
16+
proc is_MacOSX {} {
17+
if {[tk windowingsystem] eq {aqua}} {
18+
return 1
19+
}
20+
return 0
21+
}
22+
23+
proc is_Windows {} {
24+
if {$::tcl_platform(platform) eq {windows}} {
25+
return 1
26+
}
27+
return 0
28+
}
29+
30+
set _iscygwin {}
31+
proc is_Cygwin {} {
32+
global _iscygwin
33+
if {$_iscygwin eq {}} {
34+
if {[string match "CYGWIN_*" $::tcl_platform(os)]} {
35+
set _iscygwin 1
36+
} else {
37+
set _iscygwin 0
38+
}
39+
}
40+
return $_iscygwin
41+
}
42+
43+
######################################################################
44+
##
45+
## PATH lookup
46+
47+
set _search_path {}
48+
proc _which {what args} {
49+
global env _search_exe _search_path
50+
51+
if {$_search_path eq {}} {
52+
if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} {
53+
set _search_path [split [exec cygpath \
54+
--windows \
55+
--path \
56+
--absolute \
57+
$env(PATH)] {;}]
58+
set _search_exe .exe
59+
} elseif {[is_Windows]} {
60+
set gitguidir [file dirname [info script]]
61+
regsub -all ";" $gitguidir "\\;" gitguidir
62+
set env(PATH) "$gitguidir;$env(PATH)"
63+
set _search_path [split $env(PATH) {;}]
64+
# Skip empty `PATH` elements
65+
set _search_path [lsearch -all -inline -not -exact \
66+
$_search_path ""]
67+
set _search_exe .exe
68+
} else {
69+
set _search_path [split $env(PATH) :]
70+
set _search_exe {}
71+
}
72+
}
73+
74+
if {[is_Windows] && [lsearch -exact $args -script] >= 0} {
75+
set suffix {}
76+
} else {
77+
set suffix $_search_exe
78+
}
79+
80+
foreach p $_search_path {
81+
set p [file join $p $what$suffix]
82+
if {[file exists $p]} {
83+
return [file normalize $p]
84+
}
85+
}
86+
return {}
87+
}
88+
89+
proc sanitize_command_line {command_line from_index} {
90+
set i $from_index
91+
while {$i < [llength $command_line]} {
92+
set cmd [lindex $command_line $i]
93+
if {[file pathtype $cmd] ne "absolute"} {
94+
set fullpath [_which $cmd]
95+
if {$fullpath eq ""} {
96+
throw {NOT-FOUND} "$cmd not found in PATH"
97+
}
98+
lset command_line $i $fullpath
99+
}
100+
101+
# handle piped commands, e.g. `exec A | B`
102+
for {incr i} {$i < [llength $command_line]} {incr i} {
103+
if {[lindex $command_line $i] eq "|"} {
104+
incr i
105+
break
106+
}
107+
}
108+
}
109+
return $command_line
110+
}
111+
112+
# Override `exec` to avoid unsafe PATH lookup
113+
114+
rename exec real_exec
115+
116+
proc exec {args} {
117+
# skip options
118+
for {set i 0} {$i < [llength $args]} {incr i} {
119+
set arg [lindex $args $i]
120+
if {$arg eq "--"} {
121+
incr i
122+
break
123+
}
124+
if {[string range $arg 0 0] ne "-"} {
125+
break
126+
}
127+
}
128+
set args [sanitize_command_line $args $i]
129+
uplevel 1 real_exec $args
130+
}
131+
132+
# Override `open` to avoid unsafe PATH lookup
133+
134+
rename open real_open
135+
136+
proc open {args} {
137+
set arg0 [lindex $args 0]
138+
if {[string range $arg0 0 0] eq "|"} {
139+
set command_line [string trim [string range $arg0 1 end]]
140+
lset args 0 "| [sanitize_command_line $command_line 0]"
141+
}
142+
uplevel 1 real_open $args
143+
}
144+
145+
# End of safe PATH lookup stuff
146+
12147
proc hasworktree {} {
13148
return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
14149
[exec git rev-parse --is-inside-git-dir] == "false"}]

0 commit comments

Comments
 (0)