So every entry you want to eliminate is a sequence of non-: which contains XXX, which in regex world is [^:]*XXX[^:]*
But you also want to eliminate the : that follows it, and this means you want to match and eliminate [^:]*XXX[^:]*:.
Actually, that would not allow you to eliminate a field containing XXX if it happens to be the last; to fix this, you want to match the end of line as an alternative to the closing :, so the command is
sed -E 's/[^:]*XXX[^:]*(:|$)//g' that_file
However this still has an issue: it leaves a trailing : as soon as tha last item matches. To fix this, we can simply run another substitution ad hoc, so that the full Sed command is this,
sed -E 's/[^:]*XXX[^:]*(:|$)//g;s/:$//' that_file
Do we really need to susbstitution commands?
Sed has no lookaheads, which means that whatever we match is consumed, and cannot be matched again by the same s command, even if there's the g flag.
On the other hand, we want to eliminate the fields containing XXX together with either, but not both, of the two : around it.
If we choose the right :, as I did, than it's clear that if the last field (which matches with the trailing end of line instead of :) matches XXX, it will leave the result with a trailing : (unless all fields match XXX, in which case the result is the empty string).
This means that there's no way for a single substitution command to give you the "clean" answer for all scenarios of your usecase.
Using two s commands is enough to fix this, as I've showed.