Skip to content

fix(server): enforce edit permission on application snapshot deletion (GHSA-g2hc-wmw2-32jr)#41624

Merged
subrata71 merged 3 commits intoreleasefrom
fix/snapshot-bola-delete-authz-GHSA-g2hc-wmw2-32jr
Mar 19, 2026
Merged

fix(server): enforce edit permission on application snapshot deletion (GHSA-g2hc-wmw2-32jr)#41624
subrata71 merged 3 commits intoreleasefrom
fix/snapshot-bola-delete-authz-GHSA-g2hc-wmw2-32jr

Conversation

@subrata71
Copy link
Collaborator

@subrata71 subrata71 commented Mar 16, 2026

Description

Fixes a Broken Object-Level Authorization (BOLA/IDOR) vulnerability in the application snapshot deletion endpoint (GHSA-g2hc-wmw2-32jr).

Root cause: ApplicationSnapshotServiceCEImpl.deleteSnapshot was calling applicationSnapshotRepository.deleteAllByApplicationId directly without performing any authorization check. Any authenticated user who knew a target application ID could send DELETE /api/v1/applications/snapshot/{appId} and successfully destroy that application's snapshots — including snapshots belonging to other users and tenants.

Fix: Mirror the existing restoreSnapshot pattern in the same class. Resolve the application via applicationService.findById(id, applicationPermission.getEditPermission()) before executing the delete. When the caller does not have edit permission on the application, findById returns empty, which triggers switchIfEmpty and returns NO_RESOURCE_FOUND to the caller — identical behavior to all other protected operations in this service.

Changes:

  • ApplicationSnapshotServiceCEImpl.java: 5-line change to deleteSnapshot — permission check added, no interface or API signature changes
  • ApplicationSnapshotServiceTest.java: Updated existing deleteSnapshot happy-path test to run under a real user + owned application; added new regression test deleteSnapshot_WhenUserHasNoAccess_ThrowsError asserting that an inaccessible app ID returns AppsmithError.NO_RESOURCE_FOUND

Fixes https://linear.app/appsmith/issue/APP-15032/high-broken-object-level-authorization-allows-non-owner-to-delete

Automation

/ok-to-test tags="@tag.All"

🔍 Cypress test results

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/23285869385
Commit: e4911c0
Cypress dashboard.
Tags: @tag.All
Spec:


Thu, 19 Mar 2026 09:54:26 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • Bug Fixes

    • Snapshot read and delete actions now validate application existence and user permissions before proceeding; unauthorized access returns a clear error.
  • Tests

    • Added tests covering access control for snapshot deletion and snapshot read-without-data to assert proper error handling for users without access.

Closes GHSA-g2hc-wmw2-32jr. The deleteSnapshot service method was
performing no authorization check, allowing any authenticated user to
delete snapshots belonging to applications they do not own or have
access to (BOLA/IDOR vulnerability).

Fix mirrors the existing restoreSnapshot pattern in the same class:
resolve the application via applicationService.findById with
getEditPermission() before executing the delete, returning
NO_RESOURCE_FOUND to the caller when permission is absent.

Also updates the deleteSnapshot happy-path test to run under a real
user context with an owned application, and adds a regression test
that asserts the error is returned for an inaccessible application ID.
@subrata71 subrata71 added the ok-to-test Required label for CI label Mar 16, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2026

Walkthrough

Both getWithoutDataByBranchedApplicationId and deleteSnapshot now resolve the target Application via applicationService.findById(...) (read permission for the getter, edit for delete), raising NO_RESOURCE_FOUND if absent, and then operate on snapshots by the resolved application.getId(). Tests added for unauthorized access and updated existing test setup.

Changes

Cohort / File(s) Summary
Service Implementation
app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceCEImpl.java
Both getWithoutDataByBranchedApplicationId and deleteSnapshot now first fetch the Application (enforcing read/edit permission respectively) and use the resolved application.getId() for snapshot queries; previously snapshots were queried/deleted directly by the passed branchedApplicationId.
Service Tests
app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java
Updated deleteSnapshot_WhenSnapshotExists_Deleted to use real Application creation and snapshot creation via service; added deleteSnapshot_WhenUserHasNoAccess_ThrowsError and getWithoutDataByBranchedApplicationId_WhenUserHasNoAccess_ThrowsError to assert AppsmithError.NO_RESOURCE_FOUND when the caller lacks access.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AppSnapshotService as SnapshotService
    participant ApplicationService as AppService
    participant SnapshotRepo as SnapshotRepository

    Client->>SnapshotService: deleteSnapshot(branchedApplicationId)
    SnapshotService->>AppService: findById(branchedApplicationId, EDIT)
    AppService-->>SnapshotService: Application (or NOT_FOUND)
    alt Application found
        SnapshotService->>SnapshotRepo: deleteByApplicationId(application.id)
        SnapshotRepo-->>SnapshotService: delete result
        SnapshotService-->>Client: success
    else Not found / no access
        AppService-->>SnapshotService: NO_RESOURCE_FOUND
        SnapshotService-->>Client: error (NO_RESOURCE_FOUND)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🔎 Resolve first, then clear the slate,
