Skip to content

Commit

Permalink
only require trusted host for evalex
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed May 5, 2024
1 parent 71b69df commit 890b6b6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
25 changes: 20 additions & 5 deletions src/werkzeug/debug/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

from .._internal import _log
from ..exceptions import NotFound
from ..exceptions import SecurityError
from ..http import parse_cookie
from ..sansio.utils import host_is_trusted
from ..security import gen_salt
from ..utils import send_file
from ..wrappers.request import Request
Expand Down Expand Up @@ -352,7 +354,7 @@ def debug_application(

is_trusted = bool(self.check_pin_trust(environ))
html = tb.render_debugger_html(
evalex=self.evalex,
evalex=self.evalex and self.check_host_trust(environ),
secret=self.secret,
evalex_trusted=is_trusted,
)
Expand Down Expand Up @@ -380,6 +382,9 @@ def execute_command( # type: ignore[return]
frame: DebugFrameSummary | _ConsoleFrame,
) -> Response:
"""Execute a command in a console."""
if not self.check_host_trust(request.environ):
return SecurityError() # type: ignore[return-value]

contexts = self.frame_contexts.get(id(frame), [])

with ExitStack() as exit_stack:
Expand All @@ -390,6 +395,9 @@ def execute_command( # type: ignore[return]

def display_console(self, request: Request) -> Response:
"""Display a standalone shell."""
if not self.check_host_trust(request.environ):
return SecurityError() # type: ignore[return-value]

if 0 not in self.frames:
if self.console_init_func is None:
ns = {}
Expand Down Expand Up @@ -442,12 +450,18 @@ def check_pin_trust(self, environ: WSGIEnvironment) -> bool | None:
return None
return (time.time() - PIN_TIME) < ts

def check_host_trust(self, environ: WSGIEnvironment) -> bool:
return host_is_trusted(environ.get("HTTP_HOST"), self.trusted_hosts)

def _fail_pin_auth(self) -> None:
time.sleep(5.0 if self._failed_pin_auth > 5 else 0.5)
self._failed_pin_auth += 1

def pin_auth(self, request: Request) -> Response:
"""Authenticates with the pin."""
if not self.check_host_trust(request.environ):
return SecurityError() # type: ignore[return-value]

exhausted = False
auth = False
trust = self.check_pin_trust(request.environ)
Expand Down Expand Up @@ -497,8 +511,11 @@ def pin_auth(self, request: Request) -> Response:
rv.delete_cookie(self.pin_cookie_name)
return rv

def log_pin_request(self) -> Response:
def log_pin_request(self, request: Request) -> Response:
"""Log the pin if needed."""
if not self.check_host_trust(request.environ):
return SecurityError() # type: ignore[return-value]

if self.pin_logging and self.pin is not None:
_log(
"info", " * To enable the debugger you need to enter the security pin:"
Expand All @@ -514,8 +531,6 @@ def __call__(
# form data! Otherwise the application won't have access to that data
# any more!
request = Request(environ)
request.trusted_hosts = self.trusted_hosts
assert request.host # will raise 400 error if not trusted
response = self.debug_application
if request.args.get("__debugger__") == "yes":
cmd = request.args.get("cmd")
Expand All @@ -527,7 +542,7 @@ def __call__(
elif cmd == "pinauth" and secret == self.secret:
response = self.pin_auth(request) # type: ignore
elif cmd == "printpin" and secret == self.secret:
response = self.log_pin_request() # type: ignore
response = self.log_pin_request(request) # type: ignore
elif (
self.evalex
and cmd is not None
Expand Down
2 changes: 1 addition & 1 deletion src/werkzeug/sansio/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from ..urls import uri_to_iri


def host_is_trusted(hostname: str, trusted_list: t.Iterable[str]) -> bool:
def host_is_trusted(hostname: str | None, trusted_list: t.Iterable[str]) -> bool:
"""Check if a host matches a list of trusted names.
:param hostname: The name to check.
Expand Down

0 comments on commit 890b6b6

Please sign in to comment.