Summary
InvoiceShelf contains an authorization flaw in the estimate-to-invoice conversion endpoint that checks whether an authenticated user may create invoices but does not verify access to the selected estimate. A user with the required invoice-creation ability could use an estimate belonging to another company, exposing its contents and potentially causing the original estimate to be changed or deleted.
InvoiceShelf contains an authorization flaw in the estimate-to-invoice conversion endpoint that checks whether an authenticated user may create invoices but does not verify access to the selected estimate. A user with the required invoice-creation ability could use an estimate belonging to another company, exposing its contents and potentially causing the original estimate to be changed or deleted.
Affected context
The issue occurs in multi-company InvoiceShelf deployments before the affected fix where the estimate conversion route accepts a route-bound estimate. Risk increases when an authenticated user has the ability to create invoices and the application resolves estimates without confirming that they belong to the user's company or authorized tenant. The conversion workflow may also execute company-configured actions against the original estimate.
The issue occurs in multi-company InvoiceShelf deployments before the affected fix where the estimate conversion route accepts a route-bound estimate. Risk increases when an authenticated user has the ability to create invoices and the application resolves estimates without confirming that they belong to the user's company or authorized tenant. The conversion workflow may also execute company-configured actions against the original estimate.
Exploit preconditions
- Attack surface: Authenticated web API endpoint for estimate-to-invoice conversion - Required access: A valid account with the create-invoice ability - Trigger point: A request to the estimate conversion route containing an estimate
identifier
- Authorization gap: The endpoint checks invoice-creation permission but does not
independently authorize access to the route-bound estimate
- Why exploitation is possible: Estimate identifiers can resolve across company
boundaries, allowing data from another company's estimate to be incorporated
into an invoice in the attacker's company
- Attack surface: Authenticated web API endpoint for estimate-to-invoice conversion - Required access: A valid account with the create-invoice ability - Trigger point: A request to the estimate conversion route containing an estimate
identifier
- Authorization gap: The endpoint checks invoice-creation permission but does not
independently authorize access to the route-bound estimate
- Why exploitation is possible: Estimate identifiers can resolve across company
boundaries, allowing data from another company's estimate to be incorporated
into an invoice in the attacker's company
Why this happens
The underlying bug is an object-level authorization failure mapped to CWE-639, Authorization Bypass Through User-Controlled Key. The controller authorizes the requested operation at the capability level but fails to enforce ownership or tenant scope for the specific estimate object selected by route-model binding. As a result, a valid permission to create an invoice is incorrectly treated as permission to read and act on any resolvable estimate.
The underlying bug is an object-level authorization failure mapped to CWE-639, Authorization Bypass Through User-Controlled Key. The controller authorizes the requested operation at the capability level but fails to enforce ownership or tenant scope for the specific estimate object selected by route-model binding. As a result, a valid permission to create an invoice is incorrectly treated as permission to read and act on any resolvable estimate.
Potential impact
- An attacker may copy another company's line items, prices, totals, taxes, notes, currency, and customer data.
- Sensitive customer and billing information could be disclosed across company boundaries.
- An attacker could create invoices containing data from an unauthorized company.
- The victim company's original estimate may be changed or deleted when configured conversion actions are processed.
- Business records and financial workflows could be corrupted.
- An attacker may copy another company's line items, prices, totals, taxes, notes, currency, and customer data.
- Sensitive customer and billing information could be disclosed across company boundaries.
- An attacker could create invoices containing data from an unauthorized company.
- The victim company's original estimate may be changed or deleted when configured conversion actions are processed.
- Business records and financial workflows could be corrupted.
General mitigation guidance
Mitigation generally focuses on enforcing object-level authorization at every operation boundary. Estimate retrieval and conversion should be constrained by the authenticated user's company or tenant context, rather than relying only on a general create-invoice permission. Secure-by-default patterns include scoped queries, server-side ownership checks, explicit authorization policies for both the source estimate and destination invoice, and transaction safeguards for conversion actions. User-controlled identifiers should not determine access without an independent authorization decision, and application roles should receive only the minimum cross-company privileges required.
Mitigation generally focuses on enforcing object-level authorization at every operation boundary. Estimate retrieval and conversion should be constrained by the authenticated user's company or tenant context, rather than relying only on a general create-invoice permission. Secure-by-default patterns include scoped queries, server-side ownership checks, explicit authorization policies for both the source estimate and destination invoice, and transaction safeguards for conversion actions. User-controlled identifiers should not determine access without an independent authorization decision, and application roles should receive only the minimum cross-company privileges required.
How teams detect issues like this
Detection can include static and dynamic checks for controller methods that use route-bound or user-supplied object identifiers without tenant-scoped queries. Code review should look for capability checks that are not paired with object-ownership or company-membership validation, especially in copy, export, conversion, update, and delete workflows. Automated tests can attempt cross-company object references using authorized accounts, while policy enforcement can require authorization checks for every retrieved domain object.
Detection can include static and dynamic checks for controller methods that use route-bound or user-supplied object identifiers without tenant-scoped queries. Code review should look for capability checks that are not paired with object-ownership or company-membership validation, especially in copy, export, conversion, update, and delete workflows. Automated tests can attempt cross-company object references using authorized accounts, while policy enforcement can require authorization checks for every retrieved domain object.

