diff --git a/nbgitpuller/config.py b/nbgitpuller/config.py new file mode 100644 index 0000000..c113be4 --- /dev/null +++ b/nbgitpuller/config.py @@ -0,0 +1,17 @@ +from traitlets import Bool +from traitlets.config import Configurable + + +class NbGitPullerFeatures(Configurable): + """ + Traitlet used to configure enabling / disabling various nbgitpuller features + """ + enable_targetpath = Bool( + False, + config=True, + help=""" + Allow setting `targetPath` in the url to specify where the repo should be cloned. + + Set to False to disable, for higher security + """ + ) diff --git a/nbgitpuller/handlers.py b/nbgitpuller/handlers.py index 2e57276..0b02279 100644 --- a/nbgitpuller/handlers.py +++ b/nbgitpuller/handlers.py @@ -1,6 +1,7 @@ from tornado import gen, web, locks import traceback import urllib.parse +from textwrap import dedent import threading import json @@ -11,6 +12,7 @@ from .pull import GitPuller from .version import __version__ from ._compat import get_base_handler +from .config import NbGitPullerFeatures JupyterHandler = get_base_handler() @@ -46,6 +48,15 @@ async def emit(self, data): @web.authenticated async def get(self): + features = NbGitPullerFeatures(parent=self.settings['nbapp']) + + if not features.enable_targetpath and self.get_argument('targetpath', None) is not None: + error_text = dedent(""" + targetPath is set in the URL, but NbGitPullerFeatures.enable_targetpath is set to False. + Please remove targetPath from the URL, or configure NbGitPullerFeatures.enable_targetpath to True. + """) + raise web.HTTPError(403, error_text) + try: await self.git_lock.acquire(1) except gen.TimeoutError: @@ -139,17 +150,34 @@ class UIHandler(JupyterHandler): async def get(self): app_env = os.getenv('NBGITPULLER_APP', default='notebook') + features = NbGitPullerFeatures(parent=self.settings['nbapp']) + repo = self.get_argument('repo') branch = self.get_argument('branch', None) depth = self.get_argument('depth', None) urlPath = self.get_argument('urlpath', None) or \ self.get_argument('urlPath', None) - subPath = self.get_argument('subpath', None) or \ - self.get_argument('subPath', '.') app = self.get_argument('app', app_env) parent_reldir = os.getenv('NBGITPULLER_PARENTPATH', '') + + # Defaults are set below, as these can be disabled targetpath = self.get_argument('targetpath', None) or \ - self.get_argument('targetPath', repo.split('/')[-1]) + self.get_argument('targetPath', None) + subPath = self.get_argument('subpath', None) or \ + self.get_argument('subPath', None) + + if not features.enable_targetpath: + if targetpath is not None and subPath is not None: + error_text = dedent(""" + targetPath is set in the URL, but NbGitPullerFeatures.enable_targetpath is set to False. + Please remove targetPath from the URL, or configure NbGitPullerFeatures.enable_targetpath to True. + """) + raise web.HTTPError(403, error_text) + + if targetpath is None: + targetpath = repo.split('/')[-1] + if subPath is None: + subPath = '.' if urlPath: path = urlPath diff --git a/nbgitpuller/pull.py b/nbgitpuller/pull.py index f5a7dab..2207591 100644 --- a/nbgitpuller/pull.py +++ b/nbgitpuller/pull.py @@ -4,7 +4,7 @@ import time import argparse import datetime -from traitlets import Integer, default +from traitlets import Integer, Bool, default from traitlets.config import Configurable from functools import partial @@ -69,6 +69,7 @@ def _depth_default(self): where the GitPuller class hadn't been loaded already.""" return int(os.environ.get('NBGITPULLER_DEPTH', 1)) + def __init__(self, git_url, repo_dir, **kwargs): assert git_url