Trello Board Deletion Bypass — Privilege Escalation via the Board Move API

DP
Deev Pal
Dec 16, 2024 14 min read
This vulnerability was reported to Atlassian via Bugcrowd, accepted as P3, fixed, and rewarded $1,200. Disclosure: Bugcrowd CrowdStream.

TL;DR

Trello Premium workspaces let admins restrict who can delete boards — including a "No one can delete boards" option. A normal workspace member can bypass every deletion restriction by sending a single PUT /1/boards/{boardId} request that moves the target board to a workspace they own. This removes the board from the original workspace (effectively deleting it), after which the attacker can permanently delete it from their own workspace where no restrictions apply.

The core issue: Trello's authorization layer enforced deletion restrictions on the DELETE verb but failed to enforce the same restrictions on the PUT (move/reassign) operation, which achieves the same destructive outcome through a different code path.

Background — What is Trello?

If you're not familiar with Trello, here's the quick version: Trello is a project management tool owned by Atlassian (the company behind Jira, Confluence, and Bitbucket). Teams use it to organize work using boards, lists, and cards — think of it like a digital whiteboard with sticky notes.

The organizational hierarchy works like this:

  • Workspace — the top-level container. A company or team creates a workspace and invites members. Think of it as a shared office.
  • Board — a project within the workspace. Think of it as a whiteboard in that office. Boards contain lists and cards.
  • Members — people in the workspace. They can be normal members (regular employees) or workspace admins (managers with elevated privileges).
Why does this matter for security? Trello Premium costs money. Organizations pay for Premium specifically because it offers security controls like "prevent non-admins from deleting boards." If those controls can be bypassed, the organization is paying for a lock that doesn't actually lock.

Trello also has an API — a way for software (or people with the right tools) to interact with Trello programmatically. Instead of clicking buttons in the web interface, you can send HTTP requests directly to Trello's servers to perform the same actions. This is important because the web interface might hide certain buttons from you, but the API might still accept the request. That gap between what the UI shows and what the API allows is often where vulnerabilities hide.

Context — Trello's Board Deletion Permissions

Trello Premium and Enterprise workspaces expose a granular permission model under Workspace Settings > Board Deletion Restrictions. Admins can configure deletion permissions independently for each board visibility level (Public, Private, Workspace-visible).

Trello board deletion restrictions panel showing default settings where any workspace member can delete all board types
Default settings: Out of the box, any workspace member can delete public, workspace-visible, and private boards. The "Change" button lets admins tighten these permissions.

When an admin clicks "Change," they see three options for each board visibility type:

Board deletion permission options: Any Workspace member, Only Workspace admins, or Nobody
The three permission levels: "Any Workspace member" (default), "Only Workspace admins" (restricted), or "Nobody" (completely locked down). These apply independently to public, workspace-visible, and private boards.
In plain English: Imagine a shared Google Drive folder where the team lead can set a rule like "only managers can delete documents" or even "nobody can delete documents." That's what this Trello feature does — it prevents accidental or malicious deletion of project boards by restricting who has the power to delete.

After the admin configures the restriction, the settings panel confirms the change:

Board deletion restrictions showing Only Workspace admins can delete for all board types
Restricted configuration: The admin has set all three board types to "Only Workspace admins can delete." Normal workspace members should now be completely unable to delete any board.

This is a paid feature — it only exists in Premium/Enterprise tiers, which means organizations relying on it are paying specifically for this access control guarantee.

The Intended Restriction Model

When an admin sets deletion to "Workspace Admins only," the UI enforces two restrictions on normal workspace members:

1. Direct deletion is blocked. The "Delete Board" option still appears in the board menu, but clicking it fails. Even if the member is a Board Admin (admin of that specific board but not the workspace), they cannot delete it. The UI shows an error, and sending a DELETE request via a proxy tool like Burp Suite returns an Unauthorized response.

Trello UI showing a closed board with the Permanently delete board option in the menu, and a Board not deleted error at the bottom left
Deletion blocked in the UI: The workspace member attempts to permanently delete a closed board. The "Permanently delete board" option is visible in the menu (highlighted in red), but the operation fails — "Board not deleted. Something went wrong" appears at the bottom left.
What is Burp Suite? Burp Suite is a tool that security researchers use to intercept and modify the web traffic between their browser and a server. Think of it like sitting between your browser and the website, watching every request going back and forth — and being able to edit those requests before they reach the server. This lets researchers test what happens when they send requests the UI wouldn't normally allow.

