From 47ba644de78dd82cfaed205128bd34056aa99078 Mon Sep 17 00:00:00 2001 From: E Rasche Date: Mon, 28 Aug 2017 10:53:05 +0200 Subject: [PATCH 1/3] 2017-08 Security Patch --- lib/galaxy/datatypes/data.py | 30 ++++++++++++++++++------------ lib/galaxy/web/framework/base.py | 2 ++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py index 7d5ccc813e9..34bc20251d6 100644 --- a/lib/galaxy/datatypes/data.py +++ b/lib/galaxy/datatypes/data.py @@ -342,7 +342,7 @@ class Data( object ): except: mime = "text/plain" self._clean_and_set_mime_type( trans, mime ) - return open( file_path ) + return self._yield_user_file_content( trans, data, file_path ) else: return paste.httpexceptions.HTTPNotFound( "Could not find '%s' on the extra files path %s." % ( filename, file_path ) ) self._clean_and_set_mime_type( trans, data.get_mime() ) @@ -367,23 +367,29 @@ class Data( object ): max_peek_size = 10000000 # 10 MB for html preview = util.string_as_bool( preview ) if not preview or isinstance(data.datatype, datatypes.images.Image) or os.stat( data.file_name ).st_size < max_peek_size: - if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html": - # Sanitize anytime we respond with plain text/html content. - # Check to see if this dataset's parent job is whitelisted - # We cannot currently trust imported datasets for rendering. - if not data.creating_job.imported and data.creating_job.tool_id in trans.app.config.sanitize_whitelist: - return open(data.file_name).read() - # This is returning to the browser, it needs to be encoded. - # TODO Ideally this happens a layer higher, but this is a bad - # issue affecting many tools - return sanitize_html(open( data.file_name ).read()).encode('utf-8') - return open( data.file_name ) + return self._yield_user_file_content(trans, data, data.file_name) else: trans.response.set_content_type( "text/html" ) return trans.stream_template_mako( "/dataset/large_file.mako", truncated_data=open( data.file_name ).read(max_peek_size), data=data) + def _yield_user_file_content(self, trans, from_dataset, filename): + """This method is responsible for sanitizing the HTML if needed.""" + if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html": + # Sanitize anytime we respond with plain text/html content. + # Check to see if this dataset's parent job is whitelisted + # We cannot currently trust imported datasets for rendering. + if not from_dataset.creating_job.imported and from_dataset.creating_job.tool_id in trans.app.config.sanitize_whitelist: + return open(filename) + + # This is returning to the browser, it needs to be encoded. + # TODO Ideally this happens a layer higher, but this is a bad + # issue affecting many tools + return sanitize_html(open(filename).read()).encode('utf-8') + + return open(filename) + def display_name(self, dataset): """Returns formatted html of dataset name""" try: diff --git a/lib/galaxy/web/framework/base.py b/lib/galaxy/web/framework/base.py index e227a8080eb..a9a228672d6 100644 --- a/lib/galaxy/web/framework/base.py +++ b/lib/galaxy/web/framework/base.py @@ -406,6 +406,8 @@ class Response( object ): """ Send an HTTP redirect response to (target `url`) """ + if "\n" in url or "\r" in url: + raise httpexceptions.HTTPInternalServerError("Invalid redirect URL encountered.") raise httpexceptions.HTTPFound( url.encode('utf-8'), headers=self.wsgi_headeritems() ) def wsgi_headeritems( self ): From 5a18464d547d7497285ee25067050ee4cd665eda Mon Sep 17 00:00:00 2001 From: E Rasche Date: Mon, 28 Aug 2017 10:53:22 +0200 Subject: [PATCH 2/3] 2017-08 Security Patch --- lib/galaxy/datatypes/data.py | 30 ++++++++++++++++++------------ lib/galaxy/web/framework/base.py | 2 ++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py index 7d5ccc813e9..34bc20251d6 100644 --- a/lib/galaxy/datatypes/data.py +++ b/lib/galaxy/datatypes/data.py @@ -342,7 +342,7 @@ class Data( object ): except: mime = "text/plain" self._clean_and_set_mime_type( trans, mime ) - return open( file_path ) + return self._yield_user_file_content( trans, data, file_path ) else: return paste.httpexceptions.HTTPNotFound( "Could not find '%s' on the extra files path %s." % ( filename, file_path ) ) self._clean_and_set_mime_type( trans, data.get_mime() ) @@ -367,23 +367,29 @@ class Data( object ): max_peek_size = 10000000 # 10 MB for html preview = util.string_as_bool( preview ) if not preview or isinstance(data.datatype, datatypes.images.Image) or os.stat( data.file_name ).st_size < max_peek_size: - if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html": - # Sanitize anytime we respond with plain text/html content. - # Check to see if this dataset's parent job is whitelisted - # We cannot currently trust imported datasets for rendering. - if not data.creating_job.imported and data.creating_job.tool_id in trans.app.config.sanitize_whitelist: - return open(data.file_name).read() - # This is returning to the browser, it needs to be encoded. - # TODO Ideally this happens a layer higher, but this is a bad - # issue affecting many tools - return sanitize_html(open( data.file_name ).read()).encode('utf-8') - return open( data.file_name ) + return self._yield_user_file_content(trans, data, data.file_name) else: trans.response.set_content_type( "text/html" ) return trans.stream_template_mako( "/dataset/large_file.mako", truncated_data=open( data.file_name ).read(max_peek_size), data=data) + def _yield_user_file_content(self, trans, from_dataset, filename): + """This method is responsible for sanitizing the HTML if needed.""" + if trans.app.config.sanitize_all_html and trans.response.get_content_type() == "text/html": + # Sanitize anytime we respond with plain text/html content. + # Check to see if this dataset's parent job is whitelisted + # We cannot currently trust imported datasets for rendering. + if not from_dataset.creating_job.imported and from_dataset.creating_job.tool_id in trans.app.config.sanitize_whitelist: + return open(filename) + + # This is returning to the browser, it needs to be encoded. + # TODO Ideally this happens a layer higher, but this is a bad + # issue affecting many tools + return sanitize_html(open(filename).read()).encode('utf-8') + + return open(filename) + def display_name(self, dataset): """Returns formatted html of dataset name""" try: diff --git a/lib/galaxy/web/framework/base.py b/lib/galaxy/web/framework/base.py index e227a8080eb..a9a228672d6 100644 --- a/lib/galaxy/web/framework/base.py +++ b/lib/galaxy/web/framework/base.py @@ -406,6 +406,8 @@ class Response( object ): """ Send an HTTP redirect response to (target `url`) """ + if "\n" in url or "\r" in url: + raise httpexceptions.HTTPInternalServerError("Invalid redirect URL encountered.") raise httpexceptions.HTTPFound( url.encode('utf-8'), headers=self.wsgi_headeritems() ) def wsgi_headeritems( self ): From 02c77929852d99ed837e0599140d2b3f40d89767 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 6 Sep 2017 09:34:11 -0400 Subject: [PATCH 3/3] [16.01] Backport uwsgi fix from #2836. Now that newer releases require a library that the mere presence of breaks an older version of Galaxy, I think this will be encountered more during development. It is breaking Planemo's ability to switch between different versions of Galaxy. https://github.com/galaxyproject/galaxy/pull/2836 --- lib/galaxy/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/config.py b/lib/galaxy/config.py index 264a22e216b..58f4addec10 100644 --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -29,8 +29,10 @@ log = logging.getLogger( __name__ ) # uwsgi-managed process. try: import uwsgi - if uwsgi.numproc: + if hasattr(uwsgi, "numproc"): process_is_uwsgi = True + else: + process_is_uwsgi = False except ImportError: # This is not a uwsgi process, or something went horribly wrong. process_is_uwsgi = False