Skip to content

v0.24.0

Choose a tag to compare

@airut-app airut-app released this 15 Apr 12:51
· 41 commits to main since this release
Immutable release. Only release title and notes can be modified.
3fafb10

Highlights

GraphQL repository scoping — GitHub App installation tokens can perform GraphQL mutations on any public repository, creating an exfiltration channel where a sandboxed agent could post secrets to attacker-controlled issues. The proxy now resolves configured repository node IDs at token refresh time and rejects any GraphQL mutation targeting an out-of-scope repository. A second defense layer decodes GitHub node IDs in all *Id input fields to verify repository ownership, catching mutations like addComment(subjectId: ...) that don't use repositoryId directly. Unrecognized node ID formats are blocked by default (fail-secure). (#533, #545, #565)

GraphQL operation allowlist — A new default-deny operation filter for GraphQL endpoints at the proxy layer. The network-allowlist.yaml graphql block lets you whitelist queries, mutations, and subscriptions by top-level field name using fnmatch patterns. This closes the gap where mutations using non-repositoryId targeting fields could bypass repository scope checking entirely — Layer 1 blocks the operation before Layer 2 (repository scoping) even runs. (#544, #548, #552)

Security Fixes

This release addresses findings from a comprehensive security review of the network proxy:

  • AWS secret key exposure — The real AWS secret access key was passed to the container environment instead of a surrogate, contrary to spec. The proxy re-signs from scratch and never needs the container's copy. Now all three credential components are surrogated. (#556)
  • Path traversal bypass — URL paths containing /../ segments (including percent-encoded variants) could bypass URL-prefix allowlist restrictions. The proxy now rejects path traversal sequences after decoding. (#557)
  • Duplicate header bypass — Duplicate HTTP headers (e.g., two Authorization entries) could evade token replacement: only the first value was inspected, letting an attacker's duplicate survive. A new collapse step keeps only the replaced entry across all credential paths. (#559, #566)
  • Race condition in flow matching — A shared mutable variable for the matched URL entry meant concurrent proxy flows could overwrite each other's match. Replaced with per-flow metadata. (#555)
  • GraphQL scope bypass via encoded path — Percent-encoding characters in the /graphql path (e.g., /%67raphql) skipped scope validation while still getting the real token injected. (#543)
  • GraphQL scope bypass via list variables — List-of-dict GraphQL variables (e.g., [{"repositoryId": "R_evil"}]) were not recursed into, allowing scope restrictions to be bypassed. (#562)
  • Case-insensitive host matching — Domain matching in the allowlist was case-sensitive, contrary to RFC 4343. A crafted Host: API.GITHUB.COM could bypass allowlist rules. (#560)
  • GraphQL body size limit — The repository scope checker lacked the 1 MiB body size limit that the operation checker enforced, allowing CPU exhaustion via oversized GraphQL payloads. (#558)
  • DNS compression pointer injection — The DNS parser accepted compression pointers (label bytes >= 0xC0), which could cause reads beyond the question section on crafted packets. (#564)
  • AWS signing encoding fix — Multi-byte UTF-8 characters in S3 paths produced invalid percent-encoding, causing signature mismatches (fail-closed, not a security bypass). (#561)
  • Presigned URL re-signing — The canonical request used the surrogate credential instead of the real one, producing invalid signatures (fail-closed). (#563)

Other Changes

  • Added enable property to scheduled tasks, allowing tasks to be disabled without removing them from config. (#542)
  • Centralized proxy logging to one ALLOWED/BLOCKED line per request, eliminating duplicates and contradictory log entries. (#541)
  • Documented that only GitHub App credentials protect against public repo exfiltration via GraphQL; classic PATs provide no protection. (#538)
  • Updated .airut/README.md with GraphQL filtering, wildcard hosts, and credential scope documentation. (#554)
  • Added sandbox escape pentest workflow for repeatable penetration testing of sandbox isolation. (#529)

Upgrade

airut update

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