Chrome vs. WordPress: All Text Showing as Glyphs / Symbols 🤯

Ever since mid december I’ve had a few reports from people that they were seeing my blog – the thing you’re reading now – rendered in unreadable text. Instead of seeing a nice serif font, they got presented with some wingdings-like symbols for all the text when visiting through Chrome on macOS.

Very strange, as I myself am also using Chrome for my main browsing and am not seeing it. So I kind of ignored the first report, as I thought it was a standalone case: “The user visiting might have overwritten their local font stack, and therefore things went wrong” I thought to myself. After the second report I started to get suspicious though …


With a few Google Search Coupons in hand, I found that I wasn’t the only one with this problem, and that it’s related to the use of Hoefler Text. “Hoefler Text” is the font used for all regular text here on, as it is on many other WordPress sites as I’m basically running the default WordPress Twenty Nineteen theme with a few CSS tweaks sprinkled on top. For some weird reason “Hoefler Text” gets replaced with its “Hoefler Text Ornaments” counterpart when one has that font installed.


With the holidays I kinda forgot the whole thing, but after a third report today I dug deeper and found the root cause: it’s not a bug in a local font stack nor in WordPress itself, but it’s a bug in Chrome

The issue appeared between these two Chrome releases:

  • 78.0.3904.108 (not broken)
  • 79.0.3945.88 (broken)

And seems fixed in Canary:

  • 81.0.4001.0 (not broken)

It also seems to happen only on macOS 10.15.x

Brave browser on the same version seems affected too. No other browser is affected.


As this is a very specific browser bug, and WordPress themselves are awaiting a Chrome update. In the meantime I’ve updated the CSS here to no longer use Hoefler Text, falling back to Garamond.

🧐 On a side note: the font-stack is defined about 10 times in the default WordPress Twenty Nineteen theme, plastered all over the CSS file. Weird choice imho. Anyways: know that you’ll have to do as many adjustments to get it fixed.

🙏 Thanks go out to all who reported the issue (@wolfr_2, @tommyquissens, and @edwinm)

WordPress 4.2 Stored XSS

Earlier this week WordPress 4.1.3. It fixed an XSS exploit discovered by a former student of mine. This week a new exploit – even in the new WordPress versions, including 4.2 – was uncovered.

Current versions of WordPress are vulnerable to a stored XSS. An unauthenticated attacker can inject JavaScript in WordPress comments.

If triggered by a logged-in administrator, under default settings the attacker can leverage the vulnerability to execute arbitrary code on the server via the plugin and theme editors.

Here’s how it works:

If the comment text is long enough, it will be truncated when inserted in the database. The MySQL TEXT type size limit is 64 kilobytes, so the comment has to be quite long.

The truncation results in malformed HTML generated on the page. The attacker can supply any attributes in the allowed HTML tags, in the same way as with the two recently published stored XSS vulnerabilities affecting the WordPress core.

Until a patched WordPress is available, it is wise to disable comments. I guess (read: think but haven’t tested it yet) that configuring your MySQL server with STRICT_ALL_TABLES would also work, as it should then trigger an error when too much data is attempted to being inserted.

UPDATE: Fixed in 4.1.4 and 4.2.1 (announcement). The rolled out fix checks the column length before actually tyring to perform the query. If the check fails, the query won’t be executed.

WordPress 4.2 Stored XSS →

Migrating your WordPress website from HTTP to HTTPS

In light of #https2015 I flipped the switch on earlier today: from today forth is only accessible over HTTPS.

If you run a news site, or any site at all, we’d like to issue a friendly challenge to you. Make a commitment to have your site fully on HTTPS by the end of 2015 and pledge your support with the hashtag #https2015.

The switch itself should be transparent, as all “old” http:// URLs automatically redirect to their https:// counterparts.

When initially looking for information regarding this switch for WordPress sites I’ve found a lot of cruft out there. A rather high hit on Google was one dating back from 2006 (2006? … Chrome didn’t even exist for another two years) ; A few other ones recommend you to install a WordPress plugin which is just wrong (You really needn’t install a WordPress plugin to enable HTTPS!); A slew of other ones had it right, yet were incomplete; etc.


