There are several 'basic' sources for glitches in logic, in any logic family.
Noise from a badly decoupled supply voltage can be one typical source. The different logic families have slightly different requirements here, but in general it is the same.
Long/slow shifting signal flanks wil open for any noise in the system and give glitches. You control this with adding/using Schmitt trigger input gates.
If you have a very 'dirty' input signal and the schmitt trigger does not take care of the input glitches, you may need to add a debounce circuit on the input.
If you design complex logic with a number of gates, you may(will) have glitches when the different signal combinations are delayed differently through the network of gates. That is why it is normal with a defined clock or gating signal to sync the result.
If you use ripple or async counters, you may have undefined combinations on the outputs during counting, creating glitches in the following decoded logic. This is a bigger problem when the clock frequency are getting higher, and the inherent delay inside the ripple counters get more prominent. To eliminate this, use a synchronized counter.
So, the general answer is to always use defined states and stable inputs before executing a change in the logic state of the outputs.