Skip to content

fix(server): prevent unauthorized item moves to and from arbitrary inventories - #650

Merged
Qwerty1Verified merged 3 commits into
mainfrom
fix/authorize-inventory-moves
Sep 10, 2026
Merged

Qwerty1Verified merged 3 commits into
mainfrom
fix/authorize-inventory-moves

Conversation

@Qwerty1Verified

Copy link
Copy Markdown
Member

Summary

qb-inventory:server:SetInventoryData performed item moves between whatever two
inventories the client named, with no check that the player had either of them open.
The identifiers come straight from the client, so naming an inventory was sufficient
to act on it.

Exposure was in both directions and across every namespace (not just other players):

  • otherplayer-<id> reached any online player's live items, with no proximity
    requirement and without their inventory being open.
  • Stash, trunk and glovebox identifiers reached any inventory by name. Trunk
    identifiers are trunk-<plate> and plates are readable in game, so any parked
    vehicle's trunk was reachable from anywhere on the map.
  • drop-<id> reached any drop.

Because both sides of the move were unchecked, this allowed items to be moved into
another player's inventory as well as out of it, so planting items and emptying
a stash into a drop were both possible alongside straightforward theft.

Fix

  • isOpenFor(inventoryId, src) verifies the recorded viewer before any item is read
    or moved, and is called for both sides of the move.
  • Drops now record the viewer, isOpen = source rather than true, at both the
    creation and open sites.
  • Player inventories gain InventoryViewers[targetId] = viewerSrc, written by
    OpenInventoryById and cleared on close and on disconnect.
  • Amounts are coerced before being compared, so a non-numeric amount is rejected
    rather than throwing, and the inventory names are type-checked.

No authorization policy was added to qb-inventory. Whether to grant access remains
the caller's decision, which is why the decision for a distance check doesn't live in qb-inventory.
Also fixes a pre-existing leak that this made addressable: a player disconnecting
with a drop open left isOpen set forever, which stopped the cleanup thread deleting
the entity and made the bag permanently unopenable.

Related issue

Closes #645

Change type

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactor, maintenance, or performance improvement

Testing

  • FXServer artifact: b35265
  • qb-core version or commit: 1.3.0
  • Resource version or commit: 2.2.3 / 0e0e0c5
  • Server operating system: Windows Server 2022
  • Test steps and results:

Attack reproduced with a temporary client command firing the net event directly.

  1. Move from a closed trunk: rejected. Opened the trunk, identical command: succeeded,
    confirmed by closing and reopening.
  2. Same against a closed drop: rejected. Opened: succeeded.
  3. otherplayer- lifecycle, self-granted via OpenInventoryById: rejected before the
    grant, viewer recorded on open, move succeeded while open, viewer cleared on close,
    rejected again afterwards.
  4. Disconnecting with a bag open: bag is openable again and despawns on the cleanup
    interval, where previously it was stuck permanently.

Compatibility and migration

None

Checklist

  • I agree to follow the QBCore FiveM Code of Conduct.
  • My pull request title follows Conventional Commits, such as fix(scope): ... or feat(scope): ....
  • This pull request contains one focused change and does not include unrelated formatting or refactoring.
  • I tested the change on a current FXServer artifact with the relevant official resources and dependencies.
  • Existing repository checks and linting pass.
  • I documented new behavior and identified every breaking or migration-related change.
  • I added or updated configuration examples, SQL migrations, and translations where applicable.
  • I removed credentials, webhook URLs, license keys, database data, player identifiers, and other private information.
  • I have the right to submit all included code and assets under the repository's license.
  • I understand and reviewed all submitted code, including any AI-assisted code, and accept responsibility for its correctness and licensing.

@Qwerty1Verified
Qwerty1Verified merged commit ee1a418 into main Sep 10, 2026
2 checks passed
@Qwerty1Verified
Qwerty1Verified deleted the fix/authorize-inventory-moves branch September 10, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] SetInventoryData allows item theft from any player via otherplayer-<id> (no auth/distance check)

1 participant