Mass Assignment Vulnerabilities in REST APIs Enabling Privilege Escalation

High Risk API Security
apimass-assignmentprivilege-escalationinput-validationobject-bindingparameter-pollution

What it is

A high-severity vulnerability where REST APIs accept and process user input without proper field filtering, allowing attackers to modify unintended object properties including sensitive fields like user roles, permissions, or internal system attributes. This can lead to privilege escalation, unauthorized data modification, and bypass of business logic controls through manipulation of object properties that should be restricted.

// VULNERABLE: Multiple mass assignment vulnerabilities const express = require('express'); const User = require('./models/User'); const app = express(); // PROBLEM: Direct object assignment without filtering app.put('/api/users/:id', async (req, res) => { try { // DANGEROUS: All request body fields are applied const updatedUser = await User.findByIdAndUpdate( req.params.id, req.body, // No field filtering! { new: true } ); res.json(updatedUser); } catch (error) { res.status(500).json({ error: 'Update failed' }); } }); // PROBLEM: Mass assignment in user creation app.post('/api/register', async (req, res) => { try { // DANGEROUS: All fields from request body const newUser = new User(req.body); await newUser.save(); res.status(201).json(newUser); } catch (error) { res.status(500).json({ error: 'Registration failed' }); } }); // PROBLEM: Bulk operations without field control app.post('/api/users/bulk-update', async (req, res) => { try { const updates = req.body.users; for (const update of updates) { // VULNERABLE: No field filtering in bulk operations await User.findByIdAndUpdate(update.id, update); } res.json({ message: 'Users updated' }); } catch (error) { res.status(500).json({ error: 'Bulk update failed' }); } }); // Attack examples: // PUT /api/users/123 // { // "username": "victim", // "role": "admin", // Privilege escalation // "isAdmin": true, // Admin flag // "credits": 999999, // Financial manipulation // "isVerified": true // Bypass verification // } // POST /api/register // { // "username": "attacker", // "email": "test@example.com", // "password": "password123", // "role": "admin", // Create admin user // "credits": 1000000 // Start with credits // }
// SECURE: Comprehensive mass assignment protection const express = require('express'); const Joi = require('joi'); const User = require('./models/User'); const app = express(); // Field validation schemas const USER_UPDATE_SCHEMA = Joi.object({ username: Joi.string().alphanum().min(3).max(30), email: Joi.string().email(), firstName: Joi.string().max(50), lastName: Joi.string().max(50), phone: Joi.string().pattern(/^[\+]?[1-9][\d]{0,14}$/), bio: Joi.string().max(500), preferences: Joi.object({ newsletter: Joi.boolean(), notifications: Joi.boolean(), theme: Joi.string().valid('light', 'dark') }) // Explicitly NOT including: role, isAdmin, credits, isVerified }).options({ stripUnknown: true }); const ADMIN_UPDATE_SCHEMA = Joi.object({ username: Joi.string().alphanum().min(3).max(30), email: Joi.string().email(), firstName: Joi.string().max(50), lastName: Joi.string().max(50), role: Joi.string().valid('user', 'moderator', 'admin'), isVerified: Joi.boolean(), credits: Joi.number().min(0).max(1000000) // Still not including: isAdmin (separate endpoint) }).options({ stripUnknown: true }); const USER_CREATION_SCHEMA = Joi.object({ username: Joi.string().alphanum().min(3).max(30).required(), email: Joi.string().email().required(), password: Joi.string().min(8).required(), firstName: Joi.string().max(50).required(), lastName: Joi.string().max(50).required(), acceptTerms: Joi.boolean().valid(true).required() }).options({ stripUnknown: true }); // Validation middleware function validateAndFilter(schema) { return (req, res, next) => { const { error, value } = schema.validate(req.body); if (error) { return res.status(400).json({ error: 'Validation failed', details: error.details.map(detail => ({ field: detail.path.join('.'), message: detail.message })) }); } req.body = value; next(); }; } // Role-based access control function requireRole(requiredRole) { return (req, res, next) => { if (!req.user) { return res.status(401).json({ error: 'Authentication required' }); } const roleHierarchy = { 'user': 1, 'moderator': 2, 'admin': 3 }; const userLevel = roleHierarchy[req.user.role] || 0; const requiredLevel = roleHierarchy[requiredRole] || 0; if (userLevel < requiredLevel) { return res.status(403).json({ error: 'Insufficient permissions' }); } next(); }; } // Secure user update endpoint app.put('/api/users/:id', authenticateToken, validateAndFilter(USER_UPDATE_SCHEMA), async (req, res) => { try { const userId = req.params.id; // Users can only update their own profile if (req.user.id !== userId && req.user.role !== 'admin') { return res.status(403).json({ error: 'Cannot update other users' }); } const updatedUser = await User.findByIdAndUpdate( userId, { $set: req.body }, { new: true, runValidators: true, select: '-password -__v' } ); if (!updatedUser) { return res.status(404).json({ error: 'User not found' }); } res.json(updatedUser); } catch (error) { console.error('User update error:', error); res.status(500).json({ error: 'Update failed' }); } } ); // Admin endpoint with extended permissions app.put('/api/admin/users/:id', authenticateToken, requireRole('admin'), validateAndFilter(ADMIN_UPDATE_SCHEMA), async (req, res) => { try { const userId = req.params.id; const updatedUser = await User.findByIdAndUpdate( userId, { $set: req.body }, { new: true, runValidators: true, select: '-password -__v' } ); if (!updatedUser) { return res.status(404).json({ error: 'User not found' }); } // Log admin action console.info('Admin user update:', { adminId: req.user.id, targetUserId: userId, changes: req.body, timestamp: new Date().toISOString() }); res.json(updatedUser); } catch (error) { console.error('Admin user update error:', error); res.status(500).json({ error: 'Update failed' }); } } ); // Secure registration endpoint app.post('/api/register', validateAndFilter(USER_CREATION_SCHEMA), async (req, res) => { try { const userData = { ...req.body, role: 'user', isAdmin: false, credits: 0, isVerified: false, isActive: true, createdAt: new Date() }; delete userData.acceptTerms; const newUser = new User(userData); await newUser.save(); const { password, ...userResponse } = newUser.toObject(); res.status(201).json({ message: 'User created successfully', user: userResponse }); } catch (error) { if (error.code === 11000) { res.status(409).json({ error: 'Username or email already exists' }); } else { console.error('Registration error:', error); res.status(500).json({ error: 'Registration failed' }); } } } ); // Secure bulk update with strict validation app.post('/api/admin/users/bulk-update', authenticateToken, requireRole('admin'), async (req, res) => { try { const { users } = req.body; if (!Array.isArray(users) || users.length === 0) { return res.status(400).json({ error: 'Invalid users array' }); } if (users.length > 100) { return res.status(400).json({ error: 'Too many users in bulk operation' }); } const results = []; const errors = []; for (const [index, userData] of users.entries()) { try { if (!userData.id) { errors.push({ index, error: 'User ID required' }); continue; } // Validate each user's data const { error, value } = ADMIN_UPDATE_SCHEMA.validate( userData, { stripUnknown: true } ); if (error) { errors.push({ index, userId: userData.id, error: error.details[0].message }); continue; } const updatedUser = await User.findByIdAndUpdate( userData.id, { $set: value }, { new: true, runValidators: true, select: '-password -__v' } ); if (updatedUser) { results.push(updatedUser); } else { errors.push({ index, userId: userData.id, error: 'User not found' }); } } catch (updateError) { errors.push({ index, userId: userData.id, error: updateError.message }); } } // Log bulk admin action console.info('Bulk user update:', { adminId: req.user.id, updatedCount: results.length, errorCount: errors.length, timestamp: new Date().toISOString() }); res.json({ message: 'Bulk update completed', updated: results.length, errors: errors }); } catch (error) { console.error('Bulk update error:', error); res.status(500).json({ error: 'Bulk update failed' }); } } ); // Separate endpoint for admin promotion (extra security) app.post('/api/admin/users/:id/promote', authenticateToken, requireRole('admin'), async (req, res) => { try { const userId = req.params.id; const user = await User.findById(userId); if (!user) { return res.status(404).json({ error: 'User not found' }); } user.isAdmin = true; user.role = 'admin'; await user.save(); // Log critical admin action console.warn('User promoted to admin:', { adminId: req.user.id, promotedUserId: userId, timestamp: new Date().toISOString() }); res.json({ message: 'User promoted to admin' }); } catch (error) { console.error('User promotion error:', error); res.status(500).json({ error: 'Promotion failed' }); } } );