Lookup, permission—then delete the state.
Tests assert the guard's command,
Snapshots fall by rightful hand. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding edit permission enforcement to the snapshot deletion endpoint to fix a security vulnerability.
Description check ✅ Passed PR description comprehensively covers the security vulnerability, root cause, fix methodology, and specific code changes with test updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/snapshot-bola-delete-authz-GHSA-g2hc-wmw2-32jr
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@subrata71 subrata71 self-assigned this Mar 16, 2026
@subrata71 subrata71 added ok-to-test Required label for CI and removed ok-to-test Required label for CI labels Mar 16, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java`:
- Around line 299-320: The test deleteSnapshot_WhenUserHasNoAccess_ThrowsError
currently uses a randomAppId so it only exercises the “missing resource” path;
instead, create and persist a real Application owned by the other user (the one
set up in `@BeforeEach`, e.g. the api_user context) and capture its id, then
switch to the `@WithUserDetails`("usertest@usertest.com") context and call
applicationSnapshotService.deleteSnapshot(existingAppId) to verify it produces
AppsmithError.NO_RESOURCE_FOUND for FieldName.APPLICATION; update the test to
use the persisted application's id (not a random id) and keep the
StepVerifier.expectErrorMatches assertion against
AppsmithError.NO_RESOURCE_FOUND.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2921429d-6ec5-4dfc-9367-a36b802a2523

📥 Commits

Reviewing files that changed from the base of the PR and between 470aa9e and 7b4e25c.

📒 Files selected for processing (2)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceCEImpl.java
  • app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java

@linear
Copy link

linear bot commented Mar 19, 2026

@subrata71 subrata71 requested a review from sondermanish March 19, 2026 08:03
…rove tests

Adds the missing authorization check to getWithoutDataByBranchedApplicationId,
which was querying snapshot metadata directly from the repository without
verifying the caller's permission on the application (the existing comment
claimed a permission check but the code never performed one).

Uses applicationPermission.getReadPermission() (READ_APPLICATIONS) since
this is a read-only operation, mirroring the edit-permission pattern
already applied to deleteSnapshot and restoreSnapshot.

Also cleans up the deleteSnapshot no-access regression test (removes
dead code for an Application object that was created but never persisted)
and adds a matching regression test for the GET endpoint.

All four snapshot operations now enforce authorization consistently:
- create  → MANAGE_APPLICATIONS (via exportService)
- restore → MANAGE_APPLICATIONS (explicit)
- delete  → MANAGE_APPLICATIONS (explicit)
- get     → READ_APPLICATIONS   (explicit, added here)
Copy link
Contributor

@sondermanish sondermanish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@subrata71 subrata71 merged commit f46326c into release Mar 19, 2026
149 of 153 checks passed
@subrata71 subrata71 deleted the fix/snapshot-bola-delete-authz-GHSA-g2hc-wmw2-32jr branch March 19, 2026 10:44
subrata71 added a commit that referenced this pull request Mar 19, 2026
… (GHSA-g2hc-wmw2-32jr) (#41624)

## Description

Fixes a Broken Object-Level Authorization (BOLA/IDOR) vulnerability in
the application snapshot deletion endpoint (GHSA-g2hc-wmw2-32jr).

**Root cause:** `ApplicationSnapshotServiceCEImpl.deleteSnapshot` was
calling `applicationSnapshotRepository.deleteAllByApplicationId`
directly without performing any authorization check. Any authenticated
user who knew a target application ID could send `DELETE
/api/v1/applications/snapshot/{appId}` and successfully destroy that
application's snapshots — including snapshots belonging to other users
and tenants.

**Fix:** Mirror the existing `restoreSnapshot` pattern in the same
class. Resolve the application via `applicationService.findById(id,
applicationPermission.getEditPermission())` before executing the delete.
When the caller does not have edit permission on the application,
`findById` returns empty, which triggers `switchIfEmpty` and returns
`NO_RESOURCE_FOUND` to the caller — identical behavior to all other
protected operations in this service.

**Changes:**
- `ApplicationSnapshotServiceCEImpl.java`: 5-line change to
`deleteSnapshot` — permission check added, no interface or API signature
changes
- `ApplicationSnapshotServiceTest.java`: Updated existing
`deleteSnapshot` happy-path test to run under a real user + owned
application; added new regression test
`deleteSnapshot_WhenUserHasNoAccess_ThrowsError` asserting that an
inaccessible app ID returns `AppsmithError.NO_RESOURCE_FOUND`

Fixes
https://linear.app/appsmith/issue/APP-15032/high-broken-object-level-authorization-allows-non-owner-to-delete

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/23285869385>
> Commit: e4911c0
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=23285869385&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 19 Mar 2026 09:54:26 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Snapshot read and delete actions now validate application existence
and user permissions before proceeding; unauthorized access returns a
clear error.

* **Tests**
* Added tests covering access control for snapshot deletion and snapshot
read-without-data to assert proper error handling for users without
access.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Required label for CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants