|
14 | 14 | importsignal
|
15 | 15 | fromsubprocessimportPopen,PIPE,DEVNULL
|
16 | 16 | importsubprocess
|
| 17 | +importsys |
17 | 18 | importthreading
|
18 | 19 | fromtextwrapimportdedent
|
19 | 20 |
|
@@ -220,67 +221,67 @@ def pump_stream(
|
220 | 221 | finalizer(process)
|
221 | 222 |
|
222 | 223 |
|
223 |
| -def_safer_popen_windows( |
224 |
| -command:Union[str,Sequence[Any]], |
225 |
| -*, |
226 |
| -shell:bool=False, |
227 |
| -env:Optional[Mapping[str,str]]=None, |
228 |
| -**kwargs:Any, |
229 |
| -)->Popen: |
230 |
| -"""Call :class:`subprocess.Popen` on Windows but don't include a CWD in the search. |
231 |
| -
|
232 |
| - This avoids an untrusted search path condition where a file like ``git.exe`` in a |
233 |
| - malicious repository would be run when GitPython operates on the repository. The |
234 |
| - process using GitPython may have an untrusted repository's working tree as its |
235 |
| - current working directory. Some operations may temporarily change to that directory |
236 |
| - before running a subprocess. In addition, while by default GitPython does not run |
237 |
| - external commands with a shell, it can be made to do so, in which case the CWD of |
238 |
| - the subprocess, which GitPython usually sets to a repository working tree, can |
239 |
| - itself be searched automatically by the shell. This wrapper covers all those cases. |
| 224 | +safer_popen:Callable[...,Popen] |
240 | 225 |
|
241 |
| - :note: |
242 |
| - This currently works by setting the :envvar:`NoDefaultCurrentDirectoryInExePath` |
243 |
| - environment variable during subprocess creation. It also takes care of passing |
244 |
| - Windows-specific process creation flags, but that is unrelated to path search. |
| 226 | +ifsys.platform=="win32": |
245 | 227 |
|
246 |
| - :note: |
247 |
| - The current implementation contains a race condition on :attr:`os.environ`. |
248 |
| - GitPython isn't thread-safe, but a program using it on one thread should ideally |
249 |
| - be able to mutate :attr:`os.environ` on another, without unpredictable results. |
250 |
| - See comments in https://github.com/gitpython-developers/GitPython/pull/1650. |
251 |
| - """ |
252 |
| -# CREATE_NEW_PROCESS_GROUP is needed for some ways of killing it afterwards. See: |
253 |
| -# https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal |
254 |
| -# https://docs.python.org/3/library/subprocess.html#subprocess.CREATE_NEW_PROCESS_GROUP |
255 |
| -creationflags=subprocess.CREATE_NO_WINDOW|subprocess.CREATE_NEW_PROCESS_GROUP |
256 |
| - |
257 |
| -# When using a shell, the shell is the direct subprocess, so the variable must be |
258 |
| -# set in its environment, to affect its search behavior. (The "1" can be any value.) |
259 |
| -ifshell: |
260 |
| -# The original may be immutable or reused by the caller. Make changes in a copy. |
261 |
| -env= {}ifenvisNoneelsedict(env) |
262 |
| -env["NoDefaultCurrentDirectoryInExePath"]="1" |
263 |
| - |
264 |
| -# When not using a shell, the current process does the search in a CreateProcessW |
265 |
| -# API call, so the variable must be set in our environment. With a shell, this is |
266 |
| -# unnecessary, in versions where https://github.com/python/cpython/issues/101283 is |
267 |
| -# patched. If that is unpatched, then in the rare case the ComSpec environment |
268 |
| -# variable is unset, the search for the shell itself is unsafe. Setting |
269 |
| -# NoDefaultCurrentDirectoryInExePath in all cases, as is done here, is simpler and |
270 |
| -# protects against that. (As above, the "1" can be any value.) |
271 |
| -withpatch_env("NoDefaultCurrentDirectoryInExePath","1"): |
272 |
| -returnPopen( |
273 |
| -command, |
274 |
| -shell=shell, |
275 |
| -env=env, |
276 |
| -creationflags=creationflags, |
277 |
| -**kwargs, |
278 |
| - ) |
| 228 | +def_safer_popen_windows( |
| 229 | +command:Union[str,Sequence[Any]], |
| 230 | +*, |
| 231 | +shell:bool=False, |
| 232 | +env:Optional[Mapping[str,str]]=None, |
| 233 | +**kwargs:Any, |
| 234 | + )->Popen: |
| 235 | +"""Call :class:`subprocess.Popen` on Windows but don't include a CWD in the search. |
| 236 | +
|
| 237 | + This avoids an untrusted search path condition where a file like ``git.exe`` in a |
| 238 | + malicious repository would be run when GitPython operates on the repository. The |
| 239 | + process using GitPython may have an untrusted repository's working tree as its |
| 240 | + current working directory. Some operations may temporarily change to that directory |
| 241 | + before running a subprocess. In addition, while by default GitPython does not run |
| 242 | + external commands with a shell, it can be made to do so, in which case the CWD of |
| 243 | + the subprocess, which GitPython usually sets to a repository working tree, can |
| 244 | + itself be searched automatically by the shell. This wrapper covers all those cases. |
279 | 245 |
|
| 246 | + :note: |
| 247 | + This currently works by setting the :envvar:`NoDefaultCurrentDirectoryInExePath` |
| 248 | + environment variable during subprocess creation. It also takes care of passing |
| 249 | + Windows-specific process creation flags, but that is unrelated to path search. |
280 | 250 |
|
281 |
| -safer_popen:Callable[...,Popen] |
| 251 | + :note: |
| 252 | + The current implementation contains a race condition on :attr:`os.environ`. |
| 253 | + GitPython isn't thread-safe, but a program using it on one thread should ideally |
| 254 | + be able to mutate :attr:`os.environ` on another, without unpredictable results. |
| 255 | + See comments in https://github.com/gitpython-developers/GitPython/pull/1650. |
| 256 | + """ |
| 257 | +# CREATE_NEW_PROCESS_GROUP is needed for some ways of killing it afterwards. See: |
| 258 | +# https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal |
| 259 | +# https://docs.python.org/3/library/subprocess.html#subprocess.CREATE_NEW_PROCESS_GROUP |
| 260 | +creationflags=subprocess.CREATE_NO_WINDOW|subprocess.CREATE_NEW_PROCESS_GROUP |
| 261 | + |
| 262 | +# When using a shell, the shell is the direct subprocess, so the variable must be |
| 263 | +# set in its environment, to affect its search behavior. (The "1" can be any value.) |
| 264 | +ifshell: |
| 265 | +# The original may be immutable or reused by the caller. Make changes in a copy. |
| 266 | +env= {}ifenvisNoneelsedict(env) |
| 267 | +env["NoDefaultCurrentDirectoryInExePath"]="1" |
| 268 | + |
| 269 | +# When not using a shell, the current process does the search in a CreateProcessW |
| 270 | +# API call, so the variable must be set in our environment. With a shell, this is |
| 271 | +# unnecessary, in versions where https://github.com/python/cpython/issues/101283 is |
| 272 | +# patched. If that is unpatched, then in the rare case the ComSpec environment |
| 273 | +# variable is unset, the search for the shell itself is unsafe. Setting |
| 274 | +# NoDefaultCurrentDirectoryInExePath in all cases, as is done here, is simpler and |
| 275 | +# protects against that. (As above, the "1" can be any value.) |
| 276 | +withpatch_env("NoDefaultCurrentDirectoryInExePath","1"): |
| 277 | +returnPopen( |
| 278 | +command, |
| 279 | +shell=shell, |
| 280 | +env=env, |
| 281 | +creationflags=creationflags, |
| 282 | +**kwargs, |
| 283 | + ) |
282 | 284 |
|
283 |
| -ifos.name=="nt": |
284 | 285 | safer_popen=_safer_popen_windows
|
285 | 286 | else:
|
286 | 287 | safer_popen=Popen
|
|