On client, ticking the "Don't allow spectators" checkbox actually does nothing by itself - it only updates in conjunction with a battle request being sent to the server. When you toggle the checkbox initially to checked and challenge a user, a /hidenext request is sent prior to the challenge. The client then stores a hiddenNextBattle value of true, and that's why the password is added to the back of the URL. But because unchecking the box doesn't actually do anything by itself, in order to account for this, if there is a hiddenNextBattle value of true in app.user.get('settings') but the checkbox is unchecked, it is assumed that you just unchecked the box and so sends a /hidenext off request to the server before the challenge. The relevant logic here is on the client in client-mainmenu#adjustPrivacy.
One way to fix this would be to force the checkbox to instantly update the user's hiddenNextBattle settings instantly on clicking the checkbox. This might have undesirable behavior though; for example, you might check the box for a ladder game, not start the ladder game because you saw a friend send a challenge request, and accept the friend's challenge request with hiddenNextBattle true. The other way to fix this is to make the /hidenext command do nothing when typed manually by users. Either way, there's going to be some undesirable behavior.