claude.yml workflow triggers on substring match, fires on incidental @claude* strings in quoted text
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_comment → contains(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:
- 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.
- 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.
- Actor filter — add
github.event.comment.author_associationcheck 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')
@claude*`).
This doesn't fix the substring issue but prevents the most common false-trigger path (external reporters quoting text with
- 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(currentmain) - Triggered run: #191875 — conclusion: failure, duration: 28s
- Triggering comment: #66273 (comment)
- Action:
anthropics/claude-code-action@v1, model:claude-sonnet-4-5-20250929
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