VYPR
Moderate severityNVD Advisory· Published Oct 27, 2025· Updated Oct 28, 2025

InventoryGui affected by item duplication in GUIs which use GuiStorageElement

CVE-2025-62783

Description

InventoryGui is a library for creating chest GUIs for Bukkit/Spigot plugins. Versions 1.6.1-SNAPSHOT and earlier contain a vulnerability where any plugin using the `GuiStorageElement can allow item duplication when the experimental Bundle item feature is enabled on the server. The vulnerability is resolved in version 1.6.2-SNAPSHOT.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

InventoryGui library <=1.6.1-SNAPSHOT allows item duplication when a plugin uses `GuiStorageElement` and the server has the Bundle feature enabled.

Vulnerability

Overview

CVE-2025-62783 is a vulnerability in the InventoryGui library (versions 1.6.1-SNAPSHOT and earlier), which is used by Bukkit/Spigot plugins to create chest GUIs. The flaw resides in the GuiStorageElement class, and it can lead to item duplication when the experimental Bundle item feature is enabled on the server [1][2].

Exploitation

Details

The vulnerability is triggered during a double-click action on an item that occupies multiple slots. Specifically, when a player double-clicks to collect items, the simulateCollectToCursor method in InventoryGui is invoked, which calls GuiStorageElement.setStorageItem. That method can throw a NullPointerException when the player object is null, as seen in the stack trace [2]. The commit fixing the issue wraps a large section of the interaction handling in a try-catch block, including the handling of the COLLECT_TO_CURSOR action, to prevent the NPE from propagating and causing the duplication [3]. The bug requires that a plugin using InventoryGui is installed, the server has the Bundle feature enabled, and the player performs a specific double-click gesture.

Impact

Successful exploitation allows an attacker to duplicate items within the game. This can destabilize server economies, break gameplay balance, and potentially lead to widespread abuse if the vulnerability is widely known [2]. The duplication occurs because the NullPointerException interrupts normal inventory processing, likely leaving the item in the storage element while also giving a copy to the player.

Mitigation

The vulnerability is patched in version 1.6.2.2-SNAPSHOT of the InventoryGui library [1]. Server administrators should ensure that any plugins using InventoryGui are updated to a version that includes the fix (at least 1.6.2-SNAPSHOT). As a temporary workaround, disabling the experimental Bundle feature on the server may prevent exploitation, but updating the library is the recommended course of action.

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
de.themoep:inventoryguiMaven
< 1.6.2-SNAPSHOT1.6.2-SNAPSHOT

Affected products

2

Patches

1
27a52ef6d934

Fix possible NPE and make handling more robust to errors

https://github.com/Phoenix616/InventoryGuiPhoenix616Apr 2, 2024via ghsa
1 file changed · +24 25
  • src/main/java/de/themoep/inventorygui/InventoryGui.java+24 25 modified
    @@ -1152,29 +1152,29 @@ int getWidth() {
         private GuiElement.Click handleInteract(InventoryInteractEvent event, ClickType clickType, int slot, ItemStack cursor) {
             GuiElement.Action action = null;
             GuiElement element = null;
    -        if (slot >= 0) {
    -            element = getElement(slot);
    -            if (element != null) {
    -                action = element.getAction(event.getWhoClicked());
    -            }
    -        } else if (slot == -999) {
    -            action = outsideAction;
    -        } else {
    -            if (event instanceof InventoryClickEvent) {
    -                // Click was neither for the top inventory nor outside
    -                // E.g. click is in the bottom inventory
    -                if (((InventoryClickEvent) event).getAction() == InventoryAction.COLLECT_TO_CURSOR) {
    -                    GuiElement.Click click = new GuiElement.Click(this, slot, clickType, cursor, null, event);
    -                    simulateCollectToCursor(click);
    -                    return click;
    -                } else if (((InventoryClickEvent) event).getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
    -                    // This was an action we can't handle, abort
    -                    event.setCancelled(true);
    +        try {
    +            if (slot >= 0) {
    +                element = getElement(slot);
    +                if (element != null) {
    +                    action = element.getAction(event.getWhoClicked());
                     }
    +            } else if (slot == -999) {
    +                action = outsideAction;
    +            } else {
    +                if (event instanceof InventoryClickEvent) {
    +                    // Click was neither for the top inventory nor outside
    +                    // E.g. click is in the bottom inventory
    +                    if (((InventoryClickEvent) event).getAction() == InventoryAction.COLLECT_TO_CURSOR) {
    +                        GuiElement.Click click = new GuiElement.Click(this, slot, clickType, cursor, null, event);
    +                        simulateCollectToCursor(click);
    +                        return click;
    +                    } else if (((InventoryClickEvent) event).getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
    +                        // This was an action we can't handle, abort
    +                        event.setCancelled(true);
    +                    }
    +                }
    +                return null;
                 }
    -            return null;
    -        }
    -        try {
                 GuiElement.Click click = new GuiElement.Click(this, slot, clickType, cursor, element, event);
                 if (action == null || action.onClick(click)) {
                     event.setCancelled(true);
    @@ -1200,9 +1200,8 @@ private GuiElement.Click handleInteract(InventoryInteractEvent event, ClickType
                     ((Player) event.getWhoClicked()).updateInventory();
                 }
                 plugin.getLogger().log(Level.SEVERE, "Exception while trying to run action for click on "
    -                    + (element != null ? element.getClass().getSimpleName() : "empty element")
    -                    + " in slot " + slot + " of " + getTitle() + " GUI!");
    -            t.printStackTrace();
    +                    + (element != null ? element.getClass().getSimpleName() : "empty/unknown element")
    +                    + " in slot " + slot + " of " + getTitle() + " GUI!", t);
             }
             return null;
         }
    @@ -1652,7 +1651,7 @@ void simulateCollectToCursor(GuiElement.Click click) {
                             if (otherStorageItem.getAmount() == 0) {
                                 otherStorageItem = null;
                             }
    -                        storageElement.setStorageItem(i, otherStorageItem);
    +                        storageElement.setStorageItem(click.getWhoClicked(), i, otherStorageItem);
                             if (newCursor.getAmount() == newCursor.getMaxStackSize()) {
                                 break;
                             }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.