Skip to content

Bitbucket Cloud

Connecting from the web app?

Follow the prerequisites and credential creation instructions below, then return to Cloud Security → Settings → Providers → Add provider. Enter the provider IDs under Configuration and save the credential using New secret under Permissions. Run Test Provider, fix required failures, and save. The LimaCharlie CLI examples below are an alternative. First-time setup and verification explains the full journey.

Connects one Bitbucket Cloud workspace. Its repositories become repositories in the inventory, and the workspace itself becomes the account they belong to.

The connection exists to drive Code Security: once a code_scanning policy selects its repositories, they are scanned exactly like GitHub repositories and their findings land in the same worklist.

Auth model: an Atlassian API token with scopes, read-only. The connector only ever reads: every API call is a GET, and a scan's clone is a fetch.

Bitbucket Data Center is not supported

Bitbucket Data Center (self-hosted) is a different product with a different API. This connector is for Bitbucket Cloud (bitbucket.org) only.

Prerequisites

  • An Atlassian account that is a member of the workspace and can read its repositories.
  • The workspace slug — the first path segment of a repository URL: the acme in https://bitbucket.org/acme/api.

Required token scopes

Scope Why Preflight check
read:workspace:bitbucket Resolve the workspace and confirm membership token_scopes, workspace, workspace_membership
read:repository:bitbucket List repositories and let the scan clone them token_read_repository, repositories
read:user:bitbucket Identify the token's account — enforced by the GET /2.0/user call itself, not by a scope check auth

Use a narrow token — a broad one is accepted, but it is yours to justify

A token carrying more than the three scopes above still connects, and the credential test says so as an advisory note (token_read_only) rather than refusing it. That includes write: scopes and it includes admin: and delete: scopes.

It is worth understanding what you are accepting. Bitbucket cannot narrow a token to one repository, so the token each scan clones with is the connection's own token, mounted into a job that analyses untrusted third-party source. A credential that can administer or delete across the workspace carries that reach into the job. Create the token with exactly the three read scopes.

Create the token with scopes. If Bitbucket does not report a token's scopes — which means it was created without any, and is therefore bounded by none — the credential test says they were not verified, neither that the token can read nor that it is limited to reading. That is reported, not refused; the first sweep and the first scan are then the authoritative check that the token can read.

What is refused is a token that can do neither job: no scope that can read the workspace, or no scope that can clone. The check is the capability, not the scope's name — admin:workspace:bitbucket counts as the workspace read, and admin:/write:repository:bitbucket as the clone — so an admin-scoped token connects and sweeps, with the advisory note above.

A missing scope is refused wherever the token is used

The credential test is not the only gate, because a token can be rotated after a connection is saved. read:workspace:bitbucket is re-checked on every inventory sweep, and read:repository:bitbucket before every scan. A sweep that refuses leaves the inventory unchanged — the repositories and their findings stay exactly as they were, and the provider's status carries the reason — rather than reporting an empty estate.

Membership is required, and checked on every sweep

The token's account must be a member of the workspace. This is not a formality: Bitbucket answers a caller who cannot see a workspace's private repositories with a successful listing of only its public ones. Without membership that listing is not the whole estate, so the connection refuses to trust it — the sweep leaves the inventory unchanged and reports the failure, rather than removing private repositories it merely cannot see.

Create the token

  1. Sign in to your Atlassian account settings: Security → Create and manage API tokens.
  2. Create API token with scopes, give it a name and an expiry.
  3. Select the Bitbucket app and only these scopes: read:repository:bitbucket, read:workspace:bitbucket, read:user:bitbucket.
  4. Copy the token — it is shown once.

Create the credentials secret

The secret holds the token, either bare or as a JSON document:

{"token": "ATATT3xFfGF0..."}

Save the credential JSON shown above as bitbucket-secret.json, then upload it via stdin:

jq -Rs '{secret: .}' bitbucket-secret.json \
  | limacharlie secret set --key bitbucket-token --enabled \
  && rm -f bitbucket-secret.json

Create the provider record

provider.yaml:

provider_type: bitbucket
bitbucket_workspace: "acme"
credentials: hive://secret/bitbucket-token
refresh: 6h

bitbucket_workspace is the bare slug: letters, digits, _ and -, up to 100 characters. No URL, no /.

In the web app: Add provider → Bitbucket Cloud, then set Workspace and Credentials.

Verify

limacharlie cloudsec provider test --input-file provider.yaml
Check Required Meaning if it fails
auth ✅ The token was rejected (wrong, revoked or expired). Nothing else is probed.
token_scopes ✅ The token holds no scope that can read the workspace — read:workspace:bitbucket, its admin: form or the legacy account. Re-checked on every sweep. Passes with a note when the API reports no scopes at all — a token created without any is bounded by none, so it is not missing anything.
token_read_repository ✅ The token holds no scope that can clone — read:repository:bitbucket, its write:/admin: forms or the legacy repository spellings. Re-checked before every scan.
token_read_only — The token is broader than the connection uses — a write:, admin: or delete: scope. Advisory: the connection still saves. Not reported at all when the API does not report the token's scopes.
workspace ✅ The slug does not exist, or the token cannot see it.
workspace_membership ✅ The token's account is not a member of the workspace.
repositories ✅ The repository listing is not readable.
repositories_visible — The listing works but no repository is visible to the token.

Troubleshooting

provider test result Cause Fix
workspace fails as not found A display name or URL instead of the slug Use the first path segment of a repository URL
workspace fails as refused The token lacks read:workspace:bitbucket, or the account is not a member Add the scope, or add the account to the workspace
workspace_membership fails The account can see the workspace but is not a member Add the account to the workspace
token_scopes reports the scopes as not verified The API token was created without scopes, so Bitbucket reports none — such a token is not bounded by any scope and carries the account's full reach. The connection is not blocked on it Create a scoped API token with read:repository:bitbucket, read:workspace:bitbucket and read:user:bitbucket, and update the secret
The inventory stops refreshing and the provider status says the token "cannot read the workspace" The connection's secret was rotated to a token without read:workspace:bitbucket after the connection was created. The existing repositories and findings are kept, not deleted Create a token with the three read scopes and update the secret

Known limitations

  • The API token must keep its three scopes for the lifetime of the connection: read:workspace:bitbucket is re-checked on every inventory sweep and read:repository:bitbucket before every scan, so a secret rotated to a narrower token stops the connection (without deleting anything) rather than silently reporting a smaller estate. A broader token is accepted — because Bitbucket has no way to narrow a token per repository, each scan clones with the connection's own token, so how much authority that token carries is worth a deliberate decision.
  • The connection is the repository estate of one workspace. Members, groups, access keys, repository variables and branch restrictions are not collected, so the branch-protection findings GitHub repositories raise do not apply.
  • The workspace slug is configuration, not discovery: a second workspace is a second connection.
  • Scans run on the schedule of the code_scanning policy. Push-triggered rescans are not available for Bitbucket.
  • Nothing is written to Bitbucket. Pull-request checks, comments and dependency AutoFix pull requests are GitHub-only.