Files
Spoolman/tests/test_configjs.py
T
Donkie 72daa29cd2 security: finish the audit's low-severity items
Task 10: config.js JSON-encodes the base path, so a backslash cannot
escape the string literal the way the old " check allowed; search.py
escapes LIKE wildcards at both its call sites, using a helper moved into
database/utils.py so it and extra_field_query share one implementation.

Task 9 was a pair of decisions rather than fixes. /info keeps its paths:
both clients render them and removing response fields breaks API v1, while
the disclosure buys nothing against an API that is unauthenticated anyway.
/metrics keeps its shape but now says what it publishes when switched on.

Also pins the unit tests to a throwaway data directory -- importing
spoolman.main creates one as a side effect, and it was the real one.
2026-07-31 09:42:32 +02:00

50 lines
1.9 KiB
Python

"""Tests for the generated config.js, which interpolates the operator's base path into JS."""
import json
import pytest
from spoolman import main
def render(monkeypatch: pytest.MonkeyPatch, base_path: str) -> str:
"""Render config.js for the given base path, through the real endpoint."""
monkeypatch.setattr(main, "base_path", base_path)
return main.get_configjs().body.decode()
def value_of(rendered: str) -> str:
"""Parse back the JS string literal the endpoint produced."""
literal = rendered.split(" = ", 1)[1].strip().rstrip(";")
return json.loads(literal)
def test_an_ordinary_base_path_round_trips(monkeypatch: pytest.MonkeyPatch):
assert value_of(render(monkeypatch, "/spoolman")) == "/spoolman"
def test_an_empty_base_path_round_trips(monkeypatch: pytest.MonkeyPatch):
assert value_of(render(monkeypatch, "")) == ""
def test_a_quote_cannot_close_the_literal(monkeypatch: pytest.MonkeyPatch):
"""The old hand-quoting caught this case, by refusing to serve at all."""
assert value_of(render(monkeypatch, '/spool"man')) == '/spool"man'
def test_a_trailing_backslash_cannot_escape_the_closing_quote(monkeypatch: pytest.MonkeyPatch):
"""The case hand-quoting missed: the backslash would have escaped the terminating quote."""
rendered = render(monkeypatch, "/spoolman\\")
assert rendered.strip() == 'window.SPOOLMAN_BASE_PATH = "/spoolman\\\\";'
assert value_of(rendered) == "/spoolman\\"
def test_a_backslash_quote_pair_cannot_inject_a_statement(monkeypatch: pytest.MonkeyPatch):
assert value_of(render(monkeypatch, '/spoolman\\";alert(1);//')) == '/spoolman\\";alert(1);//'
def test_a_newline_cannot_break_out_of_the_statement(monkeypatch: pytest.MonkeyPatch):
rendered = render(monkeypatch, "/spool\nman")
assert "\n" not in rendered.split(" = ", 1)[1].strip()
assert value_of(rendered) == "/spool\nman"