Kingfisher’s **access map** determines the *effective identity* and *blast radius* of a credential by authenticating to the target provider and enumerating accessible resources and permissions.
Access map only runs for credential types Kingfisher knows how to authenticate with and enumerate. In the codebase, these map to `AccessMapRequest` variants recorded from validated findings (see `src/scanner/validation.rs`).
## Providers and supported credential formats
### GitHub (`github`)
- **Credential**: a single GitHub token string (read from a file for `kingfisher access-map github <FILE>`).
- **Token types supported**: any token accepted by GitHub’s REST API `Authorization` scheme used by Kingfisher (`Authorization: token <TOKEN>`), including:
- Classic PATs (commonly `ghp_...`)
- Fine-grained PATs (commonly `github_pat_...`)
- OAuth / user tokens (various prefixes; GitHub controls these)
- GitHub App tokens (Kingfisher detects `ghu_...` and `ghs_...` and uses the installations APIs for richer mapping)
- Access map currently uses `https://api.github.com` as the API base.
### GitLab (`gitlab`)
- **Credential**: a single GitLab token string (read from a file for `kingfisher access-map gitlab <FILE>`).
- **Token types supported**: any token accepted by GitLab’s `PRIVATE-TOKEN` header (PATs like `glpat-...`, plus other GitLab token types that work with that header).
When available, Kingfisher also queries the token-self endpoint for metadata; some token types may not expose token details there.
Kingfisher performs read-only enumeration for the IAM principal and, when allowed by the credential, visible resources in several common AWS services including S3, EC2, IAM, Lambda, DynamoDB, KMS, Secrets Manager, SQS, SNS, RDS, ECR, and SSM Parameter Store.
Kingfisher resolves the Alibaba Cloud caller identity with `sts:GetCallerIdentity` for both long-lived access key pairs and STS temporary credentials discovered during scanning. Current coverage is identity-focused: it maps the account and resolved RAM principal, and records that broader Alibaba service enumeration is not yet available.
Kingfisher treats the account key as full-control Storage credentials and performs best-effort enumeration across Blob containers, File shares, and Queue resources reachable with that key.
Azure DevOps access mapping is supported when a **validated Azure DevOps PAT** is discovered during scanning (the access-map record includes both the PAT and the organization). At the moment, there is **no standalone**`kingfisher access-map azure-devops ...` provider flag.
### PostgreSQL (`postgres`)
- **Credential**: a single Postgres connection URI string (read from a file).
Kingfisher queries the `/api/whoami-v2` endpoint to resolve the token identity, role, and organization memberships. It also performs best-effort enumeration of authored models, datasets, and Spaces for the user and visible organizations to assess the blast radius.
- Access map uses `https://huggingface.co/api` as the API base.
- Token role (read, write, admin, fineGrained) is derived from the `auth` section of the whoami response when available.
### Gitea (`gitea`)
- **Credential**: a single Gitea token string (read from a file for `kingfisher access-map gitea <FILE>`).
- **Token types supported**: any token accepted by Gitea's `Authorization: token <TOKEN>` header (personal access tokens).
Kingfisher queries `/api/v1/user` for identity, enumerates organizations via `/api/v1/user/orgs`, and lists accessible repositories via `/api/v1/user/repos`. Repository-level permissions (admin, push, pull) are used to classify risk.
Kingfisher queries `/2.0/user` for identity, enumerates workspace memberships and permissions via `/2.0/user/permissions/workspaces`, and lists accessible repositories via `/2.0/repositories?role=member`. Workspace ownership and private repository access are used to classify risk.
- **Credential**: a single Buildkite API token string (read from a file for `kingfisher access-map buildkite <FILE>`).
- **Token types supported**: tokens accepted by Buildkite's REST API with `Authorization: Bearer <TOKEN>` (API access tokens, commonly `bkua_...`).
Kingfisher queries `/v2/access-token` for token metadata and scopes, `/v2/user` for identity, `/v2/organizations` for organization memberships, and `/v2/organizations/{org}/pipelines` for pipeline enumeration. Token scopes and organization access are used to classify risk.
- Queries the API key aggregate endpoint for basic token metadata (when available).
- Enumerates organizations via `GET https://app.harness.io/v1/orgs` and projects via `GET https://app.harness.io/v1/orgs/{org}/projects` when the key has permission.
If organizations/projects are not enumerable (scope-limited keys), Kingfisher still produces an access-map record with a conservative severity and a note explaining the limitation.
- **Credential**: a single Anthropic API key string (read from a file for `kingfisher access-map anthropic <FILE>`).
- **Token types supported**: Anthropic keys accepted via `x-api-key`, including standard API keys and admin-style keys when exposed by Anthropic.
Kingfisher performs read-only enumeration via:
-`GET https://api.anthropic.com/v1/models` to enumerate visible models.
-`GET https://api.anthropic.com/v1/organizations/api_keys/me` or `GET https://api.anthropic.com/v1/api_keys/me` to introspect the current key when supported.
-`GET https://api.anthropic.com/v1/organizations/api_keys` to enumerate visible organization API keys when the credential can access them.
Kingfisher parses the webhook URL to extract the tenant ID and webhook identity, then sends a benign probe (`{"text":""}`) to determine whether the webhook is still active. Active webhooks can post messages to the configured Teams channel.
- **Credential**: a single monday.com API token (read from a file for `kingfisher access-map monday <FILE>`).
- **Token types supported**: personal or account-level API tokens accepted by the monday.com GraphQL API with the `Authorization: <TOKEN>` header (the JWT-style token is sent verbatim, without the `Bearer` prefix — this matches monday.com's native scheme).
Kingfisher performs read-only enumeration against `https://api.monday.com/v2`:
-`me { ..., account { id, name, slug, plan { tier } }, teams { name } }` for caller identity, role, and account metadata
-`workspaces(limit: 100) { id, name, kind, state }` for workspace-level resource exposure
-`boards(limit: 50) { id, name, board_kind, state }` for board-level resource exposure
Severity is Critical for account administrators, High for standard members with broad workspace/board visibility (>5 workspaces or >20 boards), Medium for standard members with any workspace/board access, and Low for guest/viewer tokens or empty accounts.
- Access map currently uses `https://api.monday.com/v2` (GraphQL v2) as the API base.
- monday.com API tokens do not carry granular scopes; permissions follow the underlying user's role (admin/member/viewer/guest).
-`provider_metadata.version` carries the monday.com plan tier when exposed by the account.
- Recorded during `scan --access-map` for validated `kingfisher.monday.1` findings.
### Asana (`asana`)
- **Credential**: a single Asana access token (read from a file for `kingfisher access-map asana <FILE>`).
- **Token types supported**: tokens accepted by Asana's REST API with `Authorization: Bearer <TOKEN>`:
- Legacy OAuth / personal access tokens (`0/...`)
- Personal Access Tokens V1 (`1/<user_gid>:<secret>`)
- Personal Access Tokens V2 (`2/<app_gid>/<user_gid>:<secret>`)
Kingfisher performs read-only enumeration against `https://app.asana.com/api/1.0`:
-`GET /users/me?opt_fields=gid,name,email,resource_type,workspaces.gid,workspaces.name,workspaces.is_organization,workspaces.resource_type` for caller identity and accessible workspaces/organizations
-`GET /projects?workspace=<gid>&limit=50&opt_fields=gid,name,privacy_setting,archived` for per-workspace project exposure
-`GET /users/me/teams?organization=<gid>&opt_fields=gid,name` for team memberships in each organization workspace
Severity is High when the token reaches an organization workspace with more than 20 visible projects, Medium when it reaches an organization workspace or has broad project visibility (>5 projects), and Low for single-workspace or empty tokens.
- Asana access tokens do not expose granular scopes. Access follows the underlying user's membership in each workspace, organization, and team.
-`token_details.token_type` is classified from the token prefix (`personal_access_token_v2`, `personal_access_token_v1`, `oauth_or_legacy_pat`, or generic `asana_token`).
- Recorded during `scan --access-map` for validated `kingfisher.asana.3`, `kingfisher.asana.4`, and `kingfisher.asana.5` findings only. `kingfisher.asana.1` is a client ID and `kingfisher.asana.2` is a client secret (requiring the client ID for an OAuth exchange), so neither is used on its own to enumerate user-level resources.
## Notes on access-map generation during `scan --access-map`
- Access-map entries are only recorded for **validated** findings.
- Some providers require extra context that Kingfisher infers from the finding context or validation response (for example, Azure DevOps organization name).
- Validated Hugging Face, Gitea, Bitbucket, Buildkite, Harness, OpenAI, Anthropic, Salesforce, Weights & Biases, Microsoft Teams, monday.com, and Asana credentials discovered during scans with `--access-map` are automatically collected and mapped, matching the existing behavior for other platforms.