Here’s how to move your WordPress website from HTTP to HTTPS in just a few simple steps:

1. Install an SSL Certificate

Buy a certificate for your domain and activate it on the server. Most of the time your hosting provider offers a simple UI for this activation: paste in the private key, the certificate itself, and the CA-bundle. If you have to manually install it, I recommend taking a look at Mozilla’s SSL Configurator to get you started with the correct settings.

Note: Don’t let SSL Certificate Providers rip you off though. Services like or offer them really cheap or even for free! Starting mid 2015 Let’s Encrypt will open it’s doors, offering free certificates for everyone.

You can safely install the certificate as your site will remain accessible over HTTP. In addition it’ll also be reachable over HTTPS. Verify this by manually changing the URL in the address bar from to Your website should appear, and the URL in the address bar should still hold the entered https:// URL.

Note that your browser will most likely not show the green lock icon next to the URL just yet, as your website will contain “Mixed Content”: the HTML of your site may be loaded over HTTPS, yet images contained may still be referred to using their http:// URL. We’ll fix this issue later on, in step 4.

Mixed Content warning in Chrome

Tip: Tools such as SSLLabs’ SSL Server Test come in handy to verify the proper installation of your certificate. Above that you’ll get a lovely report from it. Just one word of caution though: don’t run it on URLs used by your bank … those reports are mostly just depressing (sad but true)

Note: My first encounter with certificates back in the day had me confused about the CA-bundle. It took me a while to get to know that it’s no more than a text file containing all intermediate certificates, alle pasted one after the other.

2. Update the WordPress Settings

When having finished step 1 you’ll notice that next/prev links to blogposts and links to pages will still use the insecure http:// URLs. That’s because WordPress itself doesn’t know yet you’ll be using HTTPS from now on.

To let WordPress know you’re using HTTPS log in to wp-admin and under “Settings” → “General Settings” adjust the values for WordPress Address (URL) and Site Address (URL) to their HTTPS counterparts.

The WordPress Settings one needs to change

Once saved you should be able to start on your website over HTTPS and click through it – using the WordPress rendered links such as next/prev blogpost, pages, etc. – whilst remaining over HTTPS.

3. Force SSL for wp-admin

WordPress offers a setting to force the wp-admin only being accessible over HTTPS. To activate this edit your wp-config.php and add the following line:

define('FORCE_SSL_ADMIN', true);

Once adjusted you should be automatically redirected from to Whilst we later on (step 5) will redirect all traffic to HTTPS, it’s a good test before we change it all.

4. Fix those mixed content warnings

We’re almost to getting our site working entirely over HTTPS. What still remains is to update the content all our blogposts so that images referred, and blogposts linked (from within the content) use our https:// URLs instead of the http:// ones. Updating all blogposts manually would be a very time-consuming job. Luckily a single SQL query can this it for you.

Log on to PhpMyAdmin (or another tool which your hosting provider offers) and execute the queries below on your WordPress database.

Make sure you take a backup of your database first. If things were to go wrong you can always restore that backup.

Whilst at it I’ve also added a few extra queries to updating all internal pingbacks, and to updating all YouTube & Vimeo embeds.

# Update self-hosted embeds (images, iframes, scripts, etc.)
UPDATE wp_posts SET post_content = REPLACE(post_content, '', '');
UPDATE wp_posts SET post_content = REPLACE(post_content, '', '');

# Update internal pingbacks
UPDATE wp_comments SET comment_author_url = REPLACE(comment_author_url, '', '');
UPDATE wp_comments SET comment_author_url = REPLACE(comment_author_url, '', '');

# Update YouTube embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, '', '');
UPDATE wp_posts SET post_content = REPLACE(post_content, '', '');

# Update Vimeo embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, '', '');

# Update Flickr embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://farm', 'https://farm');

# Update Slideshare embeds
UPDATE wp_posts SET post_content = REPLACE(post_content, '', '');

