Critical severityNVD Advisory· Published Sep 29, 2015· Updated May 6, 2026
CVE-2015-7337
CVE-2015-7337
Description
The editor in IPython Notebook before 3.2.2 and Jupyter Notebook 4.0.x before 4.0.5 allows remote attackers to execute arbitrary JavaScript code via a crafted file, which triggers a redirect to files/, related to MIME types.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
notebookPyPI | >= 4.0.0, < 4.0.5 | 4.0.5 |
ipythonPyPI | < 3.2.2 | 3.2.2 |
Patches
20a8096adf165Merge edit-redirect fix for 3.x
5 files changed · +22 −20
IPython/html/files/handlers.py+5 −0 modified@@ -40,6 +40,11 @@ def get(self, path): cur_mime = mimetypes.guess_type(name)[0] if cur_mime is not None: self.set_header('Content-Type', cur_mime) + else: + if model['format'] == 'base64': + self.set_header('Content-Type', 'application/octet-stream') + else: + self.set_header('Content-Type', 'text/plain') if model['format'] == 'base64': b64_bytes = model['content'].encode('ascii')
IPython/html/services/contents/filemanager.py+7 −5 modified@@ -277,18 +277,20 @@ def _file_model(self, path, content=True, format=None): model['type'] = 'file' os_path = self._get_os_path(path) + model['mimetype'] = mimetypes.guess_type(os_path)[0] if content: content, format = self._read_file(os_path, format) - default_mime = { - 'text': 'text/plain', - 'base64': 'application/octet-stream' - }[format] + if model['mimetype'] is None: + default_mime = { + 'text': 'text/plain', + 'base64': 'application/octet-stream' + }[format] + model['mimetype'] = default_mime model.update( content=content, format=format, - mimetype=mimetypes.guess_type(os_path)[0] or default_mime, ) return model
IPython/html/services/contents/handlers.py+0 −3 modified@@ -52,9 +52,6 @@ def validate_model(model, expect_content): ) maybe_none_keys = ['content', 'format'] - if model['type'] == 'file': - # mimetype should be populated only for file models - maybe_none_keys.append('mimetype') if expect_content: errors = [key for key in maybe_none_keys if model[key] is None] if errors:
IPython/html/static/edit/js/editor.js+3 −12 modified@@ -90,19 +90,10 @@ function($, }).catch( function(error) { that.events.trigger("file_load_failed.Editor", error); - if (((error.xhr||{}).responseJSON||{}).reason === 'bad format') { - window.location = utils.url_path_join( - that.base_url, - 'files', - that.file_path - ); - } else { - console.warn('Error while loading: the error was:') - console.warn(error) - } + console.warn('Error loading: ', error); cm.setValue("Error! " + error.message + "\nSaving disabled.\nSee Console for more details."); - cm.setOption('readOnly','nocursor') + cm.setOption('readOnly','nocursor'); that.save_enabled = false; } ); @@ -186,7 +177,7 @@ function($, Editor.prototype._clean_state = function(){ var clean = this.codemirror.isClean(this.generation); if (clean === this.clean){ - return + return; } else { this.clean = clean; }
IPython/html/static/tree/js/notebooklist.js+7 −0 modified@@ -532,6 +532,13 @@ define([ icon = 'running_' + icon; } var uri_prefix = NotebookList.uri_prefixes[model.type]; + if (model.type === 'file' && + model.mimetype && model.mimetype.substr(0,5) !== 'text/' + ) { + // send text/unidentified files to editor, others go to raw viewer + uri_prefix = 'files'; + } + item.find(".item_icon").addClass(icon).addClass('icon-fixed-width'); var link = item.find("a.item_link") .attr('href',
9e63dd89b603Merge edit-redirect fix into 4.0.x
5 files changed · +22 −20
notebook/files/handlers.py+5 −0 modified@@ -40,6 +40,11 @@ def get(self, path): cur_mime = mimetypes.guess_type(name)[0] if cur_mime is not None: self.set_header('Content-Type', cur_mime) + else: + if model['format'] == 'base64': + self.set_header('Content-Type', 'application/octet-stream') + else: + self.set_header('Content-Type', 'text/plain') if model['format'] == 'base64': b64_bytes = model['content'].encode('ascii')
notebook/services/contents/filemanager.py+7 −5 modified@@ -278,18 +278,20 @@ def _file_model(self, path, content=True, format=None): model['type'] = 'file' os_path = self._get_os_path(path) + model['mimetype'] = mimetypes.guess_type(os_path)[0] if content: content, format = self._read_file(os_path, format) - default_mime = { - 'text': 'text/plain', - 'base64': 'application/octet-stream' - }[format] + if model['mimetype'] is None: + default_mime = { + 'text': 'text/plain', + 'base64': 'application/octet-stream' + }[format] + model['mimetype'] = default_mime model.update( content=content, format=format, - mimetype=mimetypes.guess_type(os_path)[0] or default_mime, ) return model
notebook/services/contents/handlers.py+0 −3 modified@@ -55,9 +55,6 @@ def validate_model(model, expect_content): ) maybe_none_keys = ['content', 'format'] - if model['type'] == 'file': - # mimetype should be populated only for file models - maybe_none_keys.append('mimetype') if expect_content: errors = [key for key in maybe_none_keys if model[key] is None] if errors:
notebook/static/edit/js/editor.js+3 −12 modified@@ -90,19 +90,10 @@ function($, }).catch( function(error) { that.events.trigger("file_load_failed.Editor", error); - if (((error.xhr||{}).responseJSON||{}).reason === 'bad format') { - window.location = utils.url_path_join( - that.base_url, - 'files', - that.file_path - ); - } else { - console.warn('Error while loading: the error was:') - console.warn(error) - } + console.warn('Error loading: ', error); cm.setValue("Error! " + error.message + "\nSaving disabled.\nSee Console for more details."); - cm.setOption('readOnly','nocursor') + cm.setOption('readOnly','nocursor'); that.save_enabled = false; } ); @@ -186,7 +177,7 @@ function($, Editor.prototype._clean_state = function(){ var clean = this.codemirror.isClean(this.generation); if (clean === this.clean){ - return + return; } else { this.clean = clean; }
notebook/static/tree/js/notebooklist.js+7 −0 modified@@ -540,6 +540,13 @@ define([ icon = 'running_' + icon; } var uri_prefix = NotebookList.uri_prefixes[model.type]; + if (model.type === 'file' && + model.mimetype && model.mimetype.substr(0,5) !== 'text/' + ) { + // send text/unidentified files to editor, others go to raw viewer + uri_prefix = 'files'; + } + item.find(".item_icon").addClass(icon).addClass('icon-fixed-width'); var link = item.find("a.item_link") .attr('href',
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/advisories/GHSA-92mr-v722-f48mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2015-7337ghsaADVISORY
- lists.fedoraproject.org/pipermail/package-announce/2015-September/167670.htmlnvdWEB
- seclists.org/oss-sec/2015/q3/558nvdWEB
- seclists.org/oss-sec/2015/q3/634nvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/ipython/ipython/commit/0a8096adf165e2465550bd5893d7e352544e5967nvdWEB
- github.com/jupyter/notebook/commit/9e63dd89b603dfbe3a7e774d8a962ee0fa30c0b5nvdWEB
- github.com/pypa/advisory-database/tree/main/vulns/ipython/PYSEC-2015-25.yamlghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/notebook/PYSEC-2015-27.yamlghsaWEB
- security.gentoo.org/glsa/201512-02nvdWEB
News mentions
0No linked articles in our index yet.