Authorization Bypass Through User-Controlled Key
The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.
Retrieval of a user record usually occurs in the system based on some key value. When a value that is directly specified by the user is used to look up that record, the key value can be modified to access records belonging to other users.
How to fix this vulnerability
Prevention strategies for Authorization Bypass via User Key based on 8 Shoulder detection rules.
Validate resource ownership before allowing modifications using user-supplied IDs
func updateProfile(c *gin.Context) { profileID := c.Param("id") - db.Model(&Profile{}).Where("id = ?", profileID).Updates(data) + userID := c.GetString("user_id") + var profile Profile + db.First(&profile, profileID) + if profile.UserID != userID { + c.JSON(403, gin.H{"error": "unauthorized"}) + return + } + db.Model(&profile).Updates(data) }
Validate resource ownership before database access using user-supplied IDs
func getUser(c *gin.Context) { - userID := c.Param("id") - var user User - db.First(&user, userID) + requestedID := c.Param("id") + currentID := c.GetString("user_id") + if requestedID != currentID { + c.JSON(403, gin.H{"error": "unauthorized"}) + return + } + var user User + db.First(&user, requestedID) c.JSON(200, user) }
Verify resource ownership before returning data accessed by user-supplied identifiers
func getOrder(c *gin.Context) { orderID := c.Param("id") - order := orders[orderID] + currentUserID := c.GetString("user_id") + order := orders[orderID] + if order.UserID != currentUserID { + c.JSON(403, gin.H{"error": "Forbidden"}) + return + } c.JSON(200, order) }
Filter queries by authenticated user ID to verify resource ownership
app.get('/api/profile/:userId', async (req, res) => { - const profile = await User.findOne({ where: { id: req.params.userId } }); + const profile = await User.findOne({ + where: { id: req.params.userId, userId: req.user.id } + }); + if (!profile) return res.status(403).json({ error: 'Forbidden' }); res.json(profile); });
Include userId in database queries to verify resource ownership before access
app.get('/api/orders/:id', async (req, res) => { - const order = await Order.findByPk(req.params.id); + const order = await Order.findOne({ + where: { id: req.params.id, userId: req.user.id } + }); + if (!order) return res.status(404).json({ error: 'Not found' }); res.json(order); });
Verify resource ownership before returning data by checking it belongs to the authenticated user
app.get('/api/orders/:id', (req, res) => { const order = orderRepo.findById(req.params.id); + if (order.userId !== req.user.id) { + return res.status(403).json({ error: 'Forbidden' }); + } res.json(order); });
Include the authenticated user as a filter condition in all ORM queries that use user-supplied IDs
- def get_document(request, doc_id): - requested_id = request.GET.get('id') - document = Document.objects.get(id=requested_id) + from django.contrib.auth.decorators import login_required + + @login_required + def get_document(request, doc_id): + requested_id = request.GET.get('id') + document = Document.objects.get( + id=requested_id, + owner=request.user + ) return JsonResponse(document.to_dict())
Find vulnerabilities in your code
Use Shoulder to scan your codebase for Authorization Bypass Through User-Controlled Key patterns. 8 rules.
# Scan with Shoulder CLI npx @shoulderdev/cli trust --cwe=639 # Or scan entire project npx @shoulderdev/cli trust .
Detection Rules (8)
What to watch for in code reviews
These patterns indicate potential Authorization Bypass Through User-Controlled Key vulnerabilities. Look for these during code reviews and security audits.
Scan your codebase for Authorization Bypass Through User-Controlled Key
Shoulder CLI finds vulnerable patterns across your entire codebase.