Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.

Unreleased
===========================
* **Security fix.** A query link carrying parameters (``?params=id:5``) ran the query on a plain
page view. The parameter values travel with the link rather than coming from the person who
opened it, so a shared link could execute SQL in that person's session without them taking any
action. Parameterized queries loaded from the URL now wait for an explicit "Save & Run". Queries
with no URL parameters, and the ``EXPLORER_AUTORUN_QUERY_WITH_PARAMS`` behaviour, are unchanged.

* `#722`_: The query list (home page) no longer loads the entire query log history on every view. Run counts and
last runs are computed in SQL, so the page stays fast as logs accumulate (300k logs: ~9.7s -> ~0.9s). The query
list and query log pages also no longer run an extra database query per row.
Expand Down
4 changes: 4 additions & 0 deletions docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ parameters before hitting "Save & Run"

EXPLORER_AUTORUN_QUERY_WITH_PARAMS = False

Note that queries whose parameters arrive in the URL (``?params=id:5``) are never run on a plain
page view, regardless of this setting. Those parameters come with the link rather than from the
person who opened it, so the query waits for an explicit "Save & Run".

There are a handful of features (snapshots, emailing queries) that
rely on Celery and the dependencies in optional-requirements.txt. If
you have Celery installed, set ``EXPLORER_TASKS_ENABLED=True`` in your
Expand Down
26 changes: 26 additions & 0 deletions explorer/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,32 @@ def test_admin_required(self):
)
self.assertTemplateUsed(resp, "admin/login.html")

def test_url_supplied_params_do_not_autorun(self):
# Params in the URL travel with the link, so viewing it must not execute their SQL.
query = SimpleQueryFactory(sql="select 'MARKER$$p:x$$' as v;")
resp = self.client.get(
reverse("query_detail", kwargs={"query_id": query.id}),
{"params": "p:x"}
)
self.assertNotContains(resp, "MARKERx")

def test_url_supplied_params_do_not_autorun_even_when_autorun_enabled(self):
query = SimpleQueryFactory(sql="select 'MARKER$$p:x$$' as v;")
with self.settings(EXPLORER_AUTORUN_QUERY_WITH_PARAMS=True):
resp = self.client.get(
reverse("query_detail", kwargs={"query_id": query.id}),
{"params": "p:x"}
)
self.assertNotContains(resp, "MARKERx")

def test_query_without_url_params_still_autoruns(self):
# The documented default behaviour is unaffected when the link carries no params.
query = SimpleQueryFactory(sql="select 'MARKER' as v;")
resp = self.client.get(
reverse("query_detail", kwargs={"query_id": query.id})
)
self.assertContains(resp, "MARKER")

def test_admin_required_with_explorer_no_permission_setting(self):
self.client.logout()
query = SimpleQueryFactory()
Expand Down
5 changes: 5 additions & 0 deletions explorer/views/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ def get(self, request, query_id):
params = query.available_params()
if not app_settings.EXPLORER_AUTORUN_QUERY_WITH_PARAMS and params:
show = False
# Parameters carried in the URL come with the link, not from the person who opened it.
# Running them on a plain page view turns any shared query link into a way to execute
# SQL in the visitor's session, so require an explicit action (Save & Run) instead.
if url_get_params(request):
show = False
try:
vm = query_viewmodel(
request,
Expand Down
Loading