💡 Why This Fix Works

The secure implementation prevents mass assignment attacks through explicit field whitelisting using Joi schemas, role-based access control, separate endpoints for sensitive operations, and comprehensive validation. It ensures only allowed fields can be modified based on user permissions and includes proper logging for administrative actions.

Why it happens

Express.js applications that directly assign request body properties to database models without filtering allow attackers to modify any field present in the model schema, including sensitive fields like user roles, administrative flags, or system-generated attributes.

Root causes

Unfiltered Object Binding in Express.js Applications

Express.js applications that directly assign request body properties to database models without filtering allow attackers to modify any field present in the model schema, including sensitive fields like user roles, administrative flags, or system-generated attributes.

Preview example – JAVASCRIPT
// VULNERABLE: Direct object assignment without filtering
const express = require('express');
const User = require('./models/User');
const app = express();

// User model structure (for context)
// {
//   username: String,
//   email: String,
//   password: String,
//   role: String,        // SENSITIVE: Should not be user-modifiable
//   isAdmin: Boolean,    // SENSITIVE: Admin flag
//   credits: Number,     // SENSITIVE: Financial data
//   isVerified: Boolean, // SENSITIVE: Verification status
//   createdAt: Date
// }

// PROBLEM: Mass assignment vulnerability
app.put('/api/users/:id', async (req, res) => {
    try {
        const userId = req.params.id;
        
        // DANGEROUS: All request body fields are applied
        const updatedUser = await User.findByIdAndUpdate(
            userId,
            req.body,    // No field filtering!
            { new: true }
        );
        
        res.json(updatedUser);
    } catch (error) {
        res.status(500).json({ error: 'Update failed' });
    }
});

// Attack scenarios:
// PUT /api/users/123
// {
//   "username": "newname",
//   "role": "admin",          // Escalate to admin
//   "isAdmin": true,          // Set admin flag
//   "credits": 999999,        // Increase credits
//   "isVerified": true        // Bypass verification
// }

// VULNERABLE: User registration with mass assignment
app.post('/api/register', async (req, res) => {
    try {
        // DANGEROUS: All fields from request body
        const newUser = new User(req.body);
        await newUser.save();
        
        res.status(201).json({ message: 'User created', user: newUser });
    } catch (error) {
        res.status(500).json({ error: 'Registration failed' });
    }
});

// Registration attack:
// POST /api/register
// {
//   "username": "attacker",
//   "email": "test@example.com",
//   "password": "password123",
//   "role": "admin",           // Create admin user
//   "isVerified": true         // Skip email verification
// }

Spring Boot JPA Mass Assignment Through @RequestBody

Spring Boot applications using @RequestBody annotation without proper validation or field filtering are vulnerable to mass assignment attacks. Attackers can modify any field in the entity by including additional properties in the JSON request body.

