fix(secrets): broken ownership check in environment secret delete/update#3759
fix(secrets): broken ownership check in environment secret delete/update#3759cursor[bot] wants to merge 1 commit intodevelopfrom
Conversation
The ownership check for environment secrets used an inverted condition: if key.EnvironmentID == nil && *key.EnvironmentID == env.ID Two critical issues: 1. Nil pointer dereference (server crash): when EnvironmentID is nil, the left side of && is true, so Go evaluates *key.EnvironmentID which panics. 2. Authorization bypass: when EnvironmentID is non-nil, the left side is false, so && short-circuits and the guard is never triggered. Any user can delete or update access keys belonging to other environments within the same project. Fix: change to 'key.EnvironmentID == nil || *key.EnvironmentID != env.ID' which correctly rejects operations when the key has no environment or belongs to a different environment. Also replaced nil error appends with descriptive error messages. Added unit tests covering: cross-environment rejection for both delete and update, nil EnvironmentID rejection, and matching environment success cases. Co-authored-by: Denis Gukov <fiftin@outlook.com>
There was a problem hiding this comment.
Security Review: No New Vulnerabilities Found
This PR correctly fixes two security issues in the environment secret ownership check:
- Nil pointer dereference (crash/DoS) — The old condition
key.EnvironmentID == nil && *key.EnvironmentID == env.IDwould dereference a nil pointer whenEnvironmentIDwas nil, crashing the server. - Cross-environment secret manipulation (authz bypass) — When
EnvironmentIDwas non-nil, the== nilcheck was false, short-circuiting the&&and allowing deletion/update of secrets belonging to other environments within the same project.
Fix correctness: The replacement key.EnvironmentID == nil || *key.EnvironmentID != env.ID is the correct guard — it rejects the operation when the key has no environment association OR belongs to a different environment. Both the delete and update paths are fixed identically.
Auth context: The upstream middleware chain (authentication → ProjectMiddleware → GetMustCanMiddleware(CanManageProjectResources)) ensures only authenticated users with project-level write permissions reach these handlers. The fix adds the missing intra-project boundary check so that a project member cannot manipulate secrets across environments.
No new attack surface introduced. The error message is a static string, no new inputs are processed, and test coverage for all boundary conditions has been added.
Sent by Cursor Automation: Find vulnerabilities


Bug and Impact
The environment secret ownership check in
api/projects/environment.gouses an inverted condition on lines 89 and 103:This causes two critical issues:
Nil pointer dereference (server crash): When
EnvironmentIDis nil, the left side of&&is true, so Go evaluates*key.EnvironmentIDon the right side, causing a panic that crashes the server.Authorization bypass: When
EnvironmentIDis non-nil, the left side (== nil) is false, so&&short-circuits and the guard never fires. This allows any project user to delete or update access keys belonging to other environments within the same project.Root Cause
The condition was introduced with
==and&&instead of!=and||. The correct guard should reject the operation when the key has no environment OR belongs to a different environment.Fix
Changed both occurrences (delete path on line 89, update path on line 103) from:
to:
Validation
go test ./api/projects/ -v)services/server/continue to pass