Summary
OpenProject contained an authorization flaw that let regular project users manipulate FileLinks through the work package PATCH API without having the specific manage_file_links permission.
Under these conditions, an attacker could detach, delete, or re-parent FileLinks across projects, exposing file metadata and violating access control boundaries.
OpenProject contained an authorization flaw that let regular project users manipulate FileLinks through the work package PATCH API without having the specific manage_file_links permission.
Under these conditions, an attacker could detach, delete, or re-parent FileLinks across projects, exposing file metadata and violating access control boundaries.
Affected context
This vulnerability arises in OpenProject deployments where authenticated users can call PATCH /api/v3/work_packages/{id} and have the edit_work_packages permission but lack manage_file_links.
In that situation, the API's handling of _links.fileLinks treats the raw FileLink IDs as implicitly trusted, allowing operations on Storages::FileLink records that should be restricted.
The issue primarily affects environments that rely on role-based permissions to separate file link management from general work package editing.
This vulnerability arises in OpenProject deployments where authenticated users can call PATCH /api/v3/work_packages/{id} and have the edit_work_packages permission but lack manage_file_links.
In that situation, the API's handling of _links.fileLinks treats the raw FileLink IDs as implicitly trusted, allowing operations on Storages::FileLink records that should be restricted.
The issue primarily affects environments that rely on role-based permissions to separate file link management from general work package editing.
Exploit preconditions
- Attack surface: OpenProject HTTP API endpoint
PATCH /api/v3/work_packages/{id}. - Required access: Valid authenticated account with
edit_work_packagespermission in at least one project; no need formanage_file_links. - Trigger point: Supplying crafted
_links.fileLinksdata referencingStorages::FileLinkrecords by raw ID when updating a work package. - Why exploitation is possible: The endpoint authorizes based on edit rights to the work package but does not enforce granular authorization on FileLink operations, allowing ID-based access and manipulation of links owned by other projects.
- Attack surface: OpenProject HTTP API endpoint
PATCH /api/v3/work_packages/{id}. - Required access: Valid authenticated account with
edit_work_packagespermission in at least one project; no need formanage_file_links. - Trigger point: Supplying crafted
_links.fileLinksdata referencingStorages::FileLinkrecords by raw ID when updating a work package. - Why exploitation is possible: The endpoint authorizes based on edit rights to the work package but does not enforce granular authorization on FileLink operations, allowing ID-based access and manipulation of links owned by other projects.
Why this happens
The underlying bug is an authorization gap where object-level permissions on FileLinks are not consistently enforced when they are manipulated through the work package update API.
The implementation treats the presence of edit_work_packages as sufficient to operate on associated FileLinks and trusts client-supplied _links.fileLinks identifiers without verifying that the caller has manage_file_links or equivalent rights over the targeted Storages::FileLink records.
This maps to CWE-862: Missing Authorization, where accesses to sensitive operations are granted based on incomplete or incorrect permission checks, enabling cross-project resource manipulation through ID-based references.
The underlying bug is an authorization gap where object-level permissions on FileLinks are not consistently enforced when they are manipulated through the work package update API.
The implementation treats the presence of edit_work_packages as sufficient to operate on associated FileLinks and trusts client-supplied _links.fileLinks identifiers without verifying that the caller has manage_file_links or equivalent rights over the targeted Storages::FileLink records.
This maps to CWE-862: Missing Authorization, where accesses to sensitive operations are granted based on incomplete or incorrect permission checks, enabling cross-project resource manipulation through ID-based references.
Potential impact
- Attackers can detach existing FileLinks from legitimate work packages, disrupting expected project documentation.
- Attackers may hard-delete FileLinks that they do not own, causing data loss or forcing restoration from backups.
- FileLinks from other projects can be re-parented to attacker-controlled work packages, exposing origin filename, origin ID, and MIME type metadata.
- Project boundaries and role-based separation of duties can be undermined, potentially leaking information about documents linked in other projects.
- Audit trails tied to file linkage relationships can be corrupted, complicating incident response and compliance reporting.
- Attackers can detach existing FileLinks from legitimate work packages, disrupting expected project documentation.
- Attackers may hard-delete FileLinks that they do not own, causing data loss or forcing restoration from backups.
- FileLinks from other projects can be re-parented to attacker-controlled work packages, exposing origin filename, origin ID, and MIME type metadata.
- Project boundaries and role-based separation of duties can be undermined, potentially leaking information about documents linked in other projects.
- Audit trails tied to file linkage relationships can be corrupted, complicating incident response and compliance reporting.
General mitigation guidance
Effective mitigation focuses on ensuring that all operations on subordinate resources, such as FileLinks, undergo their own dedicated authorization checks rather than relying solely on permissions for parent objects.
Common defensive patterns include:
- Applying explicit object-level permission validation for every FileLink referenced in
_links.fileLinks, checking both project ownership and required capabilities (e.g., manage_file_links). - Designing APIs so that clients cannot directly supply raw IDs for sensitive child objects; instead, use server-side resolution and constraints tied to the current context.
- Enforcing strict separation between "content editing" and "link or storage management" permissions and reflecting that separation in the access control layer.
- Implementing deny-by-default logic for cross-project references, requiring deliberate, auditable exceptions when resources may span projects.
- Logging and monitoring all file link modifications to highlight anomalous cross-project manipulations.
Effective mitigation focuses on ensuring that all operations on subordinate resources, such as FileLinks, undergo their own dedicated authorization checks rather than relying solely on permissions for parent objects.
Common defensive patterns include:
- Applying explicit object-level permission validation for every FileLink referenced in
_links.fileLinks, checking both project ownership and required capabilities (e.g., manage_file_links). - Designing APIs so that clients cannot directly supply raw IDs for sensitive child objects; instead, use server-side resolution and constraints tied to the current context.
- Enforcing strict separation between "content editing" and "link or storage management" permissions and reflecting that separation in the access control layer.
- Implementing deny-by-default logic for cross-project references, requiring deliberate, auditable exceptions when resources may span projects.
- Logging and monitoring all file link modifications to highlight anomalous cross-project manipulations.
How teams detect issues like this
Detection generally relies on examining both application behavior and source code for authorization gaps around secondary resources:
- Code-level review: Look for endpoints that modify child objects (such as FileLinks) based solely on permissions for the parent entity (work packages, projects) without additional checks on the child object. Pay particular attention to fields like
_links.*that accept raw IDs. - Static analysis: Configure rules to flag patterns where IDs of sensitive records are taken directly from user input and used for update or delete operations without intervening authorization checks.
- Policy enforcement: Adopt secure coding guidelines that require object-level permission verification for all cross-entity relationships and ensure reviewers confirm this for any public API endpoint.
- Runtime monitoring: Analyze logs for unusual cross-project FileLink operations (detach, delete, or re-parent actions), especially when performed by accounts lacking the appropriate management permissions. Automated tooling can complement manual review by highlighting such deviations.
Detection generally relies on examining both application behavior and source code for authorization gaps around secondary resources:
- Code-level review: Look for endpoints that modify child objects (such as FileLinks) based solely on permissions for the parent entity (work packages, projects) without additional checks on the child object. Pay particular attention to fields like
_links.*that accept raw IDs. - Static analysis: Configure rules to flag patterns where IDs of sensitive records are taken directly from user input and used for update or delete operations without intervening authorization checks.
- Policy enforcement: Adopt secure coding guidelines that require object-level permission verification for all cross-entity relationships and ensure reviewers confirm this for any public API endpoint.
- Runtime monitoring: Analyze logs for unusual cross-project FileLink operations (detach, delete, or re-parent actions), especially when performed by accounts lacking the appropriate management permissions. Automated tooling can complement manual review by highlighting such deviations.