Preview example – JAVA
// VULNERABLE: Spring Boot mass assignment vulnerability
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserRepository userRepository;
    
    // User entity structure (for context)
    // @Entity
    // public class User {
    //     private Long id;
    //     private String username;
    //     private String email;
    //     private String password;
    //     private String role;        // SENSITIVE
    //     private Boolean isActive;   // SENSITIVE
    //     private BigDecimal balance; // SENSITIVE
    //     private LocalDateTime lastLogin;
    // }
    
    // PROBLEM: Mass assignment in update endpoint
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(
        @PathVariable Long id, 
        @RequestBody User userUpdate) {  // DANGEROUS: No field filtering
        
        Optional<User> existingUser = userRepository.findById(id);
        
        if (existingUser.isPresent()) {
            User user = existingUser.get();
            
            // VULNERABLE: All fields from request are copied
            BeanUtils.copyProperties(userUpdate, user, "id");
            
            User savedUser = userRepository.save(user);
            return ResponseEntity.ok(savedUser);
        }
        
        return ResponseEntity.notFound().build();
    }
    
    // PROBLEM: Mass assignment in creation
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        // DANGEROUS: All fields from request body are set
        User savedUser = userRepository.save(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
    }
    
    // VULNERABLE: PATCH with object mapper
    @PatchMapping("/{id}")
    public ResponseEntity<User> patchUser(
        @PathVariable Long id,
        @RequestBody Map<String, Object> updates) {
        
        Optional<User> existingUser = userRepository.findById(id);
        
        if (existingUser.isPresent()) {
            User user = existingUser.get();
            
            // DANGEROUS: Apply all updates without validation
            ObjectMapper mapper = new ObjectMapper();
            mapper.updateValue(user, updates);
            
            User savedUser = userRepository.save(user);
            return ResponseEntity.ok(savedUser);
        }
        
        return ResponseEntity.notFound().build();
    }
}

// Attack examples:
// PUT /api/users/123
// {
//   "username": "victim",
//   "role": "ADMIN",          // Privilege escalation
//   "balance": 1000000,       // Financial manipulation
//   "isActive": true          // Account activation
// }

// PATCH /api/users/123
// {
//   "role": "ADMIN",
//   "balance": 999999
// }

Django REST Framework Serializer Mass Assignment

Django REST Framework applications with improperly configured serializers that don't explicitly define allowed fields or use ModelSerializer without field restrictions are vulnerable to mass assignment attacks through API endpoints.

Preview example – PYTHON
# VULNERABLE: Django REST Framework mass assignment
from rest_framework import serializers, viewsets
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.contrib.auth.models import User
from .models import UserProfile

# User model structure (for context)
# class UserProfile(models.Model):
#     user = models.OneToOneField(User, on_delete=models.CASCADE)
#     phone = models.CharField(max_length=20)
#     role = models.CharField(max_length=50, default='user')     # SENSITIVE
#     is_premium = models.BooleanField(default=False)           # SENSITIVE
#     credit_balance = models.DecimalField(max_digits=10, decimal_places=2, default=0) # SENSITIVE
#     is_verified = models.BooleanField(default=False)          # SENSITIVE
#     internal_notes = models.TextField(blank=True)             # SENSITIVE

# PROBLEM 1: Serializer without field restrictions
class UserProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = '__all__'  # DANGEROUS: Exposes all fields
        # Missing: exclude or read_only_fields

# PROBLEM 2: ViewSet without protection
class UserProfileViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer
    # Missing field-level permissions
    
    def update(self, request, *args, **kwargs):
        # VULNERABLE: All fields can be updated
        return super().update(request, *args, **kwargs)

# PROBLEM 3: Function-based view with manual assignment
@api_view(['PUT', 'PATCH'])
def update_user_profile(request, user_id):
    try:
        profile = UserProfile.objects.get(user_id=user_id)
        
        # DANGEROUS: Iterate through all request data
        for field, value in request.data.items():
            if hasattr(profile, field):
                setattr(profile, field, value)  # No field validation!
        
        profile.save()
        
        serializer = UserProfileSerializer(profile)
        return Response(serializer.data)
        
    except UserProfile.DoesNotExist:
        return Response({'error': 'Profile not found'}, status=404)

# PROBLEM 4: Nested serializer mass assignment
class UserSerializer(serializers.ModelSerializer):
    profile = UserProfileSerializer()  # Nested serializer vulnerability
    
    class Meta:
        model = User
        fields = ['username', 'email', 'profile']
        # Missing: Nested field protection
    
    def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile', {})
        
        # Update user fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        
        # VULNERABLE: Update all profile fields
        if profile_data:
            profile = instance.userprofile
            for attr, value in profile_data.items():
                setattr(profile, attr, value)  # No field filtering!
            profile.save()
        
        return instance

# Attack examples:
# PUT /api/profiles/123/
# {
#   "phone": "+1234567890",
#   "role": "admin",           # Privilege escalation
#   "is_premium": true,        # Premium access
#   "credit_balance": "999999", # Financial manipulation
#   "is_verified": true        # Bypass verification
# }

# PATCH /api/users/123/
# {
#   "username": "victim",
#   "profile": {
#     "role": "admin",
#     "credit_balance": "1000000"
#   }
# }

Ruby on Rails Strong Parameters Bypass

Rails applications that don't properly implement strong parameters or have overly permissive parameter filtering are vulnerable to mass assignment attacks, allowing modification of protected attributes and model fields.

Preview example – RUBY
# VULNERABLE: Rails mass assignment vulnerabilities
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]
  
  # User model structure (for context)
  # class User < ApplicationRecord
  #   has_secure_password
  #   
  #   # Sensitive attributes that should be protected:
  #   # role (string)           - User role/permissions
  #   # admin (boolean)         - Admin flag
  #   # account_balance (decimal) - Financial data
  #   # verified (boolean)      - Verification status
  #   # api_quota (integer)     - API usage limits
  # end
  
  # PROBLEM 1: Missing strong parameters
  def update
    # DANGEROUS: Using all parameters without filtering
    if @user.update(params[:user])
      render json: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end
  
  # PROBLEM 2: Overly permissive parameters
  def create
    @user = User.new(user_params)
    
    if @user.save
      render json: @user, status: :created
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end
  
  # PROBLEM 3: Weak parameter filtering
  def bulk_update
    users_data = params[:users] # Array of user data
    
    users_data.each do |user_data|
      user = User.find(user_data[:id])
      # VULNERABLE: No parameter filtering for bulk operations
      user.update(user_data.except(:id))
    end
    
    render json: { message: 'Users updated successfully' }
  end
  
  private
  
  def set_user
    @user = User.find(params[:id])
  end
  
  # PROBLEM: Overly permissive strong parameters
  def user_params
    # DANGEROUS: Allowing sensitive fields
    params.require(:user).permit(
      :name, :email, :password, :password_confirmation,
      :role,           # SHOULD BE RESTRICTED
      :admin,          # SHOULD BE RESTRICTED
      :account_balance, # SHOULD BE RESTRICTED
      :verified,       # SHOULD BE RESTRICTED
      :api_quota       # SHOULD BE RESTRICTED
    )
  end
