mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-25 22:06:09 +00:00
0f7329c3ce
Three problems, all in .github/workflows/claude-bot.yml. It was silently dead. No comment had been posted since 2026-07-20 while every run reported success: roughly twenty issues and pull requests each burned 18-56 turns and up to $2.59, ended with permission denials, and published nothing. Comment bodies are markdown, markdown is full of backticks, and inside a quoted `--body "..."` backticks are command substitution, so the write was rejected and a failed triage looked exactly like a clean one. The body now goes to /tmp through Write and out through --body-file, in every branch of both jobs, and each job re-reads the thread afterwards so a rejected write fails loudly instead of reporting success. The run transcript is kept as an artifact. It could reach much further than it claimed. Both jobs that any GitHub user can trigger declared themselves READ-ONLY in prose while holding Bash(gh:*), which is not a GitHub-scoped allowlist: `gh alias set --shell` runs its argument through sh -c and `gh extension install` fetches and executes code, both as single commands whose first token is gh. That is a general shell on a runner holding CLAUDE_CODE_OAUTH_TOKEN, which does not expire with the job. `gh api` accepted any method, issues: write is repo-scoped rather than issue-scoped, and `gh pr review --approve`, `gh pr close` and `gh pr checkout` were forbidden in prose only. Those two jobs now list the subcommands they actually run. The untrusted title and body are fenced in tags carrying github.run_id, unguessable at the time the issue is written, and the invariants an allowlist cannot express - one issue number, labels and title only, /tmp as the sole writable path, never $GITHUB_ENV - are stated explicitly. Both checkouts get persist-credentials: false. handle-pr-fix and mention keep their wildcards: only owners, members and collaborators can trigger them, and narrowing the maintainer's own path risks more than it protects. Its review hid findings and its triage quoted stale facts. "Prefer a few high-signal findings over many low-value ones" is read literally by Opus - it finds the bug, judges it below the stated bar and says nothing - while the Severity and Confidence tiers already existed to do that filtering. The review also never said that the working directory is the base revision, so it could assert that a case was unhandled in code the pull request had already rewritten, and label it confirmed, on an outside contributor's first patch. Four CLAUDE.md conventions were missing, each a guaranteed miss: openapigen's StructAllow allowlist, the layering rules including the runtime.Runtime dispatch requirement that silently breaks multi-node when bypassed, the assertion standard, and golden share-link fixtures regenerated to turn a red test green. On the triage side the invalid and duplicate branches were gated three times over and so never fired, leaving spam to collect a full investigation and a courteous reply; /etc/default/x-ui was given as the env file when it is distro-dependent, making the PostgreSQL migration advice a silent no-op on RHEL and Arch; an env list labelled "full" omitted XUI_PORT and the XUI_TUNNEL_HEALTH_* family; XTLS was offered as a security option the panel does not have. docs/architecture.md was invisible to both prompts despite being maintained and already in the checkout. From the bot's own output: it published a trigger only the maintainer can use, retitled issues without saying so, asked for screenshots it cannot open, and once invented a reason for a number it had miscounted. All four jobs move to Opus 5, at xhigh effort rather than max - the recommended tier for agentic work, and one below the overthinking that max invites on routine triage.