How Shopify's AI Agent River Automates Vulnerability Remediation
River autonomously manages security flaws from detection to fix in Slack.
1River's Core Functionality
Shopify's AI agent River, operating in Slack, doesn't just detect security vulnerabilities but autonomously fixes them. While traditional systems can create PRs, they can't complete remediation. River works from the root of Shopify's monorepo 'World', using the same environments and conventions as developers. This shared infrastructure provides Shopify-specific context to security workflows from the outset.
2Gaps in Current Systems
Repositories can change while PRs await review; developers might add context altering fixes. A passing CI doesn't prove vulnerability removal. River bridges these gaps: it checks current code, updates patches when safe, involves right engineers for decisions, and tracks work post-handoff. Post-merge, it verifies repo head and dependency graph before marking work complete.
3Striking Results
In the first 11 days of dependency workflow, open issue backlog dropped by 70%. Two-thirds were direct merges; rest marked obsolete or fixed elsewhere. Security merges in freshness-gated queue jumped from 10% to 80%. This addresses the least-discussed aspect of agentic patching: operating the remediation pipeline around the diff.
4Defensive Asymmetry
Attackers tolerate repeated failures while defenders (especially organizations) must preserve production behavior with every fix. This asymmetry motivates our transparency: attackers reuse techniques, while sharing our work strengthens security. We aim to raise the baseline for all building agentic security workflows, preventing hard lessons.
5Two Distinct Workflows
Dependency and first-party app vulnerability remediation start differently. Dependency work typically begins with a PR upgrading vulnerable dependencies. App vulnerabilities start with agent-discovered findings and fix recommendations potentially needing deeper investigation. Both then follow identical remediation loops.
6Slack Thread Coordination
River creates one Slack thread per app vulnerability finding. For dependencies, it groups related upgrade PRs affecting the same code area. In one recent operation, 4 threads opened within a minute, covering 35 findings across codebases - each proceeding independently through rebasing, CI triggering, and Q&A without waiting for others.
7Ledger vs. Ground Truth
Each run starts by reconciling the ledger against live repo, PR, and vulnerability-tracker states. The ledger serves as memory but isn't operational truth - it might show PRs as open after merging or work ongoing on closed PRs. Therefore River treats every ledger entry as a claim requiring verification, not fact.
8Active Vulnerability Verification
River confirms vulnerabilities remain active before code changes. For dependencies, it checks if affected code still resolves to vulnerable versions or if sibling PRs fulfilled upgrades. For app vulnerabilities, it locates current repo, confirms code still matches findings at head, and searches PR systems for in-flight fixes. When systems can't be exhaustively searched, handoffs explicitly state this.
9Handling Incomplete Systems
If another change already fixed the issue, River records evidence and stops. Technically correct patches based on stale premises waste engineering time and risk unnecessary production changes. River only modifies code after confirming active vulnerabilities, preventing such waste.
10Dependency Upgrade Process
For stale dependency upgrades, River replays upgrades on repo head, regenerates lockfiles with repo's own tooling, and repairs mechanical failures. This ensures patches align with current codebase while automatically resolving potential conflicts. Developers are only consulted for critical decisions, streamlining the process.
11Shared Context for Future
Slack threads preserve not just run transcripts but investigation and handoff contexts. This enables River, security engineers, and code owners to leverage shared understanding for future fixes. While the pipeline appears simple when diagrammed, the real engineering challenge lies in transitions between states - where complexity truly resides.