Relationships
#1700 User token page (/u/<user>) shows only "swamp_..." for every API key, making leaked-key identification impossible
Opened by webframp · 8/18/2026· Shipped 9/24/2026
Description
The API key list on a user's page (https://swamp-club.com/u/<username>) renders
every key as a truncated, indistinguishable swamp_... string. There is no
visible name, label, key-ID suffix, creation date, last-used date, or scope
shown per key in that view.
This makes it impossible to identify which key is which when you need to,
e.g. after finding a credential accidentally committed to a local git commit
(never pushed, but still treated as compromised). Credential files like
auth.json expose an apiKeyId (a short hex string) alongside the full
apiKey secret — but the web UI token list has no way to cross-reference
that ID back to a labeled row, and no way to see a key's own ID from the
truncated display string alone.
Net effect: when a key leaks locally, the only safe remediation is to revoke every key on the account and reissue, because there is no affordance to scope revocation to the one specific key that was exposed. For an account with several active integrations (CI, multiple worker fleets, local dev), that is needlessly disruptive.
Steps to Reproduce
- Log in to https://swamp-club.com and create two or more API keys for the
same account (e.g. via
swamp auth loginon two different machines, or via the dashboard's "create key" action). - Visit
https://swamp-club.com/u/<username>(your own token management view). - Observe the key list: each entry displays as
swamp_...(prefix plus ellipsis/truncation) with no other distinguishing metadata rendered. - Attempt to match a known
apiKeyId(as found in a localauth.json) against a specific row in the list — there is no field on the page showing theapiKeyId, a label, or any other identifier to match against.
Environment
- Platform: swamp-club.com (Team plan)
- Client: swamp CLI,
swampVersion: 20260725.011748.0(per local.swamp.yaml) - Auth:
swamp auth login - Browser: N/A — issue is server-rendered page content, not a client-specific bug
Suggested Fix
Show, per key row: a user-assigned label/name (prompt for one at creation
time if not already supported), the apiKeyId (or a short suffix of it),
creation date, and last-used date. This is the minimum needed to support
targeted revocation during incident response instead of forcing a full
credential rotation across every integration on the account.
Shipped
Click a lifecycle step above to view its details.
skunk-ape commented 9/24/2026, 6:05:59 PM
The CLI side of fingerprints is in swamp-club/swamp#2609 (lab #2485). Two things for this issue:
1. Keep sending keyPrefix in the collective-token API. Add fingerprint alongside it, not instead of it. Released CLIs build the swamp auth token list table from token.keyPrefix and measure each cell's length, so a response without keyPrefix makes the command throw. It also silently drops the field from --json. New CLIs still show PREFIX when the server sends no fingerprints. Older CLIs ignore an extra fingerprint field, so adding it is safe.
What #2609 expects from the server: an optional fingerprint string on each token in GET /api/v1/collectives/<slug>/api-tokens, computed as lowercase hex of SHA-256(utf8(full key)), first 16 characters. Test vector: [REDACTED-SECRET-1] gives 7cba95208c56e033.
2. Please include the manual update in this work. content/manual/reference/api-key-authentication.md needs to reflect #2609:
swamp auth whoami: a newFingerprint: <16 hex>line after the identity line, and afingerprintfield in--json. This applies to personal keys and collective tokens, and to both auth.json and SWAMP_API_KEY.apiKeyIdis intentionally not shown.swamp auth token create: aFingerprint:line above the one-time secret, andfingerprintin--json. It is computed locally, so it works before this server change ships.swamp auth token list: once the server sends fingerprints, the table shows a FINGERPRINT column in place of PREFIX. ID stays, becauseswamp auth token revoketakes it.--jsonkeepsidandkeyPrefixand addsfingerprint. The page currently says the table shows "key prefix".- The auth.json field table:
apiKeyFingerprint(the SWAMP_API_KEY identity-cache key) now holds this same fingerprint instead of the key's first 12 characters. It is not listed on the page today. - A short how-to for a leaked key: run
swamp auth whoamiwith that key (or read theFingerprint:line when the token is created), find the row with that fingerprint on /u/ or inswamp auth token list, then revoke that row. This replaces the shell one-liner, which is broken by a trailing newline and has no Windows equivalent.
skunk-ape commented 9/24/2026, 6:06:08 PM
Correction to the ripple above: the CLI's secret redactor replaced the test-vector key, a made-up value, with a placeholder. The full vector is in the body of lab #2485: the key there should hash to 7cba95208c56e033, and swamp-club/swamp#2609 pins the same vector in src/domain/auth/auth_credentials_test.ts.
skunk-ape commented 9/24/2026, 8:35:08 PM
Thanks @webframp for reporting this, and for the clear write-up of the leaked-key case. It is live on swamp-club.com now.
Every token row on your profile's Access Tokens panel and in a collective's token list shows a fingerprint: the first 16 hex characters of the key's SHA-256. With the latest swamp CLI, swamp auth whoami prints the fingerprint of the key it uses, and SWAMP_API_KEY=<token> swamp auth whoami works for any other key, such as the one from that local commit. Match it to its row and revoke only that key; your other integrations keep working. Existing keys have fingerprints too, so no reissue is needed. Details: https://swamp-club.com/manual/how-to/authenticate-with-api-keys#identify-a-key
Sign in to post a ripple.