2. Close-and-reopen is blocked. Trello allows closing a board (archiving it) and then reopening it in a different workspace. Trello's developers recognized that reopening a board in a different workspace effectively removes it from the original workspace — so they blocked this path too:

Error dialog saying Cannot reopen this board outside of techycodec08.03's workspace because this organization has restrictions on board deletion
Move-via-reopen also blocked: When a member tries to reopen a closed board outside the original workspace, Trello explicitly blocks it with this error. The developers understood that moving a board out is functionally the same as deleting it.

So Trello's developers were aware that moving a board out of a workspace is functionally equivalent to deleting it from that workspace. They explicitly blocked the close-and-reopen path. But they missed another path.

The Hypothesis — Move as Implicit Delete

The key insight is that board deletion and board movement are functionally equivalent from the source workspace's perspective. If a board is moved from Workspace A to Workspace B, it no longer exists in Workspace A. The board is gone. All links to it from Workspace A break. For all practical purposes, it has been deleted from Workspace A.

An analogy: Imagine a secure office where documents can't be shredded (deletion is restricted). But what if someone can carry documents out the door to another office (move them)? From the original office's perspective, the documents are gone — even though technically they still exist somewhere else. The "no shredding" rule doesn't help if documents can be physically removed from the building.

Trello's permission model checked for these paths:

  • DELETE /1/boards/{id} — blocked
  • Close → Reopen in different workspace — blocked
  • PUT /1/boards/{id} with idOrganization change — not checked

The third path is the vulnerability. The PUT endpoint for updating board properties allows changing the idOrganization field, which reassigns the board to a different workspace. This operation was not subject to the deletion restriction checks.

What does this mean? Every Trello board "belongs to" a workspace, identified by an internal ID called idOrganization. Trello has an API endpoint that lets you update board properties — things like the board's name, background, or description. But this same endpoint also lets you change which workspace the board belongs to. Trello's security team blocked the obvious ways to remove a board (DELETE request, close-and-reopen), but forgot that changing the idOrganization field achieves the exact same outcome: the board disappears from the original workspace.

Reconnaissance — Mapping the API Surface

Before attempting the bypass, I needed to understand the full API surface for board operations. Using Burp Suite as a proxy, I captured all requests made during normal board operations to see exactly what Trello's API accepts.

First, I confirmed that direct deletion was properly blocked by sending the DELETE request myself:

Board deletion (blocked):

HTTP Request — Direct Delete (Blocked)
DELETE /1/boards/67602d9ba379b5827eb9c49c HTTP/2
Host: trello.com
Cookie: <WORKSPACE-MEMBER-COOKIES>

Response: 401 Unauthorized
Burp Suite showing a PUT request to the boards API with the response indicating that deleting public boards is prohibited by the organization administrator
API-level block confirmed: Burp Suite showing the request and response. The response body includes the message "deleting public boards is prohibited by the organization administrator" — confirming that the server enforces the restriction, not just the UI.
Why test at the API level? When a website hides a button from you, that doesn't necessarily mean the server will reject the request. The button might be hidden purely in the frontend JavaScript. A critical step in security testing is confirming that the server enforces the restriction, not just the browser. In this case, the server did properly block DELETE requests — the restriction was real. But there's another API path that achieves the same result...

Board close-and-reopen (blocked):

Attempting to close the board and reopen it in a workspace owned by the member also fails — the API returns the error we saw earlier indicating the operation violates workspace permissions.

Board property update (the target):

The PUT /1/boards/{boardId} endpoint accepts a JSON body with updatable board properties. Among these properties is idOrganization — the ID of the workspace the board belongs to. This is the field that controls which workspace "owns" the board.

The critical question: does changing idOrganization on a board in a deletion-restricted workspace trigger the same permission check as deleting the board?

Exploitation — The Full Bypass

Prerequisites

  • Attacker role: Normal workspace member (not admin) in the target Premium workspace
  • Attacker owns: A separate Trello workspace (free tier is fine — anyone can create one)
  • Target workspace: Board deletion restricted to "Admins only" or "No one"
