If you have an object that needs an iterator, and you happen to give it an infinite iterator, then all should be well. Of course, that object should never require the iterator to stop. And that is the potentially bad design.
Think of a music player. You tell it to start playing tracks in "continuous play mode" and it plays tracks until you tell it to stop. Maybe you implement this continuous play mode by shuffling a playlist forever... until the user presses "stop". In this case, MusicPlayer needs to iterator over a playlist, that might be Collection, forever. In this case, you'd want either a CyclicIterator as you've built or a ShuffleIterator that randomly picks the next track and never runs out. So far, so good.
MusicPlayer.play(Iterator wouldn't care whether the play list ends or not. It works both with an iterator over a list of tracks (play to the end, then stop) and with a ShuffleIterator over a list of tracks (pick a random track forever). All still good.
What if someone tried to write MusicPlayer.playContinuously()--which expects to play tracks "forever" (until someone presses "stop"), but accepts an Iterator as the parameter? That would be the design problem. Clearly, playContinuously() needs an infinite Iterator, and if it accepts a plain Iterator as its parameter, then that would be bad design. It would, for example, need to check hasNext() and handle the case where that returns false, even though it should never happen. Bad.
So implement all the infinite iterators you want, as long as their clients don't depend on those iterators ending. As if your client depends on the iterator going on forever, then don't give it a plain Iterator.
This should be obvious, but it doesn't seem to be.