Code analysis using yarn mappings for 1.18:
In Entity.java, within the baseTick method, there is this block of code that checks if the entity is in lava.
If so, then the entity is set on fire. Notice that the isInLava block is separate from the firetick block and is not wrapped by a check for isClient.
Within the setOnFireFromLava method, there is a call to damage the item with damage(). There is still no check for isClient.
This method is implemented on a per entity type basis. Lets use ItemEntity as an example:
In this method, the item entity's health is decremented. If there is no health remaining, the entity is removed. Considering that there are no checks for isClient, this method can be called on the client just by item ticking in lava. In doing so, the client side is able to destroy item entities independently from the server if the item is in lava.
Consider a scenario where an item entity is in lava briefly, for example, a shulker box may be unloaded rapidly in this regard by destroying the box item entity with lava (a new feature in 1.17). The lava is removed quickly by a dispenser before the box's contents are burned.
If there is some delay in receiving the packets, the lava may be removed too late client-side. In such a scenario, the box content item entities can be destroyed by the client side alone – to the server, the item entities are fine. These ghost-items are a form of server-client de-sync. This is not good.
A fix can be implemented by checking for isClient at any point in the process to damage the entity. The server should be fully authoritative when it comes to damage/entity deletion.