Okay, so this is due to allowing non-player entities to go through "locked" tunnels (ones which go back to higher spheres which are locked to push the player downwards). It's useful so that enemies don't get stuck in higher spheres and can enter the player's sphere from them, but also means powerups escape through them.
Thinking through this, I'm wondering if we should add a special case for powerups so that they can't enter locked tunnels and also make it so that enemies never leave the sphere the player's currently in.
Probably optimal to just add a check at the point of departure, if the sphere departing is playership's parent sphere, then don't depart.
Could probably do this with a polymorphic override in the entity::enemy::base class for the move_to_tunnel() function, which just checks if(player_ship && player_ship->parent == parent) and if so returns, and if not calls the polymorphic ship::base's function in turn. Either that, or wherver move_to_tunnel() is called from. It's not the most optimal, because you're checking that branch every tick potentially, but it's a lot simpler than adjusting the collision groups.