peter-toth commented on PR #57040:
URL: https://github.com/apache/spark/pull/57040#issuecomment-4907775814

   @gaogaotiantian the snippet tests `os.path.realpath`, but the extract loop 
uses `os.path.relpath` (to strip the leading `spark-x/` package dir), and 
`relpath` *emits* `..` rather than resolving it:
   
   ```python
   >>> os.path.relpath("spark-x/../../etc/evil", "spark-x/")
   '../../etc/evil'
   ```
   
   So `member.name` still contains `..` when it reaches `tar.extract(member, 
dest)` (no `filter`), which writes outside `dest`. Repro:
   
   ```python
   import io, os, tarfile, tempfile
   with tempfile.TemporaryDirectory() as tmp:
       dest = os.path.join(tmp, "dest"); os.makedirs(dest)
       p = os.path.join(tmp, "m.tar")
       with tarfile.open(p, "w") as t:
           info = tarfile.TarInfo("spark-x/../evil.txt"); info.size = 5
           t.addfile(info, io.BytesIO(b"pwned"))
       with tarfile.open(p) as t:
           for m in t.getmembers():
               m.name = os.path.relpath(m.name, "spark-x" + os.path.sep)
               t.extract(m, dest)
       print(os.path.exists(os.path.join(tmp, "evil.txt")))  # True -> escaped 
dest
   ```
   
   `realpath` *does* resolve `..` - which is exactly why a 
`realpath(os.path.join(dest, name))`-stays-under-`realpath(dest)` check is an 
effective, version-independent guard.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to