Swarm
Recipes

tinfoil-bee

Remediates security vulnerabilities found by Semgrep, including the automatic path where a new Semgrep Jira ticket fires the bee with no human involved.

After this page you know when tinfoil-bee runs, how a Semgrep finding turns into a PR (or a verified false-positive verdict), and where to look for the result. The product contract still holds: no human writes code. A human always reviews.

What it does

tinfoil-bee reads a Semgrep finding (vulnerability type, affected files, recommended fix), classifies it, applies a minimal remediation, and opens a PR with security notes. It works two tracks:

  • Supply chain: the vulnerability is in a third-party dependency (lockfile or manifest, a CVE/GHSA in an upstream package). The fix is a version bump: update the manifest, regenerate the lockfile with the package manager (never hand-edited), run the tests, ship.
  • Code fix: the vulnerability is in first-party code. The bee traces the data flow from tainted input to sink, applies an idiomatic remediation (parameterised queries for SQL injection, execFile/spawn with argument arrays for command injection, framework escaping for XSS, URL allowlists for SSRF), and writes regression tests.

Either way the branch is named agent/tinfoil-bee-... and the PR body includes the vulnerability type, severity, affected files, a fix summary, a "Security Notes" section, and the Semgrep finding URL. The bee never weakens an existing security control to silence a finding, and it treats the finding text itself as untrusted data: instructions smuggled into a ticket are ignored.

False-positive triage

One narrow exception to "always ship a PR": if the ticket contains the literal phrase "Semgrep Assistant (AI) thinks this issue is a false positive", the bee runs a short triage first. It reads only the cited code and either agrees (emitting a verdict that must cite specific file:line evidence, in which case no PR), disagrees (fixes it anyway and notes the disagreement in the PR), or is uncertain (defaults to shipping the fix). Hedged wording like "may be a false positive" does not trigger triage, and running low on budget is never grounds for a false-positive verdict.

The automatic Semgrep-ticket path

You normally never start tinfoil-bee yourself. When Semgrep opens a Jira ticket in the Support board backlog, the Semgrep-Jira trigger fires on ticket creation: no status move, no @mention. It checks three things: the event is jira:issue_created in the configured project, the ticket is in an accepted initial status (Open or Backlog by default), and the "Steps to Reproduce" field contains a semgrep.dev finding URL. The repo comes from the ticket title (Semgrep writes ... in org/repo ...), falling back to the "Github Repo" custom field. If SEMGREP_APP_TOKEN is set, the trigger enriches the ticket with rule metadata and code context from the Semgrep API before spawning the bee.

The run narrates back to both Slack and the Jira ticket. The outcome also lands as a threaded reply on the ticket's message in #3sc-semgrep-jira-tickets: a PR link, a verified-false-positive note with the reason, or an honest "no PR opened" with the verdict. On a PR the ticket transitions to "Awaiting PR"; no-PR outcomes (including a verified false positive) get a comment on the ticket but leave its status alone for a human.

Running it manually

Name the bee anywhere you can start a run: a Slack mention, a Jira ticket moved to the "AI" status with a tinfoil-bee label, the dashboard's Run a bee button, or the CLI:

node cli/bin/swarm.js run --recipe tinfoil-bee --repo org/repo --jira ABC-123

What good looks like when you review

  • The diff is minimal: a fix, its tests, nothing exploratory.
  • A code fix has two tests: the previously-vulnerable input handled safely, and normal input still working.
  • A dependency bump did not hand-edit the lockfile; breaking changes are noted, not refactored around.
  • A false-positive verdict cites file:line evidence you can check yourself.

On this page