[kupfer: 7/27] archiveinside: Don't unarchive unsafe archives. Support ZIP
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [kupfer: 7/27] archiveinside: Don't unarchive unsafe archives. Support ZIP
- Date: Tue, 16 Feb 2010 20:47:42 +0000 (UTC)
commit 0e3d2214cfa1404b7e81781dfef95b7b074e6096
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Fri Jan 22 21:21:19 2010 +0100
archiveinside: Don't unarchive unsafe archives. Support ZIP
We add in a brake for safe archives: Archives that contain paths
starting with / or .. are potentially malicious, yet Python's standard
library's extractall will happily extract them.
We support ZIP, but only in Python 2.6 where .extractall() is
available.
kupfer/plugin/archiveinside.py | 34 ++++++++++++++++++++++++++++------
1 files changed, 28 insertions(+), 6 deletions(-)
---
diff --git a/kupfer/plugin/archiveinside.py b/kupfer/plugin/archiveinside.py
index b15f0c1..c70e520 100644
--- a/kupfer/plugin/archiveinside.py
+++ b/kupfer/plugin/archiveinside.py
@@ -2,10 +2,8 @@
A test project to see if we can make a plugin that allows us to
drill down into compressed archives.
-Issues to resolve:
-
- * Add option to clean up at Kupfer's exit
- * Handle zip, tar.gz and anything we can
+So far we only support .zip and .tar, .tar.gz, .tar.bz2, using Python's
+standard library.
"""
__kupfer_name__ = _("Deep Archives")
__kupfer_contents__ = ("ArchiveContent", )
@@ -42,15 +40,39 @@ def extractor(name, extensions, predicate):
return func
return decorator
+
+class UnsafeArchiveError (Exception):
+ def __init__(self, path):
+ Exception.__init__(self, "Refusing to extract unsafe path: %s" % path)
+
+def is_safe_to_unarchive(path):
+ "return whether @path is likely a safe path to unarchive"
+ npth = os.path.normpath(path)
+ return not os.path.isabs(npth) and not npth.startswith(os.path.pardir)
+
@extractor("tar", (".tar", ".tar.gz", ".tgz", ".tar.bz2"), tarfile.is_tarfile)
def extract_tarfile(filepath, destpath):
zf = tarfile.TarFile.open(filepath, 'r')
- zf.extractall(path=destpath)
+ try:
+ for member in zf.getnames():
+ if not is_safe_to_unarchive(member):
+ raise UnsafeArchiveError(member)
+ zf.extractall(path=destpath)
+ finally:
+ zf.close()
+# ZipFile only supports extractall since Python 2.6
@extractor("zip", (".zip", ), zipfile.is_zipfile)
def extract_zipfile(filepath, destpath):
- raise NotImplementedError
+ zf = zipfile.ZipFile(filepath, 'r')
+ try:
+ for member in zf.namelist():
+ if not is_safe_to_unarchive(member):
+ raise UnsafeArchiveError(member)
+ zf.extractall(path=destpath)
+ finally:
+ zf.close()
class ArchiveContent (Source):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]