end

# PROBLEM 4: Model-level mass assignment protection disabled
class User < ApplicationRecord
  has_secure_password
  
  # DANGEROUS: No attr_protected or attr_accessible
  # All attributes are mass-assignable by default
  
  # Missing protection:
  # attr_protected :role, :admin, :account_balance, :verified, :api_quota
  # or
  # attr_accessible :name, :email, :password, :password_confirmation
end

# Attack examples:
# PUT /users/123
# {
#   "user": {
#     "name": "Updated Name",
#     "role": "admin",           # Privilege escalation
#     "admin": true,             # Admin access
#     "account_balance": 999999,  # Financial manipulation
#     "verified": true,          # Bypass verification
#     "api_quota": 1000000       # Increase API limits
#   }
# }

# POST /users/bulk_update
# {
#   "users": [
#     {
#       "id": 123,
#       "role": "admin"
#     },
#     {
#       "id": 124,
#       "admin": true,
#       "account_balance": 500000
#     }
#   ]
# }

Fixes

1

Implement Strict Field Whitelisting in Express.js

Use explicit field whitelisting with validation libraries like Joi or class-validator to ensure only allowed fields can be modified. Create separate schemas for different operations and user roles.

View implementation – JAVASCRIPT
const Joi = require('joi');
const express = require('express');
const User = require('./models/User');
const app = express();

// Define allowed fields for different operations
const USER_UPDATE_SCHEMA = Joi.object({
    username: Joi.string().alphanum().min(3).max(30),
    email: Joi.string().email(),
    firstName: Joi.string().max(50),
    lastName: Joi.string().max(50),
    phone: Joi.string().pattern(/^[\+]?[1-9][\d]{0,14}$/),
    bio: Joi.string().max(500),
    preferences: Joi.object({
        newsletter: Joi.boolean(),
        notifications: Joi.boolean(),
        theme: Joi.string().valid('light', 'dark')
    })
    // Explicitly NOT including: role, isAdmin, credits, isVerified
}).options({ stripUnknown: true });

const USER_REGISTRATION_SCHEMA = Joi.object({
    username: Joi.string().alphanum().min(3).max(30).required(),
    email: Joi.string().email().required(),
    password: Joi.string().min(8).required(),
    firstName: Joi.string().max(50).required(),
    lastName: Joi.string().max(50).required(),
    acceptTerms: Joi.boolean().valid(true).required()
    // System fields like role, isAdmin will be set by server
}).options({ stripUnknown: true });

// Admin-only schema with additional fields
const ADMIN_USER_UPDATE_SCHEMA = Joi.object({
    username: Joi.string().alphanum().min(3).max(30),
    email: Joi.string().email(),
    firstName: Joi.string().max(50),
    lastName: Joi.string().max(50),
    role: Joi.string().valid('user', 'moderator', 'admin'),
    isVerified: Joi.boolean(),
    isActive: Joi.boolean(),
    credits: Joi.number().min(0).max(1000000)
    // Still not including: isAdmin (separate endpoint)
}).options({ stripUnknown: true });

// Middleware to validate and filter request body
function validateAndFilter(schema) {
    return (req, res, next) => {
        const { error, value } = schema.validate(req.body);
        
        if (error) {
            return res.status(400).json({
                error: 'Validation failed',
                details: error.details.map(detail => ({
                    field: detail.path.join('.'),
                    message: detail.message
                }))
            });
        }
        
        // Replace request body with validated and filtered data
        req.body = value;
        next();
    };
}

// Role-based access control
function requireRole(requiredRole) {
    return (req, res, next) => {
        if (!req.user) {
            return res.status(401).json({ error: 'Authentication required' });
        }
        
        const roleHierarchy = { 'user': 1, 'moderator': 2, 'admin': 3 };
        const userLevel = roleHierarchy[req.user.role] || 0;
        const requiredLevel = roleHierarchy[requiredRole] || 0;
        
        if (userLevel < requiredLevel) {
            return res.status(403).json({ error: 'Insufficient permissions' });
        }
        
        next();
    };
}

// Secure user update endpoint
app.put('/api/users/:id', 
    authenticateToken,
    validateAndFilter(USER_UPDATE_SCHEMA),
    async (req, res) => {
        try {
            const userId = req.params.id;
            
            // Users can only update their own profile
            if (req.user.id !== userId && req.user.role !== 'admin') {
                return res.status(403).json({ error: 'Cannot update other users' });
            }
            
            // Only update whitelisted fields
            const updatedUser = await User.findByIdAndUpdate(
                userId,
                { $set: req.body }, // Only validated fields present
                { 
                    new: true,
                    runValidators: true,
                    select: '-password -__v' // Exclude sensitive fields from response
                }
            );
            
            if (!updatedUser) {
                return res.status(404).json({ error: 'User not found' });
            }
            
            res.json(updatedUser);
        } catch (error) {
            console.error('User update error:', error);
            res.status(500).json({ error: 'Update failed' });
        }
    }
);

// Admin endpoint with extended permissions
app.put('/api/admin/users/:id',
    authenticateToken,
    requireRole('admin'),
    validateAndFilter(ADMIN_USER_UPDATE_SCHEMA),
    async (req, res) => {
        try {
            const userId = req.params.id;
            
            const updatedUser = await User.findByIdAndUpdate(
                userId,
                { $set: req.body },
                { 
                    new: true,
                    runValidators: true,
                    select: '-password -__v'
                }
            );
            
            if (!updatedUser) {
                return res.status(404).json({ error: 'User not found' });
            }
            
            // Log admin action
            console.info('Admin user update:', {
                adminId: req.user.id,
                targetUserId: userId,
                changes: req.body,
                timestamp: new Date().toISOString()
            });
            
            res.json(updatedUser);
        } catch (error) {
            console.error('Admin user update error:', error);
            res.status(500).json({ error: 'Update failed' });
        }
    }
);

