Skip to content

Commit 1af8283

Browse files
committed
Feedback: validate sock-mode.
1 parent ee509ad commit 1af8283

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

notebook/notebookapp.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import select
2727
import signal
2828
import socket
29+
import stat
2930
import sys
3031
import tempfile
3132
import threading
@@ -759,7 +760,7 @@ def _default_ip(self):
759760
return 'localhost'
760761

761762
@validate('ip')
762-
def _valdate_ip(self, proposal):
763+
def _validate_ip(self, proposal):
763764
value = proposal['value']
764765
if value == u'*':
765766
value = u''
@@ -786,10 +787,28 @@ def _valdate_ip(self, proposal):
786787
help=_("The UNIX socket the notebook server will listen on.")
787788
)
788789

789-
sock_mode = Unicode(u'0600', config=True,
790-
help=_("The permissions mode/umask for UNIX socket creation (default: 0600).")
790+
sock_mode = Integer(int('0600', 8), config=True,
791+
help=_("The permissions mode for UNIX socket creation (default: 0600).")
791792
)
792793

794+
@validate('sock_mode')
795+
def _validate_sock_mode(self, proposal):
796+
value = proposal['value']
797+
try:
798+
converted_value = int(value.encode(), 8)
799+
# Ensure the mode is at least user readable/writable.
800+
assert all((
801+
bool(converted_value & stat.S_IRUSR),
802+
bool(converted_value & stat.S_IWUSR),
803+
))
804+
except ValueError:
805+
raise TraitError('invalid --sock-mode value: %s' % value)
806+
except AssertionError:
807+
raise TraitError(
808+
'invalid --sock-mode value: %s, must have u+rw (0600) at a minimum' % value
809+
)
810+
return converted_value
811+
793812
port_retries = Integer(50, config=True,
794813
help=_("The number of additional ports to try if the specified port is not available.")
795814
)
@@ -1616,7 +1635,7 @@ def _bind_http_server(self):
16161635

16171636
def _bind_http_server_unix(self):
16181637
try:
1619-
sock = bind_unix_socket(self.sock, mode=int(self.sock_mode.encode(), 8))
1638+
sock = bind_unix_socket(self.sock, mode=self.sock_mode)
16201639
self.http_server.add_socket(sock)
16211640
except socket.error as e:
16221641
if e.errno == errno.EADDRINUSE:

notebook/tests/test_notebookapp_integration.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ def test_shutdown_sock_server_integration():
1717
encoded_sock_path = urlencode_unix_socket_path(sock)
1818

1919
p = subprocess.Popen(
20-
['jupyter-notebook', '--sock=%s' % sock],
20+
['jupyter-notebook', '--sock=%s' % sock, '--sock-mode=0700'],
2121
stdout=subprocess.PIPE, stderr=subprocess.PIPE
2222
)
2323

24+
complete = False
2425
for line in iter(p.stderr.readline, b''):
26+
print(line)
2527
if url in line:
2628
complete = True
2729
break
@@ -30,8 +32,8 @@ def test_shutdown_sock_server_integration():
3032

3133
assert encoded_sock_path.encode() in subprocess.check_output(['jupyter-notebook', 'list'])
3234

33-
# Ensure default umask is properly applied.
34-
assert stat.S_IMODE(os.lstat(sock).st_mode) == 0o600
35+
# Ensure umask is properly applied.
36+
assert stat.S_IMODE(os.lstat(sock).st_mode) == 0o700
3537

3638
try:
3739
subprocess.check_output(['jupyter-notebook', 'stop'], stderr=subprocess.STDOUT)
@@ -49,6 +51,29 @@ def test_shutdown_sock_server_integration():
4951
p.wait()
5052

5153

54+
def test_sock_server_validate_sockmode_type():
55+
try:
56+
subprocess.check_output(
57+
['jupyter-notebook', '--sock=/tmp/nonexistent', '--sock-mode=badbadbad'],
58+
stderr=subprocess.STDOUT
59+
)
60+
except subprocess.CalledProcessError as e:
61+
assert 'badbadbad' in e.output.decode()
62+
else:
63+
raise AssertionError('expected execution to fail due to validation of --sock-mode param')
64+
65+
66+
def test_sock_server_validate_sockmode_accessible():
67+
try:
68+
subprocess.check_output(
69+
['jupyter-notebook', '--sock=/tmp/nonexistent', '--sock-mode=0444'],
70+
stderr=subprocess.STDOUT
71+
)
72+
except subprocess.CalledProcessError as e:
73+
assert '0444' in e.output.decode()
74+
else:
75+
raise AssertionError('expected execution to fail due to validation of --sock-mode param')
76+
5277

5378
def _ensure_stopped(check_msg='There are no running servers'):
5479
try:

0 commit comments

Comments
 (0)