feat: add n8n serve node and harden remote access
- Add the n8n community node package with credentials, command mapping, direct serve TCP client, and browser-cli protocol crypto helpers. - Cover Ed25519 signing, canonical JSON, PQ transport encryption, request mapping, and security behavior with unit tests. - Harden serve-http with per-address rate limiting, an 8 MB request body cap, and clear warnings when binding plain HTTP beyond loopback. - Stop one-shot --key overrides from being persisted automatically; document explicit remote trust and keep key-management behind the keys policy tier. - Make HTML-to-Markdown conversion safer by bounding tree depth and dropping unsafe link/image URL schemes. - Bump package and extension release metadata to 0.16.3.
This commit is contained in:
@@ -357,6 +357,48 @@ def test_serve_http_uses_compare_digest():
|
||||
assert "compare_digest" in src
|
||||
assert "== f\"Bearer" not in src
|
||||
|
||||
def test_serve_http_rate_limiter_blocks_when_exhausted():
|
||||
"""A burst-1 limiter lets the first request through, then sends 429."""
|
||||
from browser_cli.commands.serve_http import _Handler
|
||||
from browser_cli.serve.security import RateLimiter
|
||||
|
||||
handler = _Handler.__new__(_Handler)
|
||||
handler.client_address = ("203.0.113.5", 5000)
|
||||
handler.rate_limiter = RateLimiter(rate=0.001, burst=1)
|
||||
sent = []
|
||||
handler._send = lambda status, payload: sent.append((status, payload))
|
||||
|
||||
assert handler._within_rate_limit() is True
|
||||
assert handler._within_rate_limit() is False
|
||||
assert sent and sent[-1][0] == 429
|
||||
|
||||
def test_serve_http_rate_limiter_none_never_limits():
|
||||
from browser_cli.commands.serve_http import _Handler
|
||||
|
||||
handler = _Handler.__new__(_Handler)
|
||||
handler.client_address = ("203.0.113.5", 5000)
|
||||
handler.rate_limiter = None
|
||||
assert all(handler._within_rate_limit() for _ in range(100))
|
||||
|
||||
def test_serve_http_default_rate_limit_active():
|
||||
from browser_cli.commands.serve_http import _Handler
|
||||
|
||||
with patch("browser_cli.commands.serve_http.BrowserCLI"), \
|
||||
patch("browser_cli.commands.serve_http.ThreadingHTTPServer") as server_cls:
|
||||
server_cls.return_value.serve_forever.side_effect = KeyboardInterrupt
|
||||
CliRunner().invoke(main, ["serve-http", "--no-auth"])
|
||||
# The handler class passed to the server carries an active RateLimiter by default.
|
||||
handler_cls = server_cls.call_args.args[1]
|
||||
assert handler_cls.rate_limiter is not None
|
||||
assert handler_cls.rate_limiter.rate == 100.0
|
||||
|
||||
def test_serve_http_non_loopback_warns_about_cleartext():
|
||||
with patch("browser_cli.commands.serve_http.BrowserCLI"), \
|
||||
patch("browser_cli.commands.serve_http.ThreadingHTTPServer") as server_cls:
|
||||
server_cls.return_value.serve_forever.side_effect = KeyboardInterrupt
|
||||
result = CliRunner().invoke(main, ["serve-http", "--host", "0.0.0.0", "--token", "x"])
|
||||
assert "clear text" in result.output
|
||||
|
||||
def test_command_policy_allow_all_grants_everything():
|
||||
policy = command_policy_from_options(
|
||||
allow_read_page=False, allow_control=False, allow_dangerous=False, allow_all=True
|
||||
|
||||
Reference in New Issue
Block a user