Back to Research

CVE-2025-62720 - LinkAce - Data Exfiltration via Export Functions Allowing Access to All Users' Private Links

November 4, 2025

Author and Researcher

Ravindu Wickramasinghe

Ravindu Wickramasinghe

@rvz

Summary

The export functionality in the ExportController class allows any authenticated user to export the entire database of links from all users in the system, including private links that should only be accessible to their owners. The HTML and CSV export functions retrieve all links without applying any ownership or visibility filtering, effectively bypassing all access controls implemented elsewhere in the application.

Details

The export functionality in the ExportController class allows any authenticated user to export the entire database of links from all users in the system, including private links that should only be accessible to their owners. The HTML and CSV export functions retrieve all links without applying any ownership or visibility filtering, effectively bypassing all access controls implemented elsewhere in the application.

Vulnerable Endpoints:

  1. POST /export/html - Exports all links from all users as HTML file
  2. POST /export/csv - Exports all links from all users as CSV file

The vulnerable code is located in app/Http/Controllers/App/ExportController.php:

app/Http/Controllers/App/ExportController.php
// Line 33-37 - HTML Export
public function doHtmlExport(): StreamedResponse
{
    $links = Link::oldest('title')->with('tags')->get();
    // Retrieves ALL links from ALL users
    
    $fileContent = view()->make('app.export.html-export', ['links' => $links])->render();
    $fileName = config('app.name') . '_export.html';
    
    return response()->streamDownload(function () use ($fileContent) {
        echo $fileContent;
    }, $fileName);
}

// Line 52-60 - CSV Export
public function doCsvExport()
{
    $links = Link::oldest('title')->get();
    // Retrieves ALL links from ALL users
    
    $rows = $links->map(function (Link $link) {
        $link->tags = $link->tags()->get()->pluck('name')->join(',');
        $link->lists = $link->lists()->get()->pluck('name')->join(',');
        return $link;
    })->toArray();
    // ... CSV generation code
}

Both methods are accessible via POST requests to /export/html and /export/csv respectively. While these routes are protected by authentication middleware, they lack authorization checks to ensure users can only export their own data. This vulnerability allows an attacker with any valid user account to download a complete export of all bookmarks stored in the system, potentially exposing sensitive URLs, credentials embedded in URLs, private notes, and organizational information.

Proof of Concept

Steps to Reproduce

  1. Set up LinkAce with multiple user accounts, ensuring each user has created private links.
  2. Log in as any authenticated user account.
  3. Navigate to the export page at /export.
  4. Submit a POST request to /export/html or use the export form.
  5. Download and open the exported HTML file.
  6. Verify that the file contains links from all users in the system, not just the authenticated user's links.
  7. Repeat the process with CSV export by submitting a POST request to /export/csv
  8. Verify that the CSV file contains complete link data from all users.

Proof of Concept (Media)

PoC - LinkAce Data Exfiltration via Export Functions

Recommendations

Implement proper authorization by filtering exported links to only include those belonging to the authenticated user. Modify both export methods to apply the byUser() scope before retrieving links. This scope is already implemented in the application's ScopesForUser trait and is used correctly in other parts of the codebase.