mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-04 08:28:36 +00:00
fix: cap rendered webhook thread keys
This commit is contained in:
parent
f67506dadf
commit
806ab0ce33
@ -2009,7 +2009,7 @@ Common template variables:
|
||||
| `webhooks.routes.<name>.to` | empty | Required target address in `channel:chat` format. |
|
||||
| `webhooks.routes.<name>.events` | `[]` | Optional provider event-name allowlist. For GitHub this matches `X-GitHub-Event`, such as `pull_request`. |
|
||||
| `webhooks.routes.<name>.actions` | `[]` | Optional JSON payload `action` allowlist, such as `opened` or `synchronize`. |
|
||||
| `webhooks.routes.<name>.thread` | empty | Optional Jinja template for the session key. Defaults to `to`. |
|
||||
| `webhooks.routes.<name>.thread` | empty | Optional Jinja template for the session key. Defaults to `to`; rendered values are capped at 512 characters. |
|
||||
| `webhooks.routes.<name>.prompt` | empty | Optional Jinja template for the inbound agent message. |
|
||||
| `webhooks.routes.<name>.sender` | `webhook` | Sender ID placed on the inbound message. |
|
||||
| `webhooks.routes.<name>.maxBodyBytes` | `1048576` | Maximum request body size, from 1 KiB to 10 MiB. |
|
||||
|
||||
@ -19,6 +19,7 @@ from nanobot.utils.helpers import truncate_text
|
||||
|
||||
_HMAC_PREFIX = "sha256="
|
||||
_DEFAULT_PROMPT_MAX_CHARS = 24_000
|
||||
_DEFAULT_THREAD_MAX_CHARS = 512
|
||||
_REDACTED_HEADERS = {
|
||||
"authorization",
|
||||
"cookie",
|
||||
@ -494,7 +495,10 @@ def _render_thread(route: WebhookRouteConfig, context: dict[str, Any]) -> str:
|
||||
rendered = _jinja().from_string(template).render(**context)
|
||||
except TemplateError as exc:
|
||||
raise WebhookError(400, f"webhook thread template failed: {exc}") from exc
|
||||
return rendered.strip()
|
||||
rendered = rendered.strip()
|
||||
if len(rendered) > _DEFAULT_THREAD_MAX_CHARS:
|
||||
raise WebhookError(400, "webhook thread template rendered too long")
|
||||
return rendered
|
||||
|
||||
|
||||
def _jinja() -> Environment:
|
||||
|
||||
@ -218,6 +218,47 @@ async def test_webhook_custom_path_and_thread_template() -> None:
|
||||
assert msg.session_key_override == "deploy:api:delivery-2"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_webhook_rejects_overlong_thread_template_without_dedupe() -> None:
|
||||
bus = MessageBus()
|
||||
router = WebhookRouter(
|
||||
WebhooksConfig(
|
||||
routes={
|
||||
"deploy": WebhookRouteConfig(
|
||||
auth="none",
|
||||
to="websocket:ops",
|
||||
thread="deploy:{{ event.thread }}",
|
||||
prompt="Deploy {{ event.service }}",
|
||||
)
|
||||
}
|
||||
),
|
||||
bus,
|
||||
)
|
||||
|
||||
failed = await router.handle(
|
||||
method="POST",
|
||||
path="/webhooks/deploy",
|
||||
headers={"X-Nanobot-Delivery": "delivery-3"},
|
||||
body=json.dumps({"service": "api", "thread": "x" * 600}).encode(),
|
||||
)
|
||||
accepted = await router.handle(
|
||||
method="POST",
|
||||
path="/webhooks/deploy",
|
||||
headers={"X-Nanobot-Delivery": "delivery-3"},
|
||||
body=json.dumps({"service": "api", "thread": "release"}).encode(),
|
||||
)
|
||||
|
||||
assert failed is not None
|
||||
assert failed.status == 400
|
||||
assert "thread template rendered too long" in failed.body["error"]
|
||||
assert accepted is not None
|
||||
assert accepted.status == 202
|
||||
assert accepted.body["queued"] is True
|
||||
assert bus.inbound_size == 1
|
||||
msg = await bus.consume_inbound()
|
||||
assert msg.session_key_override == "deploy:release"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_github_webhook_validates_signature_and_dedupes_delivery() -> None:
|
||||
bus = MessageBus()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user