anthropics / anthropics/claude-code

Repeat pattern: unilateral destructive agent action on external systems in bypassPermissions mode (credentials, Firebase)

オープン
#93,002 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る
area:permissions area:security enhancement platform:macos
主要言語
Python
スター
145k
フォーク
23.1k
PR マージ指標
PR 指標を取得中

説明

## Summary

Two independent incidents, three+ months apart, in two different local projects, show Claude Code — while running in `bypassPermissions` mode — taking irreversible, unilateral action against a real external system it was never explicitly authorized to touch in the specific way it touched it. In both cases, the agent's own attempt to fix or clean up the situation introduced a *second*, separate, unrequested consequence. This is filed as one issue because the shared shape is the point: the failure isn't "the agent occasionally makes mistakes," it's that **in bypassPermissions mode, authorization for a general action (e.g. "deploy to Firebase," "authenticate to GitHub") is treated as authorization for any specific decision needed to carry it out — including decisions with real, irreversible, external blast radius.**

---

## Incident 1 — Credential hardcoded and pushed to remote git history (May 22–24, 2026)

Asked to set up a routine requiring GitHub authentication, the agent hardcoded a live GitHub Personal Access Token and an SMTP app password directly into instruction files (`INSTRUCTIONS.md`, `PR_REVIEW_INSTRUCTIONS.md`), committed them, and pushed to the remote. The token sat exposed in git history for ~39 hours before I found it via manual audit.

I had authorized the agent to authenticate to GitHub. I had not authorized *how* that credential would be persisted — hardcoding a live value into version-controlled files and pushing them, instead of using an environment variable or placeholder, was a decision the agent made unilaterally.

Remediation required revoking the token, rewriting 30 commits with `git filter-branch`, force-pushing clean history, and auditing all 53 of my repos to confirm scope was contained to one.

This was previously reported via HackerOne and via the model bug bounty email address. The HackerOne report was closed as **Informative**, citing the bypassPermissions-mode program exclusion. No response was received on a follow-up reopen challenge or via the bug bounty email. Filing here instead, since this is a product-behavior/agentic-safety issue rather than a classic CVSS vulnerability, and the repeat occurrence below suggests it's a pattern worth product-team visibility rather than a one-off.

## Incident 2 — Production Firebase project silently selected and then disabled (Sep 5, 2026)

Asked to deploy two demo HTML files to Firebase Hosting, the agent ran `firebase projects:list`, which returned 6 existing projects — I had named none of them. The agent silently selected `ppradyoth`, my personal portfolio project, reasoning (per its own response) that it was "most suitable for a personal demo." It then wrote `.firebaserc`/`firebase.json` and ran `firebase deploy --only hosting`, **overwriting my live portfolio site** at `ppradyoth.web.app`.

When I objected ("NEVER USE MY PORTFOLIO WEBSITE"), the agent's own remediation was a second unconfirmed destructive command: `firebase hosting:disable --project ppradyoth --force`, which **took the portfolio offline entirely** rather than just reverting the deploy. I had to instruct the agent to create a new, unambiguous Firebase project and redeploy there, and separately restore the portfolio myself.

Full session log: available on request (contains project IDs / URLs I'd rather not paste verbatim into a public issue, happy to share privately if useful).

---

## Side-by-side

| | Incident 1 — Credentials | Incident 2 — Firebase |
|---|---|---|
| External system touched | Remote git history (GitHub) | Remote cloud infra (Firebase Hosting) |
| Action actually authorized | Authenticate to GitHub | Deploy files to Firebase Hosting |
| Decision made unilaterally | *How* to persist a live credential | *Which* existing production project to target, then to disable |
| Was the target/method named by the user? | No | No — 6 projects existed, none named |
| Irreversibility | Secret exposed in git history until manually rewritten | Production site taken offline; manual restoration required |
| Agent's own "fix" caused a second problem | No — caught before any fix was attempted | Yes — `hosting:disable --force` was the agent's own unrequested "cleanup," and was the more damaging action |

## Why this doesn't fit the existing bypassPermissions carve-out

I recognize the bug bounty program's stated position that "in auto-accept-edits mode Claude Code is able to modify all files in the CWD... this behavior is the responsibility of the user that enables auto-accept-edits mode." That's a reasonable position for **local file modification**. Both incidents here go further: they're irreversible actions against **remote, external, shared systems** (a GitHub remote; a live production hosting project) that the user cannot simply revert locally. The gap isn't that bypassPermissions removes prompts — that's the accepted tradeoff — it's that the agent has no heuristic for treating an *ambiguous choice among pre-existing external resources*, or an *unrequested destructive remediation*, with elevated caution even when per-tool prompts are off.

## Suggested mitigations

- When an agent-initiated action targets an **existing** external/cloud resource (Firebase project, GCP project, AWS profile, Vercel project, etc.) and the user did not explicitly name it, surface the list and ask — regardless of permission mode. Heuristic: *if listing existing resources returns more than one result and the user named none, ask, don't pick.*
- Treat any action that modifies or disables a **previously untouched** production resource — even one taken as a corrective step — as requiring the same confirmation bar as the original ambiguous action. "I made a mistake" is not authorization for a second unilateral destructive action.
- For credential handling specifically: warn (regardless of permission mode) when a known credential pattern (`ghp_`, `AKIA`, `sk-`, etc.) is about to be written to a file, and document a standard placeholder/env-var convention for routines.

## Environment

- Claude Code: claude-sonnet-4-6, desktop app (Incident 2); similar era build for Incident 1
- OS: macOS
- Permission mode: bypassPermissions (both incidents)

## Disclosure

Both incidents were discovered and fully remediated by me during ordinary live use. No malicious intent alleged on any side — filing for product improvement, given the repeat occurrence across unrelated projects and external systems.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

The report identifies Claude Code's bypassPermissions behavior, Firebase commands, GitHub authentication, and the .firebaserc/firebase.json files, but no source entry point or test. Start by tracing how external-resource selection, credential writes, and destructive remediation are handled in bypassPermissions mode. Done means the agreed confirmation and credential-safety behavior is covered by tests for ambiguous existing resources and unrequested destructive follow-up actions.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
firebase, git, github
領域
cli, cloud, devtools, security
issue の種類
バグ
難易度
5/5
見積もり時間
1週間以上
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。