[UPDATE] Note: Whilst the internal pingbacks don’t trigger any Mixed Content warnings themselves, I thought of the update as being a bit of forward thinking: that way you don’t bounce back from HTTPS to HTTP. And whilst we’re in PhpMyAdmin anyway, I’ve added them right here.

Once executed the mixed-content warnings should be gone and the green lock should appear. Clicking from blogpost to blogpost should work just fine, all whilst remaining on HTTPS.

No more mixed content: the green lock icon appears in the address bar

[UPDATE] To automatically scan one’s website for Mixed Content I’ve created a PHP CLI script that does the job for you. Check it out here.

If you do still get mixed content warnings (check for a little shield in the Chrome Address Bar) open the DevTools Console for more information: it could be – and I had this – that a CSS file still references an http:// URL. Manually fix all those errors one by one until you get the green lock icon.

A green lock icon is present, yet a shield (on the right) also appears. DevTools has more information needed for pinpointing the problem.

Do note that if you’ve included external resources (images/scripts/css/…) you may not be able to fix them all: if they’re not accessible over HTTPS, you won’t be able to fix that error.

5. Redirect all HTTP requests to HTTPS

Now that your site works fine over both HTTP and HTTPS, it’s time to flip the switch and make it no longer accessible over HTTP. Add these rules to your .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

The rules are written in such a way that “old” http:// URLs will transparently redirect to their https:// counterparts. That way incoming links that still use http:// will keep on working just fine, but will get a security upgrade along the way.

6. Tweak your SSL Settings

If you want you can tweak some of your SSL settings, such as enabling only a strict set of ciphers. Whilst this is entirely optional, one tweak is recommended though: enabling HTTP Strict Transport Security (thanks for the tip @mathias!)

To enable HSTS, add this line to your .htaccess:

# Enable HSTS
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS


Following these steps you should be able to migrate your WordPress website from HTTP to HTTPS. It looks quite cumbersome, yet it’s done in no time (writing this blogpost took more time than actually rolling it out). Above that you only gain benefits from embracing HTTPS. And yes, TLS is fast.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

WordPress < 3.6.1 PHP Object Injection

WordPress 3.6.1 contains a PHP Object Injection Vulnerability Fix, detected by one of my former students. He also made an extensive writeup about it:

Let’s recap: maybe_serialized(‘i:1;<funkycharacterhere>’) is inserted to the database. As WordPress does not see this as a serialized string (because it doesn’t end in ; or }), this will result in i:1;. When inserted, MySQL doesn’t know how to store it properly, and removes the <funkycharacterhere>. Later on, when the value i:1; is retrieved, it will be unserialized as it now has ; as last character which will make is_serialized() return true. Boom. Vulnerability.

WordPress < 3.6.1 PHP Object Injection →

wp-cli — A command line interface for WordPress

wp-cli is a set of command-line tools for managing WordPress installations. You can update plugins, set up multisite installs, create posts and much more.

Once installed, you can run commands such as:

wp plugin install hello-dolly

which will output:

Installing Hello Dolly (1.5)

Downloading install package from ...
Unpacking the package ...
Installing the plugin ...
Plugin installed successfully.

wp-cli →

Facebook for WordPress Plugin

Something that was long overdue: an official Facebook for WordPress Plugin which brings some basic Facebook features (such as injection of a Like Button, publishing to Facebook when publishing a post, etc.) and some new ones (such as tagging a Facebook friend straight from the WordPress “add post” screen) to WordPress

If you want to set up publishing – which I did – expect a lengthy process to go through (Facebook should omit the approval step imo).

UPDATE: I cannot seem to get the Publish to author’s Timeline feature working, and I’m not the only one. After publishing a post nothing is posted on my timeline and the publish-to-timeline-checkbox in my wp-admin goes unchecked.

The supposed fix that is circulating doesn’t work. Official Facebook response (found in the thread linked above) is “Hey folks, this gets disabled if there’s a Facebook API error. We’re working on a couple of things to make this flow easier. Please keep your eyes peeled for an update to the plugin next week.”

Good to read that they’ll be updating the flow. A pity they didn’t fix this before even launching

Facebook for WordPress →