claude.yml workflow triggers on substring match, fires on incidental @​claude* strings in quoted text

Open 💬 2 comments Opened Jun 10, 2026 by hiroki-tamba-research

claude.yml workflow triggers on substring match, fires on incidental @claude* strings in quoted text

Summary

The claude.yml workflow's trigger condition uses contains(github.event.comment.body, '@claude'), which is a case-insensitive substring match. This fires on any comment containing the character sequence @claude anywhere in the body — including quoted text, code blocks, and unrelated mentions like @ClaudeDevs.

Observed behavior

On 2026-06-10T02:05:38Z, I posted a comment on #66273 that quoted cluster-document text containing the string @ClaudeDevs (referencing the official account's rate-limit reset announcement). Four seconds later, the workflow dispatched run #191875:

| Time (UTC) | Event |
|---|---|
| 02:05:38 | Comment posted (contains @ClaudeDevs in quoted text) |
| 02:05:42 | claude.yml triggered (issue_commentcontains(body, '@claude') matched) |
| 02:06:10 | Run failed at "Run Claude Code" step (28s) |

The failure is at the claude-code-action step — presumably because external contributors don't have write access. The workflow ran, consumed CI minutes, checked out the repo, and only failed at the action execution stage.

Root cause

if: |
  (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
  ...

GitHub Actions' contains() is a case-insensitive substring match (docs). It does not parse @mentions — it matches the literal character sequence anywhere in the string. So:

  • @claude ✓ (intended)
  • @Claude ✓ (intended, probably)
  • @ClaudeDevs ✓ (unintended — inside quoted text)
  • @claude-code ✓ (unintended)
  • ` @claude ` in a code block ✓ (unintended)
  • mailto:claude@example.com ✓ (unintended)

Suggested fix

A few options, in increasing precision:

  1. Word-boundary check — not natively available in GitHub Actions expressions, but achievable with a preliminary step that runs a regex (\b@claude\b) and sets an output.
  1. Exact-mention check via github.event.comment.body — GitHub doesn't expose parsed mentions in the webhook payload, but a script step could parse Markdown to distinguish mentions from quoted/code-block occurrences.
  1. Actor filter — add github.event.comment.author_association check to skip comments from users who can't invoke the bot (e.g., NONE, FIRST_TIME_CONTRIBUTOR):

``yaml
if: |
github.event.comment.author_association != 'NONE' &&
github.event.comment.author_association != 'FIRST_TIME_CONTRIBUTOR' &&
contains(github.event.comment.body, '@claude')
`
This doesn't fix the substring issue but prevents the most common false-trigger path (external reporters quoting text with
@claude*`).

  1. Combination: actor filter + word-boundary regex in a preliminary step.

Impact

  • Wasted CI minutes on guaranteed-to-fail runs
  • Confusing failure notifications for external reporters (the Actions tab shows a red ✗ that looks like it's related to the comment itself)
  • If the permission gate were ever loosened, the bot would respond to unintended triggers

Environment

  • Workflow: .github/workflows/claude.yml (current main)
  • Triggered run: #191875 — conclusion: failure, duration: 28s
  • Triggering comment: #66273 (comment)
  • Action: anthropics/claude-code-action@v1, model: claude-sonnet-4-5-20250929

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