Why is this realistic? In most companies using Trello, regular employees are "normal workspace members." They can view boards, create cards, and participate in projects — but they're not supposed to be able to delete boards. The attacker doesn't need any special access. Any employee, contractor, or even someone accidentally added to the workspace can exploit this.

Required Identifiers

The attacker needs exactly two IDs, both of which are trivially obtainable:

  1. Board ID (67602d9ba379b5827eb9c49c) — visible in the board's URL to any workspace member: trello.com/b/{shortLink}/{boardName}. The full board ID is returned by any API call involving the board and is also present in the page source.
  2. Attacker's Workspace ID (67601adaca94c108be43106b) — the idOrganization of a workspace the attacker owns. Available from GET /1/members/me/organizations or from the workspace settings page URL.

The Exploit Request

With these two IDs in hand, the attacker sends a single API request through Burp Suite (or any tool that can send HTTP requests — even the browser's developer console or a simple curl command would work):

HTTP Request — Board Move (Bypass)
PUT /1/boards/67602d9ba379b5827eb9c49c HTTP/2
Host: trello.com
Cookie: <WORKSPACE-MEMBER-COOKIES>
Content-Type: application/json
X-Trello-Client-Version: build-214455
Origin: https://trello.com
Referer: https://trello.com/b/zEsX5ZcQ/workspacememberboard001

{
  "idOrganization": "67601adaca94c108be43106b",
  "dsc": "<WORKSPACE-MEMBER-CSRF-TOKEN>"
}

Response: 200 OK — the board is now in the attacker's workspace.

This single request removes the board from the victim's workspace entirely. All workspace members lose access. All board links from the original workspace break. The board is effectively deleted from the victim's perspective.

Key Request Analysis

Let's break down every field in the exploit request so it's clear why this is so easy to pull off:

Field Value Where the attacker gets it
PUT /1/boards/{boardId} Target board ID Visible in the board URL — anyone who can see the board knows this
idOrganization Attacker's workspace ID From the attacker's own workspace (they created it, so they know the ID)
dsc CSRF token The attacker's own CSRF token from their own browser session
Cookie Session cookie The attacker's own browser session — no need to steal the victim's cookies

No victim credentials, tokens, or interaction required. The attacker uses entirely their own session. The only "victim" data needed is the board ID, which is not a secret — it's visible in the URL to every board member.

Permanent Deletion

After the board lands in the attacker's workspace, the attacker can permanently delete it from there — since their own workspace has no deletion restrictions. The board is gone forever, with no recovery path for the original workspace admin.

Think of it this way: You work at a company where shredding documents is forbidden (deletion restriction). But you can carry any document home (move it to your own workspace). Once it's at your house, company rules don't apply — you can shred it there. The company's document is gone forever, and there's nothing they can do about it.

Full Attack Chain

Here's the complete attack from start to finish, step by step:

Attack Flow
1. Attacker is a normal member of Victim's Premium Workspace
   └── Board deletion restricted to "Admins only" or "No one"

2. Attacker creates their own free Workspace
   └── No deletion restrictions (free tier doesn't have this feature)

3. Attacker identifies target Board ID
   └── Visible in URL: trello.com/b/{shortLink}
   └── Full ID via: GET /1/boards/{shortLink} → response.id

4. Attacker sends: PUT /1/boards/{targetBoardId}
   └── Body: {"idOrganization": "{attackerWorkspaceId}"}
   └── Response: 200 OK — board moved to attacker's workspace

5. Board is removed from Victim's Workspace
   └── All members lose access
   └── All links break
   └── Board no longer appears in workspace

6. Attacker permanently deletes board from their own workspace
   └── DELETE /1/boards/{targetBoardId} → 200 OK
   └── Board is gone forever — no recovery

Root Cause Analysis

The vulnerability exists because Trello implemented board deletion restrictions as a verb-specific check rather than an outcome-based check.

What does "verb-specific vs outcome-based" mean? When you interact with a web API, you use different "verbs" (also called HTTP methods) — GET to read data, POST to create, PUT to update, DELETE to remove. Trello's security check said: "if someone sends a DELETE request, check if they're allowed." But it didn't say: "if any request would result in a board being removed from this workspace, check if they're allowed." That's the difference between checking the verb (how the request is phrased) versus the outcome (what actually happens).

The authorization logic was approximately:

Pseudocode — Authorization Check
// DELETE /1/boards/{id}
if (workspace.deletionRestriction !== "anyone") {
    if (!user.isWorkspaceAdmin()) {
        return 401; // Blocked ✓
    }
}

// PUT /1/boards/{id} — update board properties
if (user.isBoardMember()) {
    board.update(requestBody); // idOrganization change NOT checked ✗
}

The developers correctly blocked the DELETE verb and the close-and-reopen workflow. But the PUT endpoint for updating board properties — specifically the idOrganization field — was not subject to the same authorization check. Moving a board to a different workspace is functionally identical to deleting it from the source workspace, but the permission model treated these as unrelated operations.

This is a textbook example of bypassing authorization via an alternative code path — the "check" happens on one code path (DELETE), but the same destructive outcome (removing a board from a workspace) can be achieved through a different code path (PUT with idOrganization change) that skips the check entirely.

Impact

CVSS 3.0: AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N — 6.5 (Medium)

  • Confidentiality: None — no data is disclosed
  • Integrity: High — workspace data (boards) can be destroyed
  • Availability: Effectively high — boards become permanently inaccessible to all legitimate users
Understanding CVSS: CVSS is a standardized scoring system for rating the severity of security vulnerabilities on a scale of 0 to 10. The score breaks down the attack along several dimensions: how difficult is it to exploit? (easy — low complexity), what access does the attacker need? (just a low-privilege account), does the victim need to do anything? (no — no user interaction needed). A score of 6.5 is "Medium" severity — significant enough to warrant a fix, but not as severe as remote code execution or data theft.

Business impact for affected organizations:

  • Any workspace member (including recently onboarded employees, contractors, or accounts added by mistake) can delete any board in the workspace
  • Deletion restrictions — a paid Premium feature — are completely negated
  • No audit trail distinguishes a "move" from a "delete" — the board simply vanishes from the workspace
  • Insider threat: a disgruntled employee could destroy project boards before departure
  • The attack requires zero privilege escalation setup — only a standard workspace membership

Remediation

Atlassian resolved this by enforcing deletion restrictions on any operation that removes a board from a workspace, not just the explicit DELETE verb. The fix ensures that changing a board's idOrganization via the PUT endpoint triggers the same permission checks as direct deletion.

Defensive pattern: When implementing access controls on destructive operations, define restrictions based on the outcome (board is removed from workspace), not the mechanism (DELETE verb was used). Any API path that achieves the same destructive outcome must be subject to the same authorization check.

The lesson for developers: Whenever you add a security restriction, ask yourself: "What are ALL the ways someone could achieve this same result?" Don't just block the obvious path (the Delete button). Think about indirect paths — moving, transferring, merging, archiving — that achieve the same destructive outcome. Then make sure your security check covers all of them.

Timeline

  • 2024-12-16 — Vulnerability discovered and reported via Bugcrowd
  • 2024-12-16 — Triaged as P3 (Broken Access Control > Privilege Escalation)
  • 2025-03-27 — Fix deployed, vulnerability resolved
  • 2025-03-27 — $1,200 bounty awarded
  • 2025-03-27 — Disclosure approved

Takeaways for Hunters

  1. Think in outcomes, not verbs. When you see a restriction on one operation (DELETE), ask: is there another API path that achieves the same outcome (removing the resource)? Move, transfer, reassign, archive, merge — these are all potential "delete alternatives."
  2. Premium features are high-value targets. Paid access control features carry an implicit trust guarantee. Organizations are paying for the assurance that the restriction works. Breaking it has outsized business impact — and bug bounty teams tend to prioritize these reports.
  3. Map the full API surface. Don't just test the UI flow. Intercept every request in Burp, catalog all endpoints that touch the target resource, and test each one independently against the restriction. The UI only shows you the "happy path" — the API might accept requests the UI would never send.
  4. PUT endpoints are underexplored. Most hunters focus on POST (create) and DELETE (destroy). But PUT/PATCH endpoints that update resource properties can often achieve destructive outcomes by changing ownership, visibility, or organizational assignment.
  5. Two-step destruction is still destruction. The attacker couldn't delete the board directly — but they could move it somewhere they control and then delete it there. Any time you can change the context of a resource (move it to a less-restricted environment), you may be able to bypass restrictions that only apply in the original context.