> ## Documentation Index
> Fetch the complete documentation index at: https://guide.codepure.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Business Logic Errors

> Mitigation for flaws in the design and implementation of business rules that can be exploited to bypass intended application behavior.

## Overview

This vulnerability occurs when an application's **business logic** contains flaws that allow attackers to manipulate the intended flow of operations. Unlike technical vulnerabilities, these are design-level issues where the application works as coded but the logic itself is flawed. Common examples include bypassing payment processes, manipulating shopping cart prices, circumventing rate limits, exploiting race conditions in financial transactions, or abusing workflow sequences to gain unauthorized privileges. 🎯💼

***

## Business Impact

Business logic flaws can have severe financial and operational consequences.

* **Financial Loss:** Direct monetary losses through price manipulation, bypassed payment flows, or fraudulent transactions.
* **Inventory Manipulation:** Purchasing items at incorrect prices, claiming excessive discounts, or manipulating stock levels.
* **Privilege Escalation:** Bypassing approval workflows or role-based restrictions to gain unauthorized access or capabilities.
* **Data Integrity Issues:** Creating inconsistent states in the database through race conditions or improper state transitions.

***

<Card title="Reference Details" icon="book-open" iconType="solid">
  **CWE ID:** [CWE-840](https://cwe.mitre.org/data/definitions/840.html)
  **OWASP Top 10 (2021):** A04:2021 - Insecure Design
  **Severity:** Medium to Critical (depending on the business impact)
</Card>

***

## Framework-Specific Analysis and Remediation

Business logic vulnerabilities are primarily **design and implementation** issues rather than configuration problems. They require careful analysis of application workflows, state management, and transaction processing.

The fix involves:

1. **State Validation:** Verify the application is in the correct state before allowing operations.
2. **Atomic Operations:** Use database transactions and locks to prevent race conditions.
3. **Server-Side Validation:** Never trust client-side data for critical business decisions.
4. **Workflow Enforcement:** Ensure operations can only occur in the intended sequence.

***

<Tabs>
  <Tab title="Python">
    #### Framework Context

    Common in Django and Flask applications handling e-commerce, financial transactions, or multi-step workflows. Issues often arise in views handling cart operations, payment processing, or user role transitions.

    #### Vulnerable Scenario 1: Price Manipulation in Shopping Cart

    ```python theme={null}
    # views.py (Django E-commerce - VULNERABLE)
    from django.views import View
    from django.http import JsonResponse
    import json

    class AddToCartView(View):
        def post(self, request):
            data = json.loads(request.body)
            product_id = data.get('product_id')
            quantity = data.get('quantity')
            # DANGEROUS: Accepting price from client
            price = data.get('price')  # Client can manipulate this!
            
            # Add to cart with client-provided price
            cart_item = CartItem.objects.create(
                user=request.user,
                product_id=product_id,
                quantity=quantity,
                price=price  # Using client-provided price
            )
            return JsonResponse({'status': 'success'})
    ```

    #### Vulnerable Scenario 2: Race Condition in Balance Transfer

    ```python theme={null}
    # views.py (Flask Banking App - VULNERABLE)
    @app.route('/transfer', methods=['POST'])
    @login_required
    def transfer_funds():
        amount = float(request.form['amount'])
        recipient_id = request.form['recipient_id']
        
        sender = User.query.get(current_user.id)
        recipient = User.query.get(recipient_id)
        
        # DANGEROUS: Non-atomic check and update
        if sender.balance >= amount:  # Check
            time.sleep(0.1)  # Simulating processing delay
            sender.balance -= amount  # Update (race condition window)
            recipient.balance += amount
            db.session.commit()
            return jsonify({'status': 'success'})
        return jsonify({'error': 'Insufficient funds'}), 400
    ```

    #### Mitigation and Best Practices

    * **Server-Side Price Validation:** Always fetch prices from the database based on product ID.
    * **Database Transactions:** Use atomic operations with proper locking mechanisms.
    * **State Machines:** Implement proper state transitions for multi-step processes.
    * **Idempotency:** Ensure operations can't be repeated to cause unintended effects.

    #### Secure Code Example

    ```python theme={null}
    # views.py (Django E-commerce - SECURE)
    from django.db import transaction
    from django.views import View
    from decimal import Decimal

    class AddToCartView(View):
        def post(self, request):
            data = json.loads(request.body)
            product_id = data.get('product_id')
            quantity = int(data.get('quantity', 1))
            
            # SECURE: Fetch price from database, not client
            try:
                product = Product.objects.select_for_update().get(id=product_id)
            except Product.DoesNotExist:
                return JsonResponse({'error': 'Product not found'}, status=404)
            
            # SECURE: Validate business rules
            if quantity <= 0 or quantity > product.max_per_order:
                return JsonResponse({'error': 'Invalid quantity'}, status=400)
            
            if product.stock < quantity:
                return JsonResponse({'error': 'Insufficient stock'}, status=400)
            
            # SECURE: Use server-side price
            cart_item = CartItem.objects.create(
                user=request.user,
                product=product,
                quantity=quantity,
                price=product.current_price  # Server-controlled price
            )
            return JsonResponse({'status': 'success'})

    # views.py (Flask Banking - SECURE)
    @app.route('/transfer', methods=['POST'])
    @login_required
    def transfer_funds():
        amount = Decimal(request.form['amount'])
        recipient_id = request.form['recipient_id']
        
        # SECURE: Validate amount
        if amount <= 0 or amount > Decimal('10000'):
            return jsonify({'error': 'Invalid amount'}), 400
        
        # SECURE: Use database transaction with row locking
        with db.session.begin():
            sender = User.query.with_for_update().get(current_user.id)
            recipient = User.query.with_for_update().get(recipient_id)
            
            if not recipient:
                return jsonify({'error': 'Recipient not found'}), 404
            
            if sender.balance < amount:
                return jsonify({'error': 'Insufficient funds'}), 400
            
            # SECURE: Atomic update within transaction
            sender.balance -= amount
            recipient.balance += amount
            
            # Log transaction for audit
            Transaction.create(
                sender_id=sender.id,
                recipient_id=recipient.id,
                amount=amount,
                timestamp=datetime.utcnow()
            )
        
        return jsonify({'status': 'success'})
    ```

    #### Testing Strategy

    Test with concurrent requests to identify race conditions. Attempt to manipulate client-side values (prices, quantities, IDs). Verify state transitions follow the intended workflow. Use tools like Locust or Apache JMeter for load testing concurrent operations.
  </Tab>

  <Tab title="Java">
    #### Framework Context

    Common in Spring Boot applications handling financial transactions, order processing, or approval workflows. Issues often arise in REST controllers and service layers.

    #### Vulnerable Scenario 1: Discount Code Abuse

    ```java theme={null}
    // OrderController.java (VULNERABLE)
    @RestController
    @RequestMapping("/api/orders")
    public class OrderController {
        
        @PostMapping("/apply-discount")
        public ResponseEntity<?> applyDiscount(@RequestBody DiscountRequest request) {
            Order order = orderRepository.findById(request.getOrderId()).orElseThrow();
            DiscountCode discount = discountRepository.findByCode(request.getCode()).orElseThrow();
            
            // DANGEROUS: No check if discount was already applied
            double discountAmount = order.getTotal() * discount.getPercentage();
            order.setTotal(order.getTotal() - discountAmount);
            
            // DANGEROUS: No check for discount validity or usage limits
            orderRepository.save(order);
            
            return ResponseEntity.ok(order);
        }
    }
    ```

    #### Vulnerable Scenario 2: Workflow State Bypass

    ```java theme={null}
    // DocumentService.java (VULNERABLE)
    @Service
    public class DocumentService {
        
        public void approveDocument(Long documentId, Long userId) {
            Document doc = documentRepository.findById(documentId).orElseThrow();
            User user = userRepository.findById(userId).orElseThrow();
            
            // DANGEROUS: Not checking current state or user permissions
            doc.setStatus("APPROVED");
            doc.setApprovedBy(user);
            documentRepository.save(doc);
            
            // User could approve their own document or skip review stages
        }
    }
    ```

    #### Mitigation and Best Practices

    * **State Validation:** Always verify the current state before transitions.
    * **Pessimistic Locking:** Use `@Lock(LockModeType.PESSIMISTIC_WRITE)` for critical operations.
    * **Business Rule Engine:** Consider using a rules engine for complex business logic.
    * **Audit Logging:** Track all state changes and critical operations.

    #### Secure Code Example

    ```java theme={null}
    // OrderController.java (SECURE)
    @RestController
    @RequestMapping("/api/orders")
    public class OrderController {
        
        @PostMapping("/apply-discount")
        @Transactional
        public ResponseEntity<?> applyDiscount(@RequestBody DiscountRequest request,
                                              Authentication auth) {
            // SECURE: Lock order to prevent concurrent modifications
            Order order = orderRepository.findByIdWithLock(request.getOrderId())
                .orElseThrow(() -> new ResourceNotFoundException("Order not found"));
            
            // SECURE: Verify order belongs to user
            if (!order.getUserId().equals(auth.getName())) {
                throw new AccessDeniedException("Order access denied");
            }
            
            // SECURE: Check order state
            if (!order.getStatus().equals("PENDING")) {
                throw new BusinessLogicException("Cannot apply discount to processed order");
            }
            
            DiscountCode discount = discountRepository.findByCode(request.getCode())
                .orElseThrow(() -> new ResourceNotFoundException("Invalid discount code"));
            
            // SECURE: Validate discount constraints
            if (discount.getExpiryDate().isBefore(LocalDate.now())) {
                throw new BusinessLogicException("Discount code expired");
            }
            
            // SECURE: Check if already applied
            if (order.getAppliedDiscounts().contains(discount.getCode())) {
                throw new BusinessLogicException("Discount already applied");
            }
            
            // SECURE: Check usage limits
            long usageCount = orderRepository.countByAppliedDiscountsContaining(discount.getCode());
            if (usageCount >= discount.getMaxUsage()) {
                throw new BusinessLogicException("Discount usage limit reached");
            }
            
            // SECURE: Apply discount with validation
            BigDecimal discountAmount = order.getTotal()
                .multiply(BigDecimal.valueOf(discount.getPercentage()))
                .setScale(2, RoundingMode.HALF_UP);
            
            if (discountAmount.compareTo(discount.getMaxDiscountAmount()) > 0) {
                discountAmount = discount.getMaxDiscountAmount();
            }
            
            order.setTotal(order.getTotal().subtract(discountAmount));
            order.getAppliedDiscounts().add(discount.getCode());
            order.setLastModified(Instant.now());
            
            // Audit log
            auditService.log("DISCOUNT_APPLIED", order.getId(), auth.getName());
            
            return ResponseEntity.ok(orderRepository.save(order));
        }
    }

    // DocumentService.java (SECURE)
    @Service
    @Transactional
    public class DocumentService {
        
        public void approveDocument(Long documentId, Authentication auth) {
            // SECURE: Lock document for update
            Document doc = documentRepository.findByIdForUpdate(documentId)
                .orElseThrow(() -> new ResourceNotFoundException("Document not found"));
            
            User approver = userRepository.findByUsername(auth.getName())
                .orElseThrow();
            
            // SECURE: Validate current state
            if (!doc.getStatus().equals("PENDING_APPROVAL")) {
                throw new BusinessLogicException("Document not in approvable state");
            }
            
            // SECURE: Check permissions
            if (!approver.hasRole("APPROVER")) {
                throw new AccessDeniedException("User lacks approval permission");
            }
            
            // SECURE: Prevent self-approval
            if (doc.getCreatedBy().equals(approver.getId())) {
                throw new BusinessLogicException("Cannot approve own document");
            }
            
            // SECURE: State transition with validation
            doc.setStatus("APPROVED");
            doc.setApprovedBy(approver);
            doc.setApprovalDate(Instant.now());
            
            documentRepository.save(doc);
            
            // Audit trail
            auditService.log("DOCUMENT_APPROVED", doc.getId(), approver.getUsername());
        }
    }
    ```

    #### Testing Strategy

    Create test cases for edge conditions: negative quantities, extreme values, concurrent operations. Test state transitions with invalid starting states. Verify that operations respect business constraints. Use `@DirtiesContext` in Spring tests to ensure clean state between tests.
  </Tab>

  <Tab title=".NET(C#)">
    #### Framework Context

    Common in ASP.NET Core applications handling e-commerce, banking, or multi-step wizards. Issues often arise in controllers and service layers handling transactions.

    #### Vulnerable Scenario 1: Reward Points Manipulation

    ```csharp theme={null}
    // RewardsController.cs (VULNERABLE)
    [ApiController]
    [Route("api/[controller]")]
    public class RewardsController : ControllerBase
    {
        [HttpPost("redeem")]
        public async Task<IActionResult> RedeemPoints([FromBody] RedeemRequest request)
        {
            var user = await _userService.GetUserAsync(User.Identity.Name);
            
            // DANGEROUS: No validation of points value from client
            var pointsToRedeem = request.Points;
            
            // DANGEROUS: Simple subtraction without checks
            user.RewardPoints -= pointsToRedeem;
            var creditAmount = pointsToRedeem * 0.01m; // $0.01 per point
            user.AccountCredit += creditAmount;
            
            await _userService.UpdateUserAsync(user);
            
            return Ok(new { Credit = creditAmount });
        }
    }
    ```

    #### Vulnerable Scenario 2: Concurrent Booking Race Condition

    ```csharp theme={null}
    // BookingService.cs (VULNERABLE)
    public class BookingService
    {
        public async Task<BookingResult> BookSeat(int seatId, string userId)
        {
            var seat = await _context.Seats.FindAsync(seatId);
            
            // DANGEROUS: Check-then-act pattern vulnerable to race conditions
            if (seat.IsAvailable)
            {
                await Task.Delay(100); // Simulating processing
                
                seat.IsAvailable = false;
                seat.BookedBy = userId;
                seat.BookingTime = DateTime.UtcNow;
                
                await _context.SaveChangesAsync();
                return new BookingResult { Success = true };
            }
            
            return new BookingResult { Success = false };
        }
    }
    ```

    #### Mitigation and Best Practices

    * **Optimistic/Pessimistic Concurrency:** Use EF Core's concurrency tokens or row versioning.
    * **Domain-Driven Design:** Encapsulate business rules in domain models.
    * **Saga Pattern:** For distributed transactions across multiple services.
    * **Input Validation:** Always validate and sanitize user inputs server-side.

    #### Secure Code Example

    ```csharp theme={null}
    // RewardsController.cs (SECURE)
    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    public class RewardsController : ControllerBase
    {
        private readonly IDbContextFactory<AppDbContext> _contextFactory;
        private readonly ILogger<RewardsController> _logger;
        
        [HttpPost("redeem")]
        public async Task<IActionResult> RedeemPoints([FromBody] RedeemRequest request)
        {
            // SECURE: Validate input
            if (request.Points <= 0 || request.Points > 10000)
            {
                return BadRequest("Invalid points value");
            }
            
            using var context = _contextFactory.CreateDbContext();
            using var transaction = await context.Database.BeginTransactionAsync();
            
            try
            {
                // SECURE: Use row locking
                var user = await context.Users
                    .FromSqlRaw("SELECT * FROM Users WITH (UPDLOCK) WHERE Id = {0}", User.Identity.Name)
                    .FirstOrDefaultAsync();
                
                if (user == null)
                {
                    return NotFound("User not found");
                }
                
                // SECURE: Validate business rules
                if (user.RewardPoints < request.Points)
                {
                    return BadRequest("Insufficient reward points");
                }
                
                // SECURE: Check daily redemption limit
                var todayRedemptions = await context.RewardRedemptions
                    .Where(r => r.UserId == user.Id && r.Date == DateTime.Today)
                    .SumAsync(r => r.Points);
                
                if (todayRedemptions + request.Points > 5000)
                {
                    return BadRequest("Daily redemption limit exceeded");
                }
                
                // SECURE: Atomic operation with audit trail
                user.RewardPoints -= request.Points;
                var creditAmount = request.Points * 0.01m;
                user.AccountCredit += creditAmount;
                
                var redemption = new RewardRedemption
                {
                    UserId = user.Id,
                    Points = request.Points,
                    CreditAmount = creditAmount,
                    Date = DateTime.Today,
                    Timestamp = DateTime.UtcNow
                };
                
                context.RewardRedemptions.Add(redemption);
                await context.SaveChangesAsync();
                await transaction.CommitAsync();
                
                _logger.LogInformation("User {UserId} redeemed {Points} points for ${Credit}", 
                    user.Id, request.Points, creditAmount);
                
                return Ok(new { Credit = creditAmount, RemainingPoints = user.RewardPoints });
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                _logger.LogError(ex, "Error redeeming points for user {UserId}", User.Identity.Name);
                return StatusCode(500, "An error occurred");
            }
        }
    }

    // BookingService.cs (SECURE)
    public class BookingService
    {
        private readonly AppDbContext _context;
        private readonly ILogger<BookingService> _logger;
        
        public async Task<BookingResult> BookSeat(int seatId, string userId)
        {
            // SECURE: Use transaction with appropriate isolation level
            using var transaction = await _context.Database
                .BeginTransactionAsync(IsolationLevel.Serializable);
            
            try
            {
                // SECURE: Lock the row for update
                var seat = await _context.Seats
                    .FromSqlRaw("SELECT * FROM Seats WITH (UPDLOCK) WHERE Id = {0}", seatId)
                    .FirstOrDefaultAsync();
                
                if (seat == null)
                {
                    return new BookingResult { Success = false, Message = "Seat not found" };
                }
                
                // SECURE: Validate state within transaction
                if (!seat.IsAvailable)
                {
                    return new BookingResult { Success = false, Message = "Seat already booked" };
                }
                
                // SECURE: Additional business rule validation
                if (seat.EventDate < DateTime.UtcNow.AddHours(1))
                {
                    return new BookingResult { Success = false, Message = "Booking closed" };
                }
                
                // SECURE: Check user's concurrent bookings
                var userBookingsCount = await _context.Seats
                    .CountAsync(s => s.BookedBy == userId && s.EventId == seat.EventId);
                
                if (userBookingsCount >= 4)
                {
                    return new BookingResult { Success = false, Message = "Maximum seats per user exceeded" };
                }
                
                // SECURE: Update with concurrency token
                seat.IsAvailable = false;
                seat.BookedBy = userId;
                seat.BookingTime = DateTime.UtcNow;
                seat.BookingReference = Guid.NewGuid().ToString();
                
                // Use optimistic concurrency with RowVersion
                _context.Entry(seat).Property("RowVersion").OriginalValue = seat.RowVersion;
                
                await _context.SaveChangesAsync();
                await transaction.CommitAsync();
                
                _logger.LogInformation("Seat {SeatId} booked by {UserId}", seatId, userId);
                
                return new BookingResult 
                { 
                    Success = true, 
                    BookingReference = seat.BookingReference 
                };
            }
            catch (DbUpdateConcurrencyException)
            {
                await transaction.RollbackAsync();
                return new BookingResult { Success = false, Message = "Seat no longer available" };
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                _logger.LogError(ex, "Booking failed for seat {SeatId}", seatId);
                throw;
            }
        }
    }
    ```

    #### Testing Strategy

    Use xUnit with concurrent test execution to identify race conditions. Create integration tests that simulate multiple users performing the same operation simultaneously. Test boundary conditions and negative scenarios. Use `TransactionScope` in tests to ensure database rollback.
  </Tab>

  <Tab title="PHP">
    #### Framework Context

    Common in Laravel applications handling e-commerce, subscription services, or content management. Issues often arise in controllers handling payments, user upgrades, or content access.

    #### Vulnerable Scenario 1: Subscription Upgrade Bypass

    ```php theme={null}
    // SubscriptionController.php (Laravel - VULNERABLE)
    class SubscriptionController extends Controller
    {
        public function upgrade(Request $request)
        {
            $user = Auth::user();
            $planId = $request->input('plan_id');
            
            // DANGEROUS: No verification of payment
            $user->subscription_plan_id = $planId;
            $user->subscription_expires = now()->addMonth();
            $user->save();
            
            return response()->json(['message' => 'Subscription upgraded']);
        }
    }
    ```

    #### Vulnerable Scenario 2: Voucher Generation Abuse

    ```php theme={null}
    // VoucherController.php (VULNERABLE)
    class VoucherController extends Controller
    {
        public function generateVoucher(Request $request)
        {
            $amount = $request->input('amount');
            $quantity = $request->input('quantity');
            
            // DANGEROUS: No validation or rate limiting
            for ($i = 0; $i < $quantity; $i++) {
                Voucher::create([
                    'code' => Str::random(10),
                    'amount' => $amount,
                    'created_by' => Auth::id(),
                    'expires_at' => now()->addYear()
                ]);
            }
            
            return response()->json(['message' => "$quantity vouchers created"]);
        }
    }
    ```

    #### Mitigation and Best Practices

    * **Payment Verification:** Always verify payment status before granting access.
    * **Database Transactions:** Use Laravel's DB transactions for atomic operations.
    * **Rate Limiting:** Implement throttling for sensitive operations.
    * **Authorization Gates:** Use Laravel's authorization features for access control.

    #### Secure Code Example

    ```php theme={null}
    // SubscriptionController.php (Laravel - SECURE)
    class SubscriptionController extends Controller
    {
        public function upgrade(Request $request)
        {
            $validated = $request->validate([
                'plan_id' => 'required|exists:subscription_plans,id',
                'payment_token' => 'required|string'
            ]);
            
            $user = Auth::user();
            $plan = SubscriptionPlan::findOrFail($validated['plan_id']);
            
            // SECURE: Start database transaction
            return DB::transaction(function () use ($user, $plan, $validated) {
                // SECURE: Lock user record
                $user = User::where('id', $user->id)->lockForUpdate()->first();
                
                // SECURE: Validate current subscription state
                if ($user->subscription_plan_id >= $plan->id) {
                    throw new BusinessLogicException('Cannot downgrade subscription');
                }
                
                // SECURE: Calculate prorated amount
                $amount = $this->calculateProratedAmount($user, $plan);
                
                // SECURE: Process payment first
                try {
                    $payment = PaymentGateway::charge([
                        'token' => $validated['payment_token'],
                        'amount' => $amount,
                        'description' => "Upgrade to {$plan->name}"
                    ]);
                } catch (PaymentException $e) {
                    Log::error('Payment failed', ['user' => $user->id, 'error' => $e->getMessage()]);
                    throw new BusinessLogicException('Payment processing failed');
                }
                
                // SECURE: Only upgrade after successful payment
                $previousPlan = $user->subscription_plan_id;
                $user->subscription_plan_id = $plan->id;
                $user->subscription_expires = $user->subscription_expires 
                    ? $user->subscription_expires->addMonth() 
                    : now()->addMonth();
                $user->save();
                
                // SECURE: Create audit record
                SubscriptionHistory::create([
                    'user_id' => $user->id,
                    'from_plan_id' => $previousPlan,
                    'to_plan_id' => $plan->id,
                    'payment_id' => $payment->id,
                    'amount' => $amount,
                    'upgraded_at' => now()
                ]);
                
                return response()->json([
                    'message' => 'Subscription upgraded successfully',
                    'expires_at' => $user->subscription_expires
                ]);
            });
        }
        
        private function calculateProratedAmount($user, $newPlan)
        {
            // SECURE: Complex business logic for proration
            if (!$user->subscription_expires || $user->subscription_expires->isPast()) {
                return $newPlan->price;
            }
            
            $daysRemaining = now()->diffInDays($user->subscription_expires);
            $currentPlan = SubscriptionPlan::find($user->subscription_plan_id);
            $dailyCredit = $currentPlan ? ($currentPlan->price / 30) * $daysRemaining : 0;
            
            return max(0, $newPlan->price - $dailyCredit);
        }
    }

    // VoucherController.php (SECURE)
    class VoucherController extends Controller
    {
        public function __construct()
        {
            // SECURE: Rate limiting
            $this->middleware('throttle:5,1')->only('generateVoucher');
        }
        
        public function generateVoucher(Request $request)
        {
            // SECURE: Validate input
            $validated = $request->validate([
                'amount' => 'required|numeric|min:1|max:100',
                'quantity' => 'required|integer|min:1|max:10',
                'reason' => 'required|string|max:255'
            ]);
            
            // SECURE: Authorization check
            if (!Auth::user()->can('create-vouchers')) {
                abort(403, 'Unauthorized to create vouchers');
            }
            
            // SECURE: Check daily limits
            $todayCount = Voucher::where('created_by', Auth::id())
                ->whereDate('created_at', today())
                ->count();
            
            if ($todayCount + $validated['quantity'] > 50) {
                throw new BusinessLogicException('Daily voucher limit exceeded');
            }
            
            // SECURE: Use transaction for atomic operation
            $vouchers = DB::transaction(function () use ($validated) {
                $vouchers = [];
                
                for ($i = 0; $i < $validated['quantity']; $i++) {
                    // SECURE: Generate cryptographically secure codes
                    $code = strtoupper(Str::random(8));
                    
                    // SECURE: Ensure uniqueness
                    while (Voucher::where('code', $code)->exists()) {
                        $code = strtoupper(Str::random(8));
                    }
                    
                    $voucher = Voucher::create([
                        'code' => $code,
                        'amount' => $validated['amount'],
                        'created_by' => Auth::id(),
                        'reason' => $validated['reason'],
                        'expires_at' => now()->addDays(30), // SECURE: Reasonable expiry
                        'max_uses' => 1 // SECURE: Single use
                    ]);
                    
                    $vouchers[] = $voucher;
                    
                    // SECURE: Audit log
                    activity()
                        ->causedBy(Auth::user())
                        ->performedOn($voucher)
                        ->withProperties(['amount' => $validated['amount'], 'reason' => $validated['reason']])
                        ->log('Voucher generated');
                }
                
                return $vouchers;
            });
            
            return response()->json([
                'message' => count($vouchers) . ' vouchers created',
                'vouchers' => $vouchers->pluck('code')
            ]);
        }
    }
    ```

    #### Testing Strategy

    Use PHPUnit with database transactions for testing. Create tests for concurrent operations using multiple database connections. Test with invalid state transitions and boundary values. Use Laravel Dusk for end-to-end testing of multi-step workflows.
  </Tab>

  <Tab title="Node.js">
    #### Framework Context

    Common in Express applications handling real-time operations, gaming mechanics, or API rate limiting. Issues often arise in middleware and route handlers dealing with session management or resource allocation.

    #### Vulnerable Scenario 1: API Rate Limit Bypass

    ```javascript theme={null}
    // rateLimiter.js (VULNERABLE)
    const rateLimitMap = new Map();

    const rateLimiter = (req, res, next) => {
        const userId = req.user?.id;
        
        // DANGEROUS: Only checking authenticated users
        if (!userId) {
            return next(); // Unauthenticated users bypass rate limiting!
        }
        
        const userLimits = rateLimitMap.get(userId) || { count: 0, resetTime: Date.now() + 60000 };
        
        // DANGEROUS: Client can manipulate headers to reset counter
        if (req.headers['x-reset-limit'] === 'true') {
            rateLimitMap.delete(userId);
            return next();
        }
        
        if (userLimits.count >= 100) {
            return res.status(429).json({ error: 'Rate limit exceeded' });
        }
        
        userLimits.count++;
        rateLimitMap.set(userId, userLimits);
        next();
    };
    ```

    #### Vulnerable Scenario 2: Game Score Manipulation

    ```javascript theme={null}
    // gameController.js (VULNERABLE)
    router.post('/submit-score', async (req, res) => {
        const { gameId, score, timeSpent } = req.body;
        const userId = req.user.id;
        
        // DANGEROUS: Trusting client-provided score
        const gameSession = await GameSession.findOne({ userId, gameId });
        
        // DANGEROUS: No validation of score legitimacy
        gameSession.score = score;
        gameSession.timeSpent = timeSpent;
        gameSession.completed = true;
        
        await gameSession.save();
        
        // Award prizes based on score
        if (score > 10000) {
            await User.findByIdAndUpdate(userId, { $inc: { coins: 1000 } });
        }
        
        res.json({ success: true });
    });
    ```

    #### Mitigation and Best Practices

    * **Server-Side State:** Maintain game state and calculations server-side.
    * **Distributed Locking:** Use Redis for distributed rate limiting.
    * **Cryptographic Signatures:** Sign critical values to prevent tampering.
    * **Session Validation:** Verify session integrity and timing constraints.

    #### Secure Code Example

    ```javascript theme={null}
    // rateLimiter.js (SECURE)
    const Redis = require('ioredis');
    const redis = new Redis();
    const crypto = require('crypto');

    const rateLimiter = (options = {}) => {
        const {
            windowMs = 60000,
            max = 100,
            keyGenerator = (req) => req.ip // Default to IP-based
        } = options;
        
        return async (req, res, next) => {
            // SECURE: Generate rate limit key
            const key = `rate_limit:${keyGenerator(req)}`;
            
            try {
                // SECURE: Use Redis for distributed rate limiting
                const pipeline = redis.pipeline();
                const now = Date.now();
                const window = now - windowMs;
                
                // Remove old entries
                pipeline.zremrangebyscore(key, 0, window);
                // Add current request
                pipeline.zadd(key, now, `${now}-${crypto.randomBytes(4).toString('hex')}`);
                // Count requests in window
                pipeline.zcard(key);
                // Set expiry
                pipeline.expire(key, Math.ceil(windowMs / 1000));
                
                const results = await pipeline.exec();
                const requestCount = results[2][1];
                
                // SECURE: Set rate limit headers
                res.setHeader('X-RateLimit-Limit', max);
                res.setHeader('X-RateLimit-Remaining', Math.max(0, max - requestCount));
                res.setHeader('X-RateLimit-Reset', new Date(now + windowMs).toISOString());
                
                if (requestCount > max) {
                    // SECURE: Log potential abuse
                    logger.warn('Rate limit exceeded', {
                        key,
                        count: requestCount,
                        ip: req.ip,
                        user: req.user?.id
                    });
                    
                    return res.status(429).json({
                        error: 'Too many requests',
                        retryAfter: Math.ceil(windowMs / 1000)
                    });
                }
                
                next();
            } catch (error) {
                logger.error('Rate limiter error', error);
                // Fail open but log the issue
                next();
            }
        };
    };

    // gameController.js (SECURE)
    const crypto = require('crypto');
    const gameSecret = process.env.GAME_SECRET;

    router.post('/start-game', async (req, res) => {
        const { gameId } = req.body;
        const userId = req.user.id;
        
        // SECURE: Create server-side game session
        const session = await GameSession.create({
            userId,
            gameId,
            startTime: Date.now(),
            sessionToken: crypto.randomBytes(32).toString('hex'),
            maxScore: 0,
            moves: []
        });
        
        // SECURE: Send session token (not the actual game state)
        res.json({
            sessionId: session._id,
            sessionToken: session.sessionToken
        });
    });

    router.post('/game-move', async (req, res) => {
        const { sessionId, sessionToken, move } = req.body;
        
        // SECURE: Validate session
        const session = await GameSession.findById(sessionId);
        if (!session || session.sessionToken !== sessionToken) {
            return res.status(401).json({ error: 'Invalid session' });
        }
        
        // SECURE: Check session timeout
        if (Date.now() - session.startTime > 3600000) { // 1 hour limit
            session.completed = true;
            session.timedOut = true;
            await session.save();
            return res.status(400).json({ error: 'Session expired' });
        }
        
        // SECURE: Validate move server-side
        const moveValidation = validateMove(session, move);
        if (!moveValidation.valid) {
            // Log potential cheating attempt
            logger.warn('Invalid move attempted', {
                userId: session.userId,
                sessionId,
                move
            });
            return res.status(400).json({ error: 'Invalid move' });
        }
        
        // SECURE: Calculate score server-side
        const scoreIncrement = calculateScore(move, session.moves.length);
        session.moves.push({
            move,
            timestamp: Date.now(),
            score: scoreIncrement
        });
        session.maxScore += scoreIncrement;
        
        // SECURE: Check for impossible scores
        const theoreticalMax = calculateTheoreticalMax(session.moves.length, Date.now() - session.startTime);
        if (session.maxScore > theoreticalMax) {
            session.flaggedForReview = true;
            logger.alert('Suspicious game activity', {
                userId: session.userId,
                sessionId,
                score: session.maxScore,
                theoretical: theoreticalMax
            });
        }
        
        await session.save();
        
        res.json({
            currentScore: session.maxScore,
            moveAccepted: true
        });
    });

    router.post('/end-game', async (req, res) => {
        const { sessionId, sessionToken } = req.body;
        
        // SECURE: Lock session for completion
        const session = await GameSession.findOneAndUpdate(
            {
                _id: sessionId,
                sessionToken,
                completed: false
            },
            {
                $set: {
                    completed: true,
                    endTime: Date.now()
                }
            },
            {
                new: true,
                runValidators: true
            }
        );
        
        if (!session) {
            return res.status(400).json({ error: 'Invalid or already completed session' });
        }
        
        // SECURE: Validate final score
        const calculatedScore = session.moves.reduce((sum, m) => sum + m.score, 0);
        if (calculatedScore !== session.maxScore) {
            logger.alert('Score mismatch detected', {
                sessionId,
                calculated: calculatedScore,
                stored: session.maxScore
            });
            session.flaggedForReview = true;
            await session.save();
            return res.status(400).json({ error: 'Score validation failed' });
        }
        
        // SECURE: Award prizes only for validated scores
        if (!session.flaggedForReview && session.maxScore > 10000) {
            await User.findByIdAndUpdate(
                session.userId,
                {
                    $inc: { coins: Math.min(1000, Math.floor(session.maxScore / 100)) },
                    $push: {
                        achievements: {
                            type: 'HIGH_SCORE',
                            score: session.maxScore,
                            date: new Date()
                        }
                    }
                },
                { runValidators: true }
            );
        }
        
        res.json({
            finalScore: session.maxScore,
            coinsEarned: session.flaggedForReview ? 0 : Math.min(1000, Math.floor(session.maxScore / 100))
        });
    });
    ```

    #### Testing Strategy

    Use Mocha/Chai with sinon for mocking time-based operations. Create stress tests with multiple concurrent requests using supertest. Test with manipulated client data to ensure server-side validation catches cheating attempts. Use Jest for testing race conditions with proper async handling.
  </Tab>

  <Tab title="Ruby">
    #### Framework Context

    Common in Rails applications handling inventory management, auction systems, or reservation platforms. Issues often arise in controllers and models dealing with competitive resource allocation.

    #### Vulnerable Scenario 1: Inventory Double-Spending

    ```ruby theme={null}
    # products_controller.rb (VULNERABLE)
    class ProductsController < ApplicationController
      def purchase
        product = Product.find(params[:id])
        quantity = params[:quantity].to_i
        
        # DANGEROUS: Race condition between check and update
        if product.stock >= quantity
          product.stock -= quantity
          product.save
          
          Order.create!(
            user: current_user,
            product: product,
            quantity: quantity,
            total: product.price * quantity
          )
          
          render json: { success: true }
        else
          render json: { error: 'Insufficient stock' }, status: 400
        end
      end
    end
    ```

    #### Vulnerable Scenario 2: Auction Bid Manipulation

    ```ruby theme={null}
    # auction.rb (VULNERABLE)
    class Auction < ApplicationRecord
      def place_bid(user, amount)
        # DANGEROUS: No validation of bid increments
        if amount > self.current_bid
          self.current_bid = amount
          self.highest_bidder = user
          self.save
          
          # DANGEROUS: Time extension can be abused
          if self.ends_at - Time.current < 1.minute
            self.ends_at += 5.minutes
            self.save
          end
          
          true
        else
          false
        end
      end
    end
    ```

    #### Mitigation and Best Practices

    * **Pessimistic Locking:** Use `with_lock` for critical sections.
    * **Optimistic Locking:** Add `lock_version` to tables for concurrent updates.
    * **State Machines:** Use gems like AASM for controlled state transitions.
    * **Database Constraints:** Add check constraints for business rules.

    #### Secure Code Example

    ```ruby theme={null}
    # products_controller.rb (SECURE)
    class ProductsController < ApplicationController
      def purchase
        quantity = params[:quantity].to_i
        
        # SECURE: Input validation
        if quantity <= 0 || quantity > 10
          return render json: { error: 'Invalid quantity' }, status: 400
        end
        
        # SECURE: Use transaction with locking
        order = nil
        ActiveRecord::Base.transaction do
          product = Product.lock.find(params[:id])
          
          # SECURE: Verify product is purchasable
          unless product.available_for_purchase?
            raise BusinessLogicError, 'Product not available'
          end
          
          # SECURE: Check stock within lock
          if product.stock < quantity
            raise BusinessLogicError, 'Insufficient stock'
          end
          
          # SECURE: Check purchase limits
          recent_orders_count = current_user.orders
            .where(product: product)
            .where('created_at > ?', 24.hours.ago)
            .sum(:quantity)
          
          if recent_orders_count + quantity > product.max_per_customer
            raise BusinessLogicError, 'Purchase limit exceeded'
          end
          
          # SECURE: Update stock
          product.stock -= quantity
          product.save!
          
          # SECURE: Create order with validation
          order = Order.create!(
            user: current_user,
            product: product,
            quantity: quantity,
            unit_price: product.current_price, # Store price at time of purchase
            total: product.current_price * quantity,
            status: 'pending_payment'
          )
          
          # SECURE: Reserve stock for limited time
          StockReservation.create!(
            order: order,
            product: product,
            quantity: quantity,
            expires_at: 15.minutes.from_now
          )
        end
        
        # Trigger payment processing job
        ProcessPaymentJob.perform_later(order)
        
        render json: {
          success: true,
          order_id: order.id,
          reservation_expires_at: order.stock_reservation.expires_at
        }
      rescue BusinessLogicError => e
        render json: { error: e.message }, status: 400
      rescue ActiveRecord::RecordInvalid => e
        render json: { error: 'Invalid order data' }, status: 400
      end
    end

    # auction.rb (SECURE)
    class Auction < ApplicationRecord
      include AASM
      
      has_many :bids
      belongs_to :highest_bidder, class_name: 'User', optional: true
      
      # SECURE: Use optimistic locking
      # Migration: add_column :auctions, :lock_version, :integer, default: 0, null: false
      
      # SECURE: State machine for auction lifecycle
      aasm column: 'status' do
        state :draft, initial: true
        state :active
        state :ending
        state :completed
        state :cancelled
        
        event :activate do
          transitions from: :draft, to: :active
          after do
            self.starts_at = Time.current
            self.ends_at = self.starts_at + self.duration.hours
          end
        end
        
        event :complete do
          transitions from: [:active, :ending], to: :completed
        end
      end
      
      def place_bid(user, amount)
        # SECURE: Use transaction with retry on optimistic lock failure
        max_retries = 3
        retry_count = 0
        
        begin
          ActiveRecord::Base.transaction do
            # SECURE: Lock the auction record
            auction = Auction.lock.find(self.id)
            
            # SECURE: Validate auction state
            unless auction.active? || auction.ending?
              raise BusinessLogicError, 'Auction is not accepting bids'
            end
            
            # SECURE: Validate bid amount
            minimum_bid = auction.current_bid.to_f + auction.minimum_increment
            if amount < minimum_bid
              raise BusinessLogicError, "Bid must be at least #{minimum_bid}"
            end
            
            # SECURE: Validate user can bid
            if auction.seller_id == user.id
              raise BusinessLogicError, 'Cannot bid on own auction'
            end
            
            if auction.highest_bidder_id == user.id
              raise BusinessLogicError, 'You are already the highest bidder'
            end
            
            # SECURE: Check user's bid limit
            user_total_bids = user.bids
              .joins(:auction)
              .where(auctions: { status: [:active, :ending] })
              .sum(:amount)
            
            if user_total_bids + amount > user.bid_limit
              raise BusinessLogicError, 'Bid limit exceeded'
            end
            
            # SECURE: Create bid record
            bid = auction.bids.create!(
              user: user,
              amount: amount,
              ip_address: user.current_sign_in_ip,
              placed_at: Time.current
            )
            
            # SECURE: Update auction
            auction.current_bid = amount
            auction.highest_bidder = user
            auction.bid_count += 1
            
            # SECURE: Controlled time extension with limits
            time_remaining = auction.ends_at - Time.current
            if time_remaining < 2.minutes && auction.extensions_count < 3
              auction.ends_at += 2.minutes
              auction.extensions_count += 1
              auction.ending! if time_remaining < 5.minutes && auction.active?
            end
            
            auction.save!
            
            # Notify previous highest bidder
            if auction.previous_changes['highest_bidder_id']
              OutbidNotificationJob.perform_later(
                auction.previous_changes['highest_bidder_id'][0],
                auction
              )
            end
            
            bid
          end
        rescue ActiveRecord::StaleObjectError
          # SECURE: Handle optimistic locking conflict
          retry_count += 1
          if retry_count < max_retries
            sleep(0.1 * retry_count) # Exponential backoff
            retry
          else
            raise BusinessLogicError, 'Unable to place bid due to high activity'
          end
        end
      end
      
      # SECURE: Scheduled job to finalize auctions
      def self.finalize_ended_auctions
        Auction.where(status: [:active, :ending])
               .where('ends_at < ?', Time.current)
               .find_each do |auction|
          auction.with_lock do
            next unless auction.active? || auction.ending?
            
            auction.complete!
            
            if auction.highest_bidder.present?
              # Create purchase obligation
              Purchase.create!(
                buyer: auction.highest_bidder,
                auction: auction,
                amount: auction.current_bid,
                due_date: 3.days.from_now
              )
              
              # Notify winner
              AuctionWonNotificationJob.perform_later(auction)
            end
          end
        end
      end
    end
    ```

    #### Testing Strategy

    Use RSpec with `transactional` fixtures disabled for testing locking behavior. Create concurrent tests using threads or the `parallel_tests` gem. Test state machines with all possible transitions. Use FactoryBot to create complex test scenarios with various states.
  </Tab>
</Tabs>
