# SPDX-License-Identifier: 0BSD
"""Security and fuzz tests for meshchatx://map and related lxm.ingest_uri deep links."""
import asyncio
import json
from unittest.mock import MagicMock, patch
from urllib.parse import quote, urlencode
import pytest
from hypothesis import HealthCheck, given, settings
from hypothesis import strategies as st
def _await_map_ingest(mock_app, uri: str):
mock_client = MagicMock()
mock_client.send_str = MagicMock(return_value=asyncio.sleep(0))
mock_app.message_router.ingest_lxm_uri = MagicMock()
async def _run():
with patch(
"meshchatx.meshchat.AsyncUtils.run_async",
side_effect=lambda coro: asyncio.create_task(coro),
):
await mock_app.on_websocket_data_received(
mock_client,
{"type": "lxm.ingest_uri", "uri": uri},
)
await asyncio.sleep(0)
asyncio.get_event_loop_policy().get_event_loop().run_until_complete(_run())
return mock_client
@pytest.mark.asyncio
async def test_lxm_ingest_map_uri_success(mock_app):
mock_client = MagicMock()
mock_client.send_str = MagicMock(return_value=asyncio.sleep(0))
mock_app.message_router.ingest_lxm_uri = MagicMock()
with patch(
"meshchatx.meshchat.AsyncUtils.run_async",
side_effect=lambda coro: asyncio.create_task(coro),
):
await mock_app.on_websocket_data_received(
mock_client,
{
"type": "lxm.ingest_uri",
"uri": "meshchatx://map?lat=12.5&lon=-45&z=7&layers=discovered&label=HQ",
},
)
await asyncio.sleep(0)
mock_app.message_router.ingest_lxm_uri.assert_not_called()
mock_client.send_str.assert_called_once()
payload = json.loads(mock_client.send_str.call_args[0][0])
assert payload["type"] == "lxm.ingest_uri.result"
assert payload["status"] == "success"
assert payload["ingest_type"] == "map_view"
mq = payload["map_query"]
assert mq["lat"] == 12.5
assert mq["lon"] == -45.0
assert mq["zoom"] == 7
assert mq["layers"] == "discovered"
assert mq["label"] == "HQ"
@pytest.mark.asyncio
async def test_lxm_ingest_map_meshchat_alias(mock_app):
mock_client = MagicMock()
mock_client.send_str = MagicMock(return_value=asyncio.sleep(0))
mock_app.message_router.ingest_lxm_uri = MagicMock()
with patch(
"meshchatx.meshchat.AsyncUtils.run_async",
side_effect=lambda coro: asyncio.create_task(coro),
):
await mock_app.on_websocket_data_received(
mock_client,
{"type": "lxm.ingest_uri", "uri": "meshchat://map?lat=0&lon=1&z=2"},
)
await asyncio.sleep(0)
payload = json.loads(mock_client.send_str.call_args[0][0])
assert payload["ingest_type"] == "map_view"
assert payload["map_query"]["lat"] == 0.0
assert payload["map_query"]["lon"] == 1.0
@pytest.mark.asyncio
async def test_lxm_ingest_map_zoom_clamped(mock_app):
mock_client = MagicMock()
mock_client.send_str = MagicMock(return_value=asyncio.sleep(0))
mock_app.message_router.ingest_lxm_uri = MagicMock()
with patch(
"meshchatx.meshchat.AsyncUtils.run_async",
side_effect=lambda coro: asyncio.create_task(coro),
):
await mock_app.on_websocket_data_received(
mock_client,
{"type": "lxm.ingest_uri", "uri": "meshchatx://map?lat=0&lon=0&z=999"},
)
await asyncio.sleep(0)
payload = json.loads(mock_client.send_str.call_args[0][0])
assert payload["map_query"]["zoom"] == 22
@pytest.mark.asyncio
async def test_lxm_ingest_map_invalid_lat_lon(mock_app):
mock_client = MagicMock()
mock_client.send_str = MagicMock(return_value=asyncio.sleep(0))
mock_app.message_router.ingest_lxm_uri = MagicMock()
with patch(
"meshchatx.meshchat.AsyncUtils.run_async",
side_effect=lambda coro: asyncio.create_task(coro),
):
await mock_app.on_websocket_data_received(
mock_client,
{"type": "lxm.ingest_uri", "uri": "meshchatx://map?lat=x&lon=1&z=3"},
)
await asyncio.sleep(0)
payload = json.loads(mock_client.send_str.call_args[0][0])
assert payload["status"] == "error"
assert "map" in payload["message"].lower()
mock_app.message_router.ingest_lxm_uri.assert_not_called()
@pytest.mark.parametrize(
"layers,label",
[
("", "safe"),
("discovered", "
"),
("javascript:alert(1)", "ping"),
("';DROP TABLE map;--", '">