Skip to content

Security: Unauthenticated API access + IDOR in payroll and leave endpoints #1065

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

Multiple authorization vulnerabilities in the REST API layer. The root cause is missing DEFAULT_PERMISSION_CLASSES in DRF configuration (horilla/rest_conf.py), meaning any API view without explicit permission_classes defaults to AllowAny.

Finding 1: TaxBracketView Unauthenticated CRUD (CRITICAL)

File: horilla_api/api_views/payroll/views.py:348-379

TaxBracketView has NO permission_classes. All 10 sibling views in the same file (PayslipView, ContractView, AllowanceView, DeductionView, LoanAccountView, ReimbursementView, etc.) have permission_classes = [IsAuthenticated].

Anonymous users can read, create, modify, and delete payroll tax brackets.

Finding 2: HolidayGetUpdateDeleteAPIView Missing permission_classes (CRITICAL)

File: horilla_api/api_views/leave/views.py:669-704

Missing permission_classes while HolidayGetCreateAPIView (line 645) has permission_classes = [IsAuthenticated]. Methods have @permission_required decorators, but DRF authentication is bypassed.

Finding 3: CheckUserLevel Missing permission_classes (HIGH)

File: horilla_api/api_views/base/views.py:1301-1307

Missing permission_classes on utility endpoint that probes permissions.

Finding 4: ContractView GET by ID IDOR (HIGH)

File: horilla_api/api_views/payroll/views.py:119-123

Single contract retrieval Contract.objects.filter(id=id) has NO ownership check. The list endpoint (line 124-127) correctly filters by employee_id=request.user.employee_get for non-privileged users.

Any employee can read any other employee's contract (salary, terms) by enumerating IDs.

Root Cause

horilla/rest_conf.py defines REST_FRAMEWORK_SETTINGS with authentication classes but NO DEFAULT_PERMISSION_CLASSES. This means any view that forgets permission_classes silently defaults to AllowAny.

Suggested Fixes

  1. Add "DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"] to REST_FRAMEWORK_SETTINGS
  2. Add ownership check to ContractView single-object GET
  3. Audit all API views for missing permission_classes

CWE

  • CWE-306 (Missing Authentication for Critical Function)
  • CWE-639 (Authorization Bypass Through User-Controlled Key)

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