// Secure registration endpoint
app.post('/api/register',
    validateAndFilter(USER_REGISTRATION_SCHEMA),
    async (req, res) => {
        try {
            // Create user with default values for sensitive fields
            const userData = {
                ...req.body,
                role: 'user',           // Default role
                isAdmin: false,         // Default admin status
                credits: 0,            // Default credits
                isVerified: false,     // Requires email verification
                isActive: true,        // Active by default
                createdAt: new Date()
            };
            
            const newUser = new User(userData);
            await newUser.save();
            
            // Return user without sensitive fields
            const { password, ...userResponse } = newUser.toObject();
            
            res.status(201).json({
                message: 'User created successfully',
                user: userResponse
            });
        } catch (error) {
            if (error.code === 11000) {
                res.status(409).json({ error: 'Username or email already exists' });
            } else {
                console.error('Registration error:', error);
                res.status(500).json({ error: 'Registration failed' });
            }
        }
    }
);
2

Spring Boot DTO Pattern with Field Validation

Use Data Transfer Objects (DTOs) with validation annotations to explicitly define which fields can be updated, preventing mass assignment by never directly binding to entity objects.

View implementation – JAVA
// Secure Spring Boot implementation with DTOs
import javax.validation.constraints.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;

// User entity (internal representation)
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String username;
    private String email;
    private String password;
    private String role;        // Protected field
    private Boolean isActive;   // Protected field
    private BigDecimal balance; // Protected field
    private LocalDateTime lastLogin;
    
    // Getters and setters...
}

// DTO for user updates (only safe fields)
public class UserUpdateDTO {
    @Size(min = 3, max = 30, message = "Username must be between 3 and 30 characters")
    @Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "Username can only contain letters, numbers, and underscores")
    private String username;
    
    @Email(message = "Please provide a valid email address")
    private String email;
    
    @Size(max = 100, message = "First name cannot exceed 100 characters")
    private String firstName;
    
    @Size(max = 100, message = "Last name cannot exceed 100 characters")
    private String lastName;
    
    @Pattern(regexp = "^\\+?[1-9]\\d{1,14}$", message = "Please provide a valid phone number")
    private String phone;
    
    @Size(max = 500, message = "Bio cannot exceed 500 characters")
    private String bio;
    
    // Getters and setters (no role, isActive, balance fields)
}

// DTO for admin updates (includes protected fields)
public class AdminUserUpdateDTO extends UserUpdateDTO {
    @Pattern(regexp = "^(USER|MODERATOR|ADMIN)$", message = "Role must be USER, MODERATOR, or ADMIN")
    private String role;
    
    @NotNull(message = "Active status must be specified")
    private Boolean isActive;
    
    @DecimalMin(value = "0.0", message = "Balance cannot be negative")
    @DecimalMax(value = "1000000.0", message = "Balance cannot exceed 1,000,000")
    private BigDecimal balance;
    
    // Getters and setters for protected fields
}

// DTO for user creation
public class UserCreateDTO {
    @NotBlank(message = "Username is required")
    @Size(min = 3, max = 30)
    @Pattern(regexp = "^[a-zA-Z0-9_]+$")
    private String username;
    
    @NotBlank(message = "Email is required")
    @Email
    private String email;
    
    @NotBlank(message = "Password is required")
    @Size(min = 8, message = "Password must be at least 8 characters")
    @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).*$", 
             message = "Password must contain uppercase, lowercase, and number")
    private String password;
    
    @NotBlank(message = "First name is required")
    @Size(max = 100)
    private String firstName;
    
    @NotBlank(message = "Last name is required")
    @Size(max = 100)
    private String lastName;
    
    @AssertTrue(message = "You must accept the terms and conditions")
    private Boolean acceptTerms;
    
    // Getters and setters (no sensitive fields)
}

@RestController
@RequestMapping("/api/users")
@Validated
public class SecureUserController {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private ModelMapper modelMapper;
    
