#909 App-originated tool calls silently bypass rate limiting and per-workflow circuit-breaker isolation (ProxyDurableContext is not a DurableContext)

open high bug Created 2026-08-22 12:04 · Updated 2026-08-22 12:04

Description

Edit
EARS SPEC: - While an app action is executing, when it invokes a rate-limited tool, the Highway engine shall apply the same rate limit that applies when a workflow invokes that tool directly. - While an app action is executing, when it invokes a circuit-broken tool, the Highway engine shall apply per-workflow-run circuit-breaker isolation using the real workflow_run_id. - If a decorator cannot resolve a usable context, then the Highway engine shall fail closed or log at WARNING, and shall not silently skip the control. - The Highway engine shall have a test proving the rate limit BLOCKS an app-originated call once the cap is exceeded, not only that it permits one. EVIDENCE (static, verified): - enterprise/ipc/proxy.py:23 - ProxyDurableContext sets self.workflow_run_id = 'proxy-placeholder'; it does NOT subclass DurableContext. - enterprise/ipc/proxy.py:36-42 - __getattr__ returns a method_proxy callable for ANY unknown attribute, so proxy.tenant_id evaluates to a FUNCTION OBJECT rather than a string, and never raises. - docker/highway-core/engine/tools/decorators/rate_limit.py:139-141 - 'if not isinstance(ctx, DurableContext): return func(*args, **kwargs)' -> rate limiting is skipped entirely for the proxy. - docker/highway-core/engine/tools/decorators/circuit_breaker.py:163-165 - 'if isinstance(ctx, DurableContext)' is False for the proxy, so workflow_run_id stays None and per-workflow CB isolation is lost. - enterprise/apps/sdk/context_net.py:155-161 - AppContext.send_email calls send_email_tool(ctx=self._ctx, ...) IN THE CHILD with the proxy as ctx. - enterprise/tools/email_tool.py:238 - send_email_tool is decorated @with_rate_limit('tools.email.send', priority_kwarg='priority'). IMPACT: tools.email.send is rate-limited when a workflow calls it and UNLIMITED when an app calls ctx.send_email. Same for any @with_rate_limit tool reachable from the app SDK. A tenant-facing quota control is off on one path with no log line. NOT YET DONE: no live reproduction (api container was down during analysis). Reproduce by installing an app that loops ctx.send_email past the configured cap and confirming no 429/limit error.

Comments

Loading comments...

Context

Loading context...

Audit History

View All
Loading audit history...