Schwab password policies and two factor authentication: a comedy of errors


Like probably millions of people I have a Schwab brokerage account, and that account holds a good portion of my savings for retirement. I care very much about protecting my savings, and one would expect that Schwab would care a great deal about protecting a reputation for protecting me.

This is why, during a recent tech support call and subsequent investigation, I have become appalled at what appears to be a Rube-Goldberg, duct-tape-and-bailing-wire approach to implementing their much bragged about two factor authentication. Below is my list of several poor design decisions that, while taken in isolation might just be embarrassing, come together to fool perhaps tens of thousands of people into thinking that their account is secure when it is not.

Strike one: Horrible password requirements passwords are limited to eight characters, cannot contain symbols, and are case insensitive. As a computer engineer and technical cofounder who has written a decent amount of authentication code, I realize that this is a hard one to fix. The excuse thrown around is always “legacy”, and indeed dealing with legacy issues like this can take time and money.

However, Ars Technica complained about this problem 1 1/2 years ago in a well-written piece here. In a PR statement quoted in the article, Schwab is “currently evaluating a project to offer lengthened passwords”. Clearly this is still under evaluation or they have decided not to fix this glaring problem.

As an aside, shouldn’t they be hashing passwords, in which case all passwords of any length would end up being the same length in the database?

Strike two: Their password interface fools you into thinking that you have a stronger password

When you set a password on, it will allow you to cut and paste a password of any length, which is then truncated to eight characters. Anyone concerned with security surely uses a password manager that automatically generates strong passwords. At the time I was using an algorithm that only generated alphanumeric, mixed case passwords without symbols.

I simply cut and pasted the generated password into the password blank on It was happily accepted (my generated password met all of the requirements except length). I saw that there were now dots representing the characters in my password (I didn’t count them, who does?), hit submit, and the system behaved as if I had successfully set a password.

I now know that on the backend, my secure 16 digit password got stored in the system as only the first eight characters.


This is the point where we transition from obvious, stupid, and embarrassing mistakes to gross negligence.

Thinking that I was going to significantly increase the security of my account, I contacted Schwab and received one of their security tokens.

Strike three: Token activation is clearly a hack

To activate my newly received token, I was instructed to go to the homepage and append the six digit token code onto the end of my password during a login attempt. The system, apparently, detects the fact that you’re using a token, checks your username and password and then checks for an active token with that code. If it finds one, it activates your token and requires the six digit token code thereafter.

To anyone with more than five minutes of UX experience this approach is subpar at best. Why not just have a friendly link near the login box called “activate your safepass token”, or something. I’ve never, ever seen this “append stuff onto your password” approach being used. If there is some benefit to this approach I’d like to hear it, but I think it’s more likely just a lazy or sloppy programmer.

I followed the instructions and I was immediately logged into my account. There was no feedback provided. I assumed that everything worked correctly and that I was now protected by two factor authentication.

Every subsequent login, I would dutifully enter my password and append the token code onto it. And it appeared to work. Every. Single. Time.

I’m not typically paranoid. However, I recently had a decent deposit into my retirement account, and I wanted to double check that everything was working correctly. I went to the homepage, entered my username and password without the token code, and hit submit. To my surprise, I was logged on to my account.

During my conversation with tech support, it became obvious that all of the previous problems combined to create one big security hole.

Which leads us to…

Strike, um, four: Wait till you see how they parse the password

Because passwords are at MOST eight characters – they can optionally be six or seven – one can’t just strip off the first eight characters and call that the password. I don’t know the internal structure of their database, so I can’t speculate on alternate approaches.

So what they do is allow UP TO eight characters to represent the password, which is stripped from the contents of the password field. Assuming that the user is activating a token, there will be characters left over. Instead of using the LAST six characters to check the token code, they pull the NEXT 6 characters.

But wait, you say, if passwords are eight characters and token codes are six characters, that’s the same either way, right? Remember strike two?

In my case, and I suspect in many other cases, I thought that my password was 16 digits. During token activation, my password field had 16+6=22 digits.

Schwab pulled the first eight digits, called that my password, checked that against the database and found a match. Then, they pulled the next six digits, called that the token code, and checked for an active token code that matched those six digits. Not finding any, it “helpfully” forgot all about this token business and logged me on with my correct password…without activating two factor authentication.

Let me illustrate.

What I think my password is: pAssWord1LaLaLaL

What Schwab stored my password as: password

The value of the token: 123456

The contents of the password field when I’m attempting to activate my token: pAssWord1LaLaLaL123456

What Schwab checks against by stored password: password (match)

What Schwab checks against the token database: 1LaLaL (no match)

Schwab’s weird password logic: match + no match = log me in and forget I was trying to activate my token

The upshot: There are likely thousands of people who think they’re protected by two factor authentication that are not. All you have to do to hit this bug is attempt to set a password that’s greater than 8 characters (maybe you didn’t count the dots) and then try to activate a security token. There’s no way to know that it didn’t activate without testing it yourself.

Note, however, that the above bug only prevents you from activating your token. If you’ve already managed to activate your token, then as far as I know the two factor authentication works fine.

This stuff could be fixed in a few days by adding a JavaScript length check to the password field and moving the token activation to a separate link instead of using the append method. Schwab is either incapable or unwilling to spare the resources.

As a courtesy, I contacted Schwab to report this vulnerability almost 2 months ago, and have been largely ignored. Perhaps worse, they assigned me a non-technical customer service guy who was supposed to talk to someone and update me on what’s going on. He clearly did not understand the problem I was describing, and it became obvious after a few weeks that his job was basically to keep me busy until I lost interest. After a month, the best he could do was say that they were aware of problems generally, that they were working on unspecified changes, and that they plan to release updates at an unspecified time in the future.

The standard response from Schwab whenever these issues are brought up is that they have a “multilayered security strategy”. I recently initiated a transfer out of my brokerage account of a fairly large sum (for me). I did get a phone call to confirm, but they were happy to approve the transfer when I gave them my birthday and mother’s maiden name.

I think we all know how secure using birthday/mother’s maiden name is.

I have now used an additional security feature to set a verbal password on my account. However, I must point out that birthday/mother’s maiden name is the default security setup. Considering the above issues, for several months my entire savings was protected only by an eight character case insensitive password and two pieces of information that can be gotten basically from my Facebook page.

If you would like to be notified of new blog posts in the future, you can sign up for my mailing list here:

About the author

Jeremy Tunnell
By Jeremy Tunnell