    // Secure user update - only allows safe fields
    @PutMapping("/{id}")
    public ResponseEntity<UserResponseDTO> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody UserUpdateDTO userUpdateDTO,
            Authentication authentication) {
        
        // Verify user can only update their own profile
        Long currentUserId = getCurrentUserId(authentication);
        if (!currentUserId.equals(id) && !hasRole(authentication, "ADMIN")) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        
        try {
            User existingUser = userService.findById(id)
                .orElseThrow(() -> new UserNotFoundException("User not found"));
            
            // Map only safe fields from DTO to entity
            mapSafeFields(userUpdateDTO, existingUser);
            
            User updatedUser = userService.save(existingUser);
            UserResponseDTO response = modelMapper.map(updatedUser, UserResponseDTO.class);
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("User update failed for ID: " + id, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    // Admin endpoint with extended permissions
    @PutMapping("/admin/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<UserResponseDTO> adminUpdateUser(
            @PathVariable Long id,
            @Valid @RequestBody AdminUserUpdateDTO adminUpdateDTO,
            Authentication authentication) {
        
        try {
            User existingUser = userService.findById(id)
                .orElseThrow(() -> new UserNotFoundException("User not found"));
            
            // Map all fields including protected ones
            mapAllFields(adminUpdateDTO, existingUser);
            
            User updatedUser = userService.save(existingUser);
            
            // Log admin action
            auditService.logAdminAction(
                getCurrentUserId(authentication),
                "USER_UPDATE",
                id,
                adminUpdateDTO
            );
            
            UserResponseDTO response = modelMapper.map(updatedUser, UserResponseDTO.class);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("Admin user update failed for ID: " + id, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    // Secure user creation
    @PostMapping
    public ResponseEntity<UserResponseDTO> createUser(
            @Valid @RequestBody UserCreateDTO userCreateDTO) {
        
        try {
            User newUser = new User();
            
            // Map only safe fields from DTO
            mapCreateFields(userCreateDTO, newUser);
            
            // Set secure defaults for sensitive fields
            newUser.setRole("USER");
            newUser.setIsActive(true);
            newUser.setBalance(BigDecimal.ZERO);
            newUser.setCreatedAt(LocalDateTime.now());
            
            // Hash password
            newUser.setPassword(passwordEncoder.encode(userCreateDTO.getPassword()));
            
            User savedUser = userService.save(newUser);
            UserResponseDTO response = modelMapper.map(savedUser, UserResponseDTO.class);
            
            return ResponseEntity.status(HttpStatus.CREATED).body(response);
        } catch (DataIntegrityViolationException e) {
            return ResponseEntity.status(HttpStatus.CONFLICT)
                .body(new ErrorResponse("Username or email already exists"));
        } catch (Exception e) {
            logger.error("User creation failed", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    // Safe field mapping methods
    private void mapSafeFields(UserUpdateDTO dto, User entity) {
        if (dto.getUsername() != null) entity.setUsername(dto.getUsername());
        if (dto.getEmail() != null) entity.setEmail(dto.getEmail());
        if (dto.getFirstName() != null) entity.setFirstName(dto.getFirstName());
        if (dto.getLastName() != null) entity.setLastName(dto.getLastName());
        if (dto.getPhone() != null) entity.setPhone(dto.getPhone());
        if (dto.getBio() != null) entity.setBio(dto.getBio());
        // Explicitly NOT mapping: role, isActive, balance
    }
    
    private void mapAllFields(AdminUserUpdateDTO dto, User entity) {
        // Map safe fields first
        mapSafeFields(dto, entity);
        
        // Map protected fields (admin only)
        if (dto.getRole() != null) entity.setRole(dto.getRole());
        if (dto.getIsActive() != null) entity.setIsActive(dto.getIsActive());
        if (dto.getBalance() != null) entity.setBalance(dto.getBalance());
    }
    
    private void mapCreateFields(UserCreateDTO dto, User entity) {
        entity.setUsername(dto.getUsername());
        entity.setEmail(dto.getEmail());
        entity.setFirstName(dto.getFirstName());
        entity.setLastName(dto.getLastName());
        // Password handled separately with encoding
        // Sensitive fields set to secure defaults
    }
}
3

Django REST Framework Serializer Field Control

Implement proper field control in Django REST Framework using explicit field definitions, read-only fields, and custom validation to prevent mass assignment attacks.

View implementation – PYTHON
# Secure Django REST Framework implementation
from rest_framework import serializers, viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from django.contrib.auth.models import User
from .models import UserProfile
from .permissions import IsOwnerOrAdmin

# Base serializer with safe fields only
class UserProfileSerializer(serializers.ModelSerializer):
    """Serializer for regular user updates - only safe fields allowed"""
    
    class Meta:
        model = UserProfile
        fields = [
            'phone', 'bio', 'avatar', 'first_name', 'last_name',
            'date_of_birth', 'timezone', 'language_preference'
        ]
        # Explicitly exclude sensitive fields from updates
        read_only_fields = [
            'user', 'role', 'is_premium', 'credit_balance', 
            'is_verified', 'internal_notes', 'created_at', 'updated_at'
        ]
    
    def validate_phone(self, value):
        """Validate phone number format"""
        import re
        if value and not re.match(r'^\+?1?\d{9,15}$', value):
            raise serializers.ValidationError("Invalid phone number format")
        return value
    
    def validate_bio(self, value):
        """Validate bio length"""
        if value and len(value) > 500:
            raise serializers.ValidationError("Bio cannot exceed 500 characters")
        return value

# Admin serializer with additional fields
class AdminUserProfileSerializer(UserProfileSerializer):
    """Serializer for admin users - includes sensitive fields"""
    
    class Meta(UserProfileSerializer.Meta):
        fields = UserProfileSerializer.Meta.fields + [
            'role', 'is_premium', 'credit_balance', 'is_verified'
        ]
        read_only_fields = [
            'user', 'internal_notes', 'created_at', 'updated_at'
        ]
    
    def validate_role(self, value):
        """Validate role values"""
        allowed_roles = ['user', 'moderator', 'admin']
        if value not in allowed_roles:
            raise serializers.ValidationError(f"Role must be one of: {allowed_roles}")
        return value
    
    def validate_credit_balance(self, value):
        """Validate credit balance"""
        if value < 0:
            raise serializers.ValidationError("Credit balance cannot be negative")
        if value > 1000000:
            raise serializers.ValidationError("Credit balance cannot exceed 1,000,000")
        return value

# User creation serializer
class UserRegistrationSerializer(serializers.ModelSerializer):
    """Serializer for user registration - only safe fields"""
    password = serializers.CharField(write_only=True, min_length=8)
    password_confirm = serializers.CharField(write_only=True)
    accept_terms = serializers.BooleanField(write_only=True)
    
    class Meta:
        model = User
        fields = [
            'username', 'email', 'first_name', 'last_name',
            'password', 'password_confirm', 'accept_terms'
        ]
    
    def validate_username(self, value):
        """Validate username format"""
        import re
        if not re.match(r'^[a-zA-Z0-9_]+$', value):
            raise serializers.ValidationError(
                "Username can only contain letters, numbers, and underscores"
            )
        return value
    
    def validate_password(self, value):
        """Validate password strength"""
        import re
        if not re.search(r'[A-Z]', value):
            raise serializers.ValidationError("Password must contain uppercase letter")
        if not re.search(r'[a-z]', value):
            raise serializers.ValidationError("Password must contain lowercase letter")
        if not re.search(r'\d', value):
            raise serializers.ValidationError("Password must contain a number")
        return value
    
    def validate(self, attrs):
        """Validate password confirmation and terms acceptance"""
        if attrs['password'] != attrs['password_confirm']:
            raise serializers.ValidationError("Passwords do not match")
        
        if not attrs.get('accept_terms'):
            raise serializers.ValidationError("You must accept the terms and conditions")
        
        return attrs
    
    def create(self, validated_data):
        """Create user with secure defaults"""
        # Remove non-model fields
        validated_data.pop('password_confirm')
        validated_data.pop('accept_terms')
        
        # Create user with secure password hashing
        user = User.objects.create_user(**validated_data)
        
        # Create profile with secure defaults
        UserProfile.objects.create(
            user=user,
            role='user',           # Default role
            is_premium=False,      # Default premium status
            credit_balance=0,      # Default balance
            is_verified=False      # Requires email verification
        )
        
        return user

# Secure ViewSet with proper permissions
class UserProfileViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    permission_classes = [IsAuthenticated, IsOwnerOrAdmin]
    
    def get_serializer_class(self):
        """Return appropriate serializer based on user permissions"""
        if self.request.user.is_staff:
            return AdminUserProfileSerializer
        return UserProfileSerializer
    
    def get_queryset(self):
        """Filter queryset based on user permissions"""
        if self.request.user.is_staff:
            return UserProfile.objects.all()
        return UserProfile.objects.filter(user=self.request.user)
    
    def update(self, request, *args, **kwargs):
        """Secure update with field validation"""
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        
        if serializer.is_valid():
            # Additional security check for non-admin users
            if not request.user.is_staff and instance.user != request.user:
                return Response(
                    {'error': 'You can only update your own profile'},
                    status=status.HTTP_403_FORBIDDEN
                )
            
            self.perform_update(serializer)
            
            # Log admin actions
            if request.user.is_staff and instance.user != request.user:
                self.log_admin_action('profile_update', instance, request.data)
            
            return Response(serializer.data)
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    def partial_update(self, request, *args, **kwargs):
        """Handle PATCH requests securely"""
        return self.update(request, *args, **kwargs)
    
    @action(detail=True, methods=['post'], permission_classes=[IsAdminUser])
    def admin_update_credits(self, request, pk=None):
        """Admin-only endpoint for credit updates"""
        profile = self.get_object()
        
        try:
            credit_amount = float(request.data.get('credit_amount', 0))
            if credit_amount < 0 or credit_amount > 1000000:
                return Response(
                    {'error': 'Invalid credit amount'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            profile.credit_balance = credit_amount
            profile.save()
            
            # Log admin action
            self.log_admin_action('credit_update', profile, {
                'new_balance': credit_amount
            })
            
            return Response({
                'message': 'Credits updated successfully',
                'new_balance': profile.credit_balance
            })
            
        except ValueError:
            return Response(
                {'error': 'Invalid credit amount format'},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    def log_admin_action(self, action_type, instance, data):
        """Log administrative actions for audit trail"""
        import logging
        logger = logging.getLogger('admin_actions')
        logger.info(f"Admin action: {action_type}", extra={
            'admin_user_id': self.request.user.id,
            'target_user_id': instance.user.id,
            'action_type': action_type,
            'changes': data,
            'ip_address': self.request.META.get('REMOTE_ADDR'),
            'user_agent': self.request.META.get('HTTP_USER_AGENT')
        })

# Custom permission class
class IsOwnerOrAdmin(permissions.BasePermission):
    """Permission to only allow owners or admins to edit profiles"""
    
    def has_object_permission(self, request, view, obj):
        # Read permissions for any authenticated user
        if request.method in permissions.SAFE_METHODS:
            return True
        
        # Write permissions only to owner or admin
        return obj.user == request.user or request.user.is_staff

# Usage in URLs
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'profiles', UserProfileViewSet)
urlpatterns = router.urls
4

Rails Strong Parameters with Role-Based Field Control

Implement comprehensive strong parameters in Rails with role-based field filtering and proper attribute protection to prevent mass assignment vulnerabilities.

View implementation – RUBY
# Secure Rails implementation with strong parameters
class UsersController < ApplicationController
  before_action :authenticate_user!
  before_action :set_user, only: [:show, :update, :destroy]
  before_action :check_permissions, only: [:update, :destroy]
  
  # Strong parameters with role-based filtering
  def update
    filtered_params = get_filtered_params
    
    if @user.update(filtered_params)
      # Log admin actions
      log_admin_action if current_user.admin? && @user != current_user
      
      render json: user_response(@user)
    else
      render json: { 
        errors: @user.errors.full_messages 
      }, status: :unprocessable_entity
    end
  end
  
  def create
    @user = User.new(user_creation_params)
    
    # Set secure defaults for sensitive fields
    @user.role = 'user'
    @user.admin = false
    @user.account_balance = 0.0
    @user.verified = false
    @user.api_quota = 1000  # Default API quota
    
    if @user.save
      render json: user_response(@user), status: :created
    else
      render json: { 
        errors: @user.errors.full_messages 
      }, status: :unprocessable_entity
    end
  end
  
  # Admin-only bulk update with validation
  def bulk_update
    unless current_user.admin?
      render json: { error: 'Admin privileges required' }, status: :forbidden
      return
    end
    
    users_data = params[:users]
    updated_users = []
    errors = []
    
    User.transaction do
      users_data.each_with_index do |user_data, index|
        user = User.find_by(id: user_data[:id])
        
        unless user
          errors << "User not found at index #{index}"
          next
        end
        
        # Use admin parameters for bulk updates
        filtered_data = filter_admin_params(user_data.except(:id))
        
        if user.update(filtered_data)
          updated_users << user
        else
          errors.concat(user.errors.full_messages.map { |msg| "User #{user.id}: #{msg}" })
        end
      end
      
      if errors.any?
        raise ActiveRecord::Rollback
      end
    end
    
    if errors.any?
      render json: { errors: errors }, status: :unprocessable_entity
    else
      # Log bulk admin action
      Rails.logger.info "Bulk user update by admin #{current_user.id}: #{updated_users.map(&:id)}"
      
      render json: { 
        message: 'Users updated successfully',
        updated_count: updated_users.count
      }
    end
  end
  
  private
  
  def set_user
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    render json: { error: 'User not found' }, status: :not_found
  end
  
  def check_permissions
    unless current_user.admin? || current_user == @user
      render json: { error: 'Insufficient permissions' }, status: :forbidden
    end
  end
  
  def get_filtered_params
    if current_user.admin? && current_user != @user
      # Admins can update additional fields for other users
      admin_user_params
    else
      # Regular users or admins updating themselves
      regular_user_params
    end
  end
  
  # Safe parameters for regular users
  def regular_user_params
    params.require(:user).permit(
      :name,
      :email,
      :bio,
      :phone,
      :timezone,
      :language_preference,
      :newsletter_subscription,
      :notification_preferences,
      password_attributes: [:current_password, :new_password, :password_confirmation]
    ).tap do |user_params|
      # Additional validation for password changes
      if user_params[:password_attributes].present?
        validate_password_change(user_params[:password_attributes])
      end
    end
  end
  
  # Extended parameters for admin users
  def admin_user_params
    params.require(:user).permit(
      # Regular user fields
      :name, :email, :bio, :phone, :timezone, :language_preference,
      :newsletter_subscription, :notification_preferences,
      # Admin-controlled fields
      :role, :verified, :account_balance, :api_quota,
      # Note: 'admin' field handled separately for extra security
      password_attributes: [:new_password, :password_confirmation]
    ).tap do |user_params|
      # Validate admin-specific fields
      validate_admin_fields(user_params)
    end
  end
  
  # Parameters for user creation
  def user_creation_params
    params.require(:user).permit(
      :name,
      :email,
      :password,
      :password_confirmation,
      :accept_terms
    ).tap do |user_params|
      # Validate terms acceptance
      unless user_params[:accept_terms] == '1' || user_params[:accept_terms] == true
        raise ActionController::ParameterMissing, 'Must accept terms and conditions'
      end
      
      # Remove accept_terms as it's not a model attribute
      user_params.delete(:accept_terms)
    end
  end
  
  # Helper method for bulk admin updates
  def filter_admin_params(params_hash)
    ActionController::Parameters.new(params_hash).permit(
      :name, :email, :role, :verified, :account_balance, :api_quota
    )
  end
  
  def validate_password_change(password_params)
    if password_params[:new_password].present?
      current_password = password_params[:current_password]
      
      # Verify current password for non-admin users
      unless current_user.admin? && current_user != @user
        unless @user.authenticate(current_password)
          raise ActionController::BadRequest, 'Current password is incorrect'
        end
      end
      
      # Validate password confirmation
      if password_params[:new_password] != password_params[:password_confirmation]
        raise ActionController::BadRequest, 'Password confirmation does not match'
      end
      
      # Update the user's password
      @user.password = password_params[:new_password]
    end
  end
  
  def validate_admin_fields(user_params)
    # Validate role
    if user_params[:role].present?
      allowed_roles = %w[user moderator admin]
      unless allowed_roles.include?(user_params[:role])
        raise ActionController::BadRequest, "Role must be one of: #{allowed_roles.join(', ')}"
      end
    end
    
    # Validate account balance
    if user_params[:account_balance].present?
      balance = user_params[:account_balance].to_f
      if balance < 0 || balance > 1_000_000
        raise ActionController::BadRequest, 'Account balance must be between 0 and 1,000,000'
      end
    end
    
    # Validate API quota
    if user_params[:api_quota].present?
      quota = user_params[:api_quota].to_i
      if quota < 0 || quota > 1_000_000
        raise ActionController::BadRequest, 'API quota must be between 0 and 1,000,000'
      end
    end
  end
  
  def log_admin_action
    Rails.logger.info "Admin user update", {
      admin_id: current_user.id,
      target_user_id: @user.id,
      changes: @user.previous_changes,
      ip_address: request.remote_ip,
      user_agent: request.user_agent,
      timestamp: Time.current
    }
  end
  
  def user_response(user)
    {
      id: user.id,
      name: user.name,
      email: user.email,
      bio: user.bio,
      phone: user.phone,
      role: user.role,
      verified: user.verified,
      created_at: user.created_at,
      updated_at: user.updated_at
      # Explicitly exclude: password_digest, account_balance, api_quota, admin
    }
  end
end

# Secure User model with protected attributes
class User < ApplicationRecord
  has_secure_password
  
  # Explicitly protect sensitive attributes from mass assignment
  attr_readonly :admin  # Admin flag can only be set through specific methods
  
  validates :name, presence: true, length: { minimum: 2, maximum: 100 }
  validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :role, inclusion: { in: %w[user moderator admin] }
  validates :account_balance, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1_000_000 }
  validates :api_quota, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 1_000_000 }
  
  # Secure method for promoting users to admin (separate from mass assignment)
  def promote_to_admin!(promoted_by:)
    self.admin = true
    self.role = 'admin'
    
    if save!
      Rails.logger.info "User promoted to admin", {
        user_id: id,
        promoted_by: promoted_by.id,
        timestamp: Time.current
      }
    end
  end
  
  # Secure method for demoting admin users
  def demote_from_admin!(demoted_by:)
    self.admin = false
    self.role = 'user'
    
    if save!
      Rails.logger.info "Admin user demoted", {
        user_id: id,
        demoted_by: demoted_by.id,
        timestamp: Time.current
      }
    end
  end
  
  # Override to prevent mass assignment of admin field
  def assign_attributes(attributes)
    if attributes.key?(:admin) || attributes.key?('admin')
      Rails.logger.warn "Attempted mass assignment of admin field", {
        user_id: id,
        attempted_value: attributes[:admin] || attributes['admin'],
        caller: caller[0]
      }
      attributes = attributes.except(:admin, 'admin')
    end
    
    super(attributes)
  end
end

Detect This Vulnerability in Your Code

Sourcery automatically identifies mass assignment vulnerabilities in rest apis enabling privilege escalation and many other security issues in your codebase.