For the record and for the sake of future readers.
I've had a similar problem in the past and investigated it quite thoroughly.
My conclusion was that the "MoveTo acts as a Return" thing is actually a bug in the game engine that crashes the script for that frame. But the engine is smart enough to detect the crash, so it tries to run the script again next frame . . . and it crashes again . . . and it tries again . . . so the conclusion that it is in loop (which it is, but for a different reason).
This conclusion of mine if confirmed here once more, as there would be no reason for the OnDeath block to run over and over again.
The DoOnce works because on the second run, there is no MoveTo, therefore no crash, therefore no additional run of the script. Any other script condition that prevented the script to run the MoveTo two frames in a row would also work, e.g. a flip-flop switch or a timer.
By the same token, if the XMarker were in a different cell, the problem would not occur, because, as the player is moved to another cell, the rat would go off-scope and the script would not re-run.
And, again, by the same token, you can consistently recreate the scenario without the OnDeath block. I remember I used a TriggerZone that moved the player to a XMarker in the same cell, but outside the TZ, leading to exactly the same effect.
You also will have the same problem if the script that moves the player (even to a different cell) is in an item in the player's inventory. As the item goes along, its script continues running and crashing and running and crashing . . .
My 'crashing' conclusion may not be correct, but the game behavior is certainly consistent with this theory.