diff options
Diffstat (limited to 'packages/meshbay-node/tests/test_security_regressions.py')
| -rw-r--r-- | packages/meshbay-node/tests/test_security_regressions.py | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/packages/meshbay-node/tests/test_security_regressions.py b/packages/meshbay-node/tests/test_security_regressions.py index 6bb680c..dcd9cf6 100644 --- a/packages/meshbay-node/tests/test_security_regressions.py +++ b/packages/meshbay-node/tests/test_security_regressions.py @@ -579,3 +579,26 @@ def test_admin_ui_escapes_filenames(tmp_path): assert payload not in html, "filename rendered unescaped — stored XSS (H2)" assert "<img" in html, "filename should appear escaped" + +def test_admin_ui_escapes_roster_usernames(tmp_path): + """ + H2 again, for the roster: usernames originate at the hub and land on the + operator's own admin page, which can re-key groups and read the audit log. + """ + from meshbay_node.ui.app import _render_page + + payload = '<img src=x onerror="fetch(1)">' + html = _render_page( + {"status": "running", "groups_ctx": {}, "indexes": {}}, + { + "identities": {"u1": {"user_id": "u1", "username": payload, + "pk_ed25519": "AAA", "pinned_at": "now", + "pinned_via": "code"}}, + "members": [{"group_id": "", "user_id": "u1", "role": "operator", + "status": "active"}], + "invites": [], + }, + ) + + assert payload not in html, "username rendered unescaped — stored XSS (H2)" + assert "<img" in html |