Skip to content

v0.25.0

Choose a tag to compare

@airut-app airut-app released this 27 May 15:16
· 9 commits to main since this release
Immutable release. Only release title and notes can be modified.
0b557a8

Highlights

Slack channel mode — Airut now engages in Slack public and private channels via @-mention, not just DMs. Mention the bot in a thread and it joins the conversation; a sticky-thread rule lets follow-ups land without re-mentioning, and a mid-thread mention replays prior thread context (≤200 messages) into Claude's first prompt. Channel work is acknowledged with a :eyes: reaction on arrival that swaps to :white_check_mark: (success) or :x: (failure) on completion. Inbound Slack tokens are resolved to human-readable names and outbound @name/#name/@group references are rewritten back to live Slack mentions. An optional per-repo allowed_channels allowlist scopes which channels the bot will engage in (empty = any invited channel; DMs always bypass it). (#595, #598, #599, #601, #602, #603, #604, #605)

Gateway message coalescing — Messages that arrive while a conversation is busy are now merged into a single pending follow-up instead of being queued and rejected once the queue filled. Bursts are folded into one task with per-sender [<sender> <timestamp>] attribution headers, so a flurry of messages during a long run becomes one coherent prompt. This is channel-agnostic — it applies to email and Slack alike — and on Slack it pairs with a prep-window-scoped working status so the composer stays unlocked and follow-ups can flow. (#597, #601, #602)

Anthropic server-side-tool domain enforcement — A new proxy mitigation closes an exfiltration channel where an agent could use Anthropic's server-side fetcher tools (web_fetch_*, web_search_*, code_execution_*, etc.) to read URLs the airut network allowlist denies — the fetch happens from Anthropic's egress, so the proxy never sees it. The proxy now parses /v1/messages request bodies and trims each tool's allowed_domains to the intersection with hosts the allowlist already permits, rejecting blocked_domains and wildcard entries. Addresses a 2026-04-27 pentest that captured a network-blocked canary this way. (#587, #596)

Security Fixes

Continuing the proxy hardening series, closing further pentest-reported bypasses:

  • GraphQL multi-repo enumeration — The GitHub App repo-scope checker caught singular repository(owner, name) but not plural enumeration paths like organization.repositories.nodes, viewer.repositories, or Query.search(type: REPOSITORY), letting an in-scope token read any repo the installation could see. A new fail-secure layer blocks the repositories/forks connections and Query.search. Also fixes case-sensitive *Id matching that hid GitHub's lowercase Query.nodes(ids:). (#586)
  • Backslash path traversal/repos/airutorg/airut\..\website slipped past the /../ traversal check (forward-slash only) while GitHub upstream normalized it as traversal, widening the installation token's blast radius beyond the configured repos. The proxy now rejects any backslash in the request path after percent-decoding. (#585)

Other Changes

  • Session-recovery fix — The fresh-session retry created after a context-compaction failure omitted the Claude binary bind-mount, so the container died with exit 127 and surfaced only a generic error. The recovery task now mounts the binary like the initial task. (#600)
  • RFC 2047 attachment filenames — Non-ASCII attachment filenames sent as encoded-words (e.g. from Outlook) are now decoded before being saved, so downstream tooling finds them by their human-readable name. (#583)
  • Request-body filter pipeline — Refactored the proxy's service-specific body inspection (GraphQL operation allowlist, Anthropic tool-domain trim) into a registry-based pipeline so new payload filters are one small class plus a registry entry. (#596)
  • Dependency bumps across the main and proxy lockfiles, including urllib3 2.7.0 (GHSA-qccp-gfcp-xxvc, GHSA-mf9v-mfxr-j63j) and idna 3.15 (GHSA-65pc-fj4g-8rjx). (#584, #588, #591, #593) Resolved the disputed PYSEC-2025-183 PyJWT advisory handling. (#592, #594)
  • Documentation cleanup ahead of the release: synced the Slack flow in doc/architecture.md to channel mode, corrected proxy method names in spec/network-sandbox.md, and trimmed spec/anthropic-tool-domain-trim.md to contract level. (#606)

Upgrade

airut update

To enable Slack channel mode (optional — DM-only setups are unaffected): update your Slack app from config/slack-app-manifest.json to grant the new scopes (app_mentions:read, channels:history, groups:history, reactions:write) and subscribe to the new events (app_mention, message.channels, message.groups), then reinstall the app to your workspace. See doc/slack-setup.md.

If airut check reports a pending config schema migration after updating, run airut migrate.