Skip to content

Security: Unauthenticated issue manipulation + manage_jobs gate always returns true #95

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

A security audit identified 12 authorization vulnerabilities (2 Critical, 6 High, 4 Medium) in free-pmo.

Critical Findings

1. Unauthenticated Issue Option Update (CRITICAL)

routes/web/projects.php:110-120 — Issue option update and comment routes are defined outside both Route::group(['middleware' => ['auth']]) blocks:

Route::patch('issues/{issue}/options', 'Issues\OptionController@update');
Route::post('issues/{issue}/comments', 'Issues\CommentController@store');
Route::patch('issues/{issue}/comments/{comment}', 'Issues\CommentController@update');
Route::delete('issues/{issue}/comments/{comment}', 'Issues\CommentController@destroy');

The OptionController@update has NO $this->authorize() call — an unauthenticated user can change any issue's priority, status, and assigned person via PATCH /issues/{id}/options.

2. manage_jobs Gate Always Returns True (CRITICAL)

AuthServiceProvider.php:44-46:

Gate::define('manage_jobs', function ($user, $project) {
    return true;
});

This gate is used by Jobs\CreateRequest, UpdateRequest, and DeleteRequest. Any authenticated worker can create, update (including prices), and delete jobs on ANY project, regardless of project membership.

HIGH Findings — Missing Authorization in Controllers

The ProjectsController has thorough $this->authorize() calls, but sibling controllers in the same namespace have ZERO authorization:

  • IssueController — full CRUD on any project's issues without auth
  • Projects/JobsController — list, export (including pricing data), and copy jobs between any projects
  • ActivityController — view any project's activity history
  • FilesController — upload/download/edit/delete files for any project
  • TasksController setDone/setAsJob — mark any task complete or convert to job
  • API ProjectsController — IDOR: retrieve any project's full details by ID

MEDIUM Findings

  • JobsController@edit uses view policy instead of update
  • JobsController@delete confirmation page — no auth
  • LogFileController — path traversal in $fileName parameter (admin-only)
  • BackupsController — path traversal in download/delete/restore (admin-only)

Recommended Fixes

  1. Move issue option/comment routes inside the auth middleware group
  2. Implement proper manage_jobs gate with project membership check:
    Gate::define('manage_jobs', function ($user, $project) {
        return $user->hasRole('admin') || $project->owner_id == $user->id;
    });
  3. Add $this->authorize() calls to all Project-related controllers
  4. Sanitize $fileName in LogFileController and BackupsController

Disclosure

Filed in good faith. No exploit code provided.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions