Broken Object Property Level Authorization

Broken Object Property Level Authorization in Laravel [CVE-2026-33882]

[Fixed 2026-03] Updated CVE-2026-33882

Overview

Real-world impact: This class of vulnerability is Broken Object Property Level Authorization. In CVE-2026-33882, Statamic (a Laravel-based CMS) exposed data through the markdown preview endpoint by augmenting responses with data from arbitrary fieldtypes. An authenticated control panel user could retrieve sensitive user data such as email addresses, encrypted passkeys, and encrypted TOTP codes. This maps to CWE-200 (Information Exposure) and CWE-20 (Improper Handling of Input) and demonstrates how object-level property exposure can leak data. Attack scenario: The markdown preview path did not enforce per-property authorization, allowing the response payload to include fields the caller should not see. When the payload dynamically included user fieldtypes, an authorized user could infer or extract details from other users, not just the published object. The root cause is lack of proper object-level authorization on properties returned in the response. Laravel remediation approach: Implement policies or gates to enforce object-level access and limit serialized data. Create a policy like view(Entry $entry) and call $this->authorize('view', $entry) in controllers. Replace raw model dumps with a Resource that whitelists safe fields, and hide sensitive attributes via $hidden or Resource definitions. Add tests to ensure unauthorized access cannot leak fields. Upgrade paths should be applied where fixes exist. Mitigation and upgrade: Upgrade to Statamic 5.73.16 or 6.7.2. Audit endpoints that emit dynamic fieldtypes, and ensure previews cannot leak sensitive fields. Explicitly whitelist exposed fields in API responses and verify permissions via tests.

Affected Versions

Prior to 5.73.16 and 6.7.2

Code Fix Example

Laravel API Security Remediation
VULNERABLE:
<?php
class PreviewController extends Controller {
    public function markdownPreviewVuln(Request $request, $entryId) {
        $entry = Entry::findOrFail($entryId);
        // Exposes full model including sensitive fields
        return response()->json($entry);
    }
}

FIX:
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Entry;
use App\Http\Resources\EntryPreviewResource;

class PreviewController extends Controller {
    public function markdownPreviewFixed(Request $request, $entryId) {
        $entry = Entry::findOrFail($entryId);
        // Enforce object-level authorization
        $this->authorize('view', $entry);
        // Use a resource to whitelist output
        return new EntryPreviewResource($entry);
    }
}

// Resource: App\Http\Resources\EntryPreviewResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\JsonResource;

class EntryPreviewResource extends JsonResource {
    public function toArray($request) {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'fields' => $this->fields,
        ];
    }
}

CVE References

Choose which optional cookies to allow. You can change this any time.