A host credential can rotate itself at any time without an admin asking for it, which revokes every other credential for that host.
agent/credentials/+server.ts:9 calls rotateCredential on any authenticated POST.
index.ts:358-370 revokes all of the host's credentials and issues the one the caller supplied.
Nothing checks that an admin queued credentials.rotate (api/hosts/[id]/credentials/+server.ts:11), and credentials never expire (index.ts:339-351 only checks revoked_at).
Someone holding a copied credential, from a backup for example, can rotate once and keep exclusive access. The real agent just starts getting 401s, with no conflicting heartbeats to show something is wrong.
Fix
Accept /api/agent/credentials only while a credentials.rotate operation for that host is open, and close the operation when rotation completes
A host credential can rotate itself at any time without an admin asking for it, which revokes every other credential for that host.
- `agent/credentials/+server.ts:9` calls `rotateCredential` on any authenticated POST.
- `index.ts:358-370` revokes all of the host's credentials and issues the one the caller supplied.
- Nothing checks that an admin queued `credentials.rotate` (`api/hosts/[id]/credentials/+server.ts:11`), and credentials never expire (`index.ts:339-351` only checks `revoked_at`).
Someone holding a copied credential, from a backup for example, can rotate once and keep exclusive access. The real agent just starts getting 401s, with no conflicting heartbeats to show something is wrong.
**Fix**
- [x] Accept `/api/agent/credentials` only while a `credentials.rotate` operation for that host is open, and close the operation when rotation completes
Reviewed 1b908f891f. All fix items are complete; closing this issue.
Checklist
Administrator authorization.hosts/index.ts:888 requires an open rotation operation for this host before issuing a new credential; completion and revocation occur in the same transaction.
Retries and rollback. Tests cover absent/other-host/other-kind/terminal operations, all accepted open states, idempotent acknowledgment, one-time authorization consumption and rollback if completion fails.
Review notes
Reviewed current EC main at fa0baa8db5. Full application suite passed: 230 files, 3,120 tests, including migration-memory coverage; no failures or skips.
Python agent suite: 332 tests passed, no skips. Type/style checks: zero errors and warnings.
Acknowledging an already-active replacement does not rotate again or consume another authorization.
Reviewed 1b908f891fc6c6bba7e7b8a63d1400a2dbc86df8. All fix items are complete; closing this issue.
**Checklist**
- [x] **Administrator authorization.** `hosts/index.ts:888` requires an open rotation operation for this host before issuing a new credential; completion and revocation occur in the same transaction.
- [x] **Retries and rollback.** Tests cover absent/other-host/other-kind/terminal operations, all accepted open states, idempotent acknowledgment, one-time authorization consumption and rollback if completion fails.
**Review notes**
- Reviewed current EC main at fa0baa8db5f7629de3f58f2e6bf8da0568018be0. Full application suite passed: 230 files, 3,120 tests, including migration-memory coverage; no failures or skips.
- Python agent suite: 332 tests passed, no skips. Type/style checks: zero errors and warnings.
- Acknowledging an already-active replacement does not rotate again or consume another authorization.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A host credential can rotate itself at any time without an admin asking for it, which revokes every other credential for that host.
agent/credentials/+server.ts:9callsrotateCredentialon any authenticated POST.index.ts:358-370revokes all of the host's credentials and issues the one the caller supplied.credentials.rotate(api/hosts/[id]/credentials/+server.ts:11), and credentials never expire (index.ts:339-351only checksrevoked_at).Someone holding a copied credential, from a backup for example, can rotate once and keep exclusive access. The real agent just starts getting 401s, with no conflicting heartbeats to show something is wrong.
Fix
/api/agent/credentialsonly while acredentials.rotateoperation for that host is open, and close the operation when rotation completesReviewed
1b908f891f. All fix items are complete; closing this issue.Checklist
hosts/index.ts:888requires an open rotation operation for this host before issuing a new credential; completion and revocation occur in the same transaction.Review notes
fa0baa8db5. Full application suite passed: 230 files, 3,120 tests, including migration-memory coverage; no failures or skips.