I’ve been receiving support requests for a login form issue when Jetpack Protect is used. This module for Jetpack adds a math captcha to the login form with the label “Prove your humanity”.
Below are some screenshots of what is supposed to look like:
Backend (wp-login.php):
Front end (WP-Members login form):
The bug people have been reporting is that the input field is not displayed when used in the WP-Members login form, but it works fine in the wp-login.php. That has led people to believe that the bug is in WP-Members.
When I first looked at it, I saw the problem immediately. If you use the browser inspector to view the generated HTML, you’ll see that there is no whitespace in the field’s input tag between “input” and “type” which results in a tag named “inputtype” (which of course is invalid HTML):
Notice that all the other HTML for Jetpack is correct and valid. It’s only this one tag.
That led me to believe the bug was in Jetpack (which it is). But that did not satisfy me.
I usually operate under the assumption that there must be something I did to cause it. So I needed to dig a little farther.
It is probably important to give a little bit of information as to how this HTML gets into the form in the first place. It is the result of a WordPress action hook – login_form. login_form allows plugins to add to the WordPress login form. WP-Members adds this same action hook so that forms adding to the WP login should remain compatible with WP-Members.
One thing to note is that in order for this to work when placing the HTML into a widget or in the main content area, the content needs to be buffered. Buffering means that any output is not immediately printed to the screen. The way that WP’s form is built, the action allows plugins to “echo” or print their extra HTML right away. But that doesn’t work if you want it in the main content area when running a filter on the_content. We need to buffer that output so it doesn’t go to the screen right away and hold it in a variable.
That is what led me to the bug. I took a look at the file /modules/protect/math-fallback.php in Jetpack. That’s where this input tag is handled. The first thing to notice is that the tag and attributes are done on multiple lines:
When I saw that, I knew what it was. Turning on the setting to view hidden characters (line breaks, tabs, spaces) it looks like this:
Notice there is no space after the tag name or after each line. (Line breaks are indicated by a paragraph notation, single space indicated by a dot.)
That’s no problem for when this is printed to the screen immediately as is the case when the input is displayed on wp-login.php. But it’s a problem for buffered output because none of those line breaks will be recognized. And it’s not the line breaks that are the problem, it’s the fact that there’s no space before the line break.
Without a space there, we get the “inputtype” run together creating an invalid tag.
Why wasn’t it a problem in 6.5 and earlier versions of Jetpack? This input was all defined on a single line (just like the one below it, which renders just fine).
I made the necessary change and tested, it works fine. So I submitted this as a pull request (a fancy way to say, I submitted a proposed fix to the Jetpack project) and they did accept it into the project. It looks like it is currently tagged for the 6.7 release.
https://github.com/Automattic/jetpack/pull/10306
In the meantime, you can either use Jetpack 6.5 which works fine, or open up /modules/protect/math-fallback.php in Jetpack, scroll to the math_form() function, and add a space before each line break for the “jetpack_protect_num” tag (especially after “input”). That’s not a permanent solution since you’re hacking a core file, but since the change will be coming in the plugin itself, hacking it will hold you over to that release.