Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Defaults Matter

    Defaults Matter

    We tout decicions and not options. We laud people who make it work, simply and efficiently. So how do we decide what the default decisions should be?

    I was looking at a new plugin for an affiliate program, and it set up the links based on region. The way this plugin worked, if you don’t have an account specifically for that country, the plugin author had it set to use his ID if the user didn’t enter one. This is a small issue, in that the user may, unwittingly, be letting the dev earn money of their site. It’s also just not permitted. You don’t put up links or ads on someone else’s site without them checking a box to allow it, it’s gauche and against the .ORG guidelines.

    Timer settingsWithout knowing the issues of the affiliate app, I pushed back, and was surprised that the plugin dev was doing this because if he didn’t, the code would break. The affiliate program didn’t have a fallback to show a default location if you didn’t have an ID for that area, it just errored out. Thankfully, this developer and I worked out a solution. If there was no ID for the region, the plugin wouldn’t display the affiliate links. There was also a checkbox “Use the developer’s affiliate code in regions where you don’t have one!” that explained this would help feed and clothe the dev.

    Another example. A plugin made a shortcode to play MP3s, and by default if you don’t have an MP3, it played one of him from his domain. Besides the fact that you’ll crash your server if you get popular enough, the fallback for that should be for the shortcode to output “Oh noes! No MP3 picked!”

    This got me thinking about how we determine the defaults for anything. We pick what we want to support most, we guess at what people will use most, and we test what we can think of. But that isn’t easy at all. Start factoring in upgrades. You add a new feature and you want people to use it, so you turn it on to aid discovery (Jetpack does this). Not everyone likes that and gets mad that the first thing they have to do is disable it! So you think about alert boxes “Hey, you upgraded and there’s a new thing!” but then people hate dismissing those alerts.

    Picking the right defaults for your intended audience matters. The affiliate code guy knew about an error if he didn’t do that, and compensated in a way that would be seamless for the users, but a little unethical (I felt) because it took advantage of their ignorance to make money for him. I’m kind of hip on educating the masses. The shortcode guy just didn’t think about the long-term ramifications. Neither actually meant to be harmful, but both were thinking about their users and their familiarity with things. Both were cognizant of the fact that a product not working because of incomplete settings should not break.

    Firetruck SettingsDetermining your default settings is a race between education and simplification. It should be as simple and straightforward as possible to make things easier for the new users. At the same time, it should be made totally obvious in straightforward ways what the defaults can be changed to. This can be done with help screens in your plugins, but also in the welcome pages and the in-line explanations of setup. You can hide aspects of the code from users until they’ve finished pre-requisites.

    Defaults are the one place where you have to actually try to know what the users will be thinking, so don’t worry if you get it wrong. You can always iterate.

  • Mailbag! .htaccess questions

    Mailbag! .htaccess questions

    New thing! So many people email me for tech support, which I’m pretty clear on how you’re not going to get it. But Ken (the web mechanic) asked some pretty basic questions, and I’ve decided to answer some of them.

    A loopIn public. Lucky you, Ken. Don’t worry! These were good questions. See, one of the (many) reasons I love WordPress and the support forums is that the answers are public so everyone can see what the question was and how it was answered! This is hugely important to foster a community, so that’s why I’m going to answer this in public, with your personal information removed, of course.

    Ken’s basic concern is that .htaccess is confusing, and is there a preferred order? The answer is yes. The basic idea is that .htaccess rules are a top-down process. The server reads the file from the top on down, in order, 1-2-3. For this reason alone, it’s obvious why you don’t want a super long .htaccess file: more to read takes longer!

    The WP permalink area… Should that always be dead last?

    Yes! WordPress rules always go last. Remember what I said about top-down? If you were to put WordPress at the top, you would load WordPress, process it, and then do the rest of the rules. Which once you say that, it’s pretty obvious eh?

    Deny IP addresses/ referrers. To me it would make sense for them to be at the beginning… Would that be true?

    True! The access controls (including IP blocks) first. Redirects go next, starting from most specific (about-me to about) first to general last. Then your Rewrite rules.

    Compression/Caching/mod_expires… I haven’t a clue where they most appropriately go. Securing wp-config, htaccess itself, other files, etc. … Before? After? the WP permalink block.

    I put them before my re-writes. Since I use a deny to secure .svn type files, it’s an access control so it goes first.

    So how does this work? Here’s a practical example. You want to do the following: remove www from your domains, protect your wp-config file, protect your comments and login from direct attacks, redirect some old pages from before you were WordPress, redirect your old permalink formats, and gzip/compress things. Oh and run WordPress!

    The order would go like this:

    1. Access Control: This is the part where we’re protecting specific files, but also blocking IPs. Basically it’s ‘Security First.’
    2. Remove WWW: We want to make sure everyone’s redirected to the non-www page. If you’re redirecting specific domains (like I send tech.ipstenu.org to halfelf.org), you do it here as well.
    3. GZIP: I do my compression here, though it woudl work just as well swapped out with the next one.
    4. Redirect: Here we’re talking one-off redirects like sending ‘about-me’ to ‘about’.
    5. Rewrite: The ReWrite rules are the ones where you say “Send http://example.com/2014/01/10/postname/ to http://example.com/postname/” with those rules with regex.
    6. WordPress Rules: Last. Always always last.

    And that is .htaccess!

    If you want a look at how my .htaccess is structured, see My super-secret .htaccess file, which hasn’t changed much since 2013. I do a couple things out of order, but they’re minor enough. As long as I can limit any recursive loops with the .htaccess checks, I’m doing good.

  • New Smilies?

    New Smilies?

    While the arguments for and against are pretty hot and heavy (see the trac ticket for more), it’s no secret I’m pro-new smilies. The old ones are too small, too pixelated, and too (pardon the phrase) web 1.0. They look old and out of date on my site.

    Here they are at normal size:

    Old Smilies, normal sized

    And here’s double:

    The smilies at twice size

    These are both gifs, to illustrate the size issue. Notice how they’re fuzzy?

    I want to make one thing clear, pun intended. None of my issues have to do with Retina. I don’t like ‘small’ anything. The smilies are too small, much like the font on many people’s websites, the pixelization is hard for me to identify. In fact, while I’m using the new smilies here, you’ll notice they’re bigger. Sure, cause I tossed this in my CSS:

    #wp_grins img, img.wp-smiley {
        height: 25px;
    }
    

    And that’s all it took to make them something I felt was readable. But the beauty, and why I like the new SVG images, is that I can make them larger like that, without losing readability.

    Thankfully, due to the curmudgeony efforts of the new smilies’ biggest naysayer, Otto, we have a filter! I’ve talked about this before, in how I handled both SVG and PNG as smilies for IE. I have a couple options here. I could write some code myself, or I could use New WordPress.com Smileys (which is on GitHub for reasons, the code is fine!).

    I like the plugin a lot. I like it so much, I refactored my SSL Grins plugin to use them with the fancy pants new span code (instead of images). But… Well, I already had this done by the time his plugin came out, and I like how I accounted for things differently. The only real difference though is he uses spans, and I just swap out the images:

    <?php
    /*
    Plugin Name: Custom Smilies
    Plugin URI:  https://ipstenu.org
    Description: I like the new smilies, shut up Otto.
    Version: 1.0
    Author: Mika Epstein
    Author URI: https://ipstenu.org/
    */
    
    // Move Smilies
    add_filter('smilies_src','helf_smilies_src', 1, 10);
    function helf_smilies_src($img_src, $img, $siteurl) {
        if ( strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE 8' ) || strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE 7' ) || strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'Android' ) ) {
            $img = 'ie/'.$img;
        }
        else {
             $img = str_replace("png", "svg", $img); // Remove PNG
        }
        return $siteurl.'/code/images/smilies/'.$img;
    }
    
    // This is in a paren for my sanity....
    {
        global $wpsmiliestrans;
    
        if ( !get_option( 'use_smilies' ) )
            return;
        
        if ( !isset( $wpsmiliestrans ) ) {
            $wpsmiliestrans = array(
            ':mrgreen:' => 'icon_mrgreen.png',
            ':neutral:' => 'icon_neutral.png',
         // removing b/c new versions
            ':twisted:' => 'icon_evil.png',
              ':arrow:' => 'icon_arrow.png',
              ':shock:' => 'icon_eek.png',
              ':smile:' => 'icon_smile.png',
                ':???:' => 'icon_confused.png',
               ':cool:' => 'icon_cool.png',
               ':evil:' => 'icon_evil.png',
               ':grin:' => 'icon_biggrin.png',
               ':idea:' => 'icon_idea.png',
               ':oops:' => 'icon_redface.png',
               ':razz:' => 'icon_razz.png',
               ':roll:' => 'icon_rolleyes.png',
               ':wink:' => 'icon_wink.png',
                ':cry:' => 'icon_cry.png',
                ':eek:' => 'icon_surprised.png',
                ':lol:' => 'icon_lol.png',
                ':mad:' => 'icon_mad.png',
                ':sad:' => 'icon_sad.png',
                  '8-)' => 'icon_cool.png',
                  '8-O' => 'icon_eek.png',
                  ':-(' => 'icon_sad.png',
                  ':-)' => 'icon_smile.png',
                  ':-?' => 'icon_confused.png',
                  ':-D' => 'icon_biggrin.png',
                  ':-P' => 'icon_razz.png',
                  ':-o' => 'icon_surprised.png',
                  ':-x' => 'icon_mad.png',
                  ':-|' => 'icon_neutral.png',
                  ';-)' => 'icon_wink.png',
            // This one transformation breaks regular text with frequency.
            //     '8)' => 'icon_cool.png',
                   '8O' => 'icon_eek.png',
                   ':(' => 'icon_sad.png',
                   ':)' => 'icon_smile.png',
                   ':?' => 'icon_confused.png',
                   ':D' => 'icon_biggrin.png',
                   ':P' => 'icon_razz.png',
                   ':o' => 'icon_surprised.png',
                   ':x' => 'icon_mad.png',
                   ':|' => 'icon_neutral.png',
                   ';)' => 'icon_wink.png',
                  ':!:' => 'icon_exclaim.png',
                  ':?:' => 'icon_question.png',
            // New for me
                  '>:(' => 'icon_mad.png',
                  'o_O' => 'icon_surprised.png',
                  'O_o' => 'icon_eek.png',
                  '^^‘' => 'icon_redface.png',
                  ':‘(' => 'icon_cry.png',
                  ':’(' => 'icon_cry.png',
       ':whiterussian:' => 'icon_whiterussian.png',
                  '|_|' => 'icon_whiterussian.png',
                   ':/' => 'icon_uneasy.png',
                  ':-/' => 'icon_uneasy.png',
          ':developer:' => 'icon_developer.png',
            ':burrito:' => 'icon_burrito.png',
            ':martini:' => 'icon_martini.png',
                  '>-I' => 'icon_martini.png',
              ':blush:' => 'icon_redface.png',
              ':heart:' => 'icon_heart.png',
                //'&amp;lt;3' => 'icon_heart.png',
               ':bear:' => 'icon_bear.png',
               ':star:' => 'icon_star.png',
                  '(w)' => 'icon_wordpress.png',
                  '(W)' => 'icon_wordpress.png',        
            );
        }
        
        if (count($wpsmiliestrans) == 0) {
            return;
        }
    }
    

    But why don’t they all show up in my comments section? Where’s the martini!? I also upgraded my plugin SSL Grins with an ‘easter egg’ of code that hides anything in this array of smiled_hide. This works on both my version of the smilies plugin and Avryl’s. and looks like this:

    $smiled_hide = array("bear", "wordpress", "martini", "developer", "whiterussian", "burrito","icon_bear.gif", "icon_wordpress.gif", "icon_martini.gif", "icon_developer.gif", "icon_whiterussian.gif", "icon_burrito.gif", "icon_bear.png", "icon_wordpress.png", "icon_martini.png", "icon_developer.png", "icon_whiterussian.png", "icon_burrito.png", "icon_bear.svg", "icon_wordpress.svg", "icon_martini.svg", "icon_developer.svg", "icon_whiterussian.svg", "icon_burrito.svg");
    

    Now this is possibly the jankiest, stupidest, code I’ve written in a while. I’d rather just have the words be there, and filter “If any of the values in this array is a partial match to the name of the smilie we’re looking at right now, don’t show it.” But I’m not clever enough with arrays and preg matching at this point, so I did that ugly list, and used this:

    if (!in_array($grin, $smiled) && !in_array($grin, $smiled_hide) ) {...}
    

    So at this point, pull requests are welcome because I’d love to clean that up!

  • Bad Browser Complacency

    Bad Browser Complacency

    Back in the day, you may have seen notices on browsers like “This site best viewed in Internet Explorer v4.” Since then, we’ve moved into the belief that a website should work on as many browsers as possible, and degrade nicely when it can’t. So imagine my surprise when I’m looking at photos online and I get a message saying I’m using an unsupported browser.

    I happened to be using Chrome on my iPad, so I clicked the link which took me to http://www.corbisimages.com/BadBrowser and I saw this:

    Bad Browser

    I was taken aback. Not that they say ‘IE 7 and up’ as it’s something I try to support as well. Frankly making sites look awesome on IE is about as easy and fun as a dental student doing your root canal. You’ll get there in the end, but it may hurt like hell.

    Now, Corbis has certainly one of the more out of date designs for a photo sites I regularly visit (there are 10), but it’s not the most egregious. Yes, there are worse ones. Still for a site to have an alert like this in 2014 and to omit Chrome is rather shocking. Someone remarked it looked like that site was designed circa 2003 and Chrome, if you didn’t know, only came out in 2008. So while I remember this new design for Corbis being rather recent (2012 or 2013, but that may have just been some tweaks), it’s clear they’ve not visited that page in at least six years.

    I talked to my family about web design at a recent brunch, stressing that I do not do website design per se, but I am happy to help them find people and upload their content. At that time, I pointed out that the trick to a website was to frequently update it and make it more modern. “It’s like the runway shows,” I replied. “What’s in this season was weird last season and may be out by next season. So making a site and never changing it is as smart as never updating your wardrobe.”

    Older fashion, not that good looking todayPeople judge by how things look. If someone only wears a black turtleneck and jeans (Steve Jobs), we create a specific mindview of them and it rarely changes. Someone who always wears avant-garde clothes that are nearly unwearable (Katy Perry), we create another. If that person always wears a suit jacket (Tim Gunn), we have yet another view. Neither is right or wrong, of course, and they all have their places.

    We update our wardrobes when we gain and lose weight, when we decide we want a change, when we feel different, when we have to change, when we want to. While I tease that Brian Gardner is never satisfied with a web design and is always changing, I’m often just as guilty of this as I don’t feel things fit forever. If I’m not afraid of changing my wardrobe, why would I be afraid of changing my website?

    And yet. We worry a lot more about the change of design, to the point that sites like Corbis haven’t significantly changed or adapted since 2002, when the site was born. Since then, 12 years have gone by, browsers have changed, security changed, and the viewing experience is wildly different. Corbis on a phone? Yeah not a great experience.

    When your site never changes with the times, never grows to adapt to it’s new audience, you lose respect in the world of the Internet. We have to keep up with the times, test and retest on as many browsers as humanly possible, and make sure that it all works. We can’t just say “Yes, this one design is good” and more so, we can’t say “This site works best on…” anymore.

    Unless you’re the sort to say “This jeans only work with turtlenecks.” Then, by all means, never change.

  • You Are The Weakest Link

    You Are The Weakest Link

    I sit by people who are on the phone with customers about their accounts all day. Each and every day I hear them talk to customers who are past due or need to activate a new credit card or had an account closed by not paying. In general, I marvel at how consistently nice these coworkers of mine are, considering the number of times I hear people screaming at them. But I also get to hear some fairly impressive conversations.

    Locked safeMost of the time, the conversations are mild, a reminder that you actually have to pay, here’s how you pay, off you go. But once in a while you get to hear the tale of someone who wants to cancel an account. This is only interesting because we don’t cancel your account for you. You have to log in and cancel the charges and billing. About once a day, someone asks why we can’t just accept they are who they say they are and close the account, and I hear my coworker explain over and over that it’s not secure. We can’t verify you over the phone, we called you, and… well there’s a reason you have to call your bank and not the other way around.

    Recently I had a credit card jacked, causing me to miss a payment I didn’t know I owed. I was called by a bill collector after 60 days and they asked for my account information. I balked and asked what card he was calling about, what was the amount, when was it charged, and so on. Then I hung up (I tried to tell him thank you, he kept talking) and called the card company directly. They confirmed the situation, I explained it wasn’t me, we got the bill reversed, everyone was happy… except me. I pointed out having some random number call me and claim to represent them was not safe or secure. They agreed, and also remarked that I shouldn’t have had a collection agency after me at only 60 days, so clearly they had a billing problem.

    I’m a little thoughtful about my security, if you can’t tell. So when I read my friend Gary’s story about Paypal’s lack of security, it surprised me. There’s no true Two Factor authentication on something that has access to my bank account, just a dongle I’d have to pay for (and keep handy) or SMS. And when you read more into why Gary turned on SMS (see the story about how @N lost his user name and $50k), it gets more disturbing.

    Social engineering to figure out passwords and pose as other people is easy. I do it all the time when I need to set up something for myself and my wife, and the company says she has to call too. I happen to have all of her information, down to access to her email (after all, I’m her sysadmin), and we actually made a specific joint email address for things like our bank account. If you have the information, it’s not hard to do.

    Chains around a railingWe can blame GoDaddy and Paypal all we want for this. Should they accept the last four digits of my credit card as identification? Should they accept my social security number? What about my password (which means they can read it, by the way), or what about a special password used only for verification? Now I have to remember more, carry more, and know more all the time. It’s information overload. And because of that, because we’ve complained, they do less.

    People see our credit cards all the time. You handed your debit card to someone to pay your eye-doctor’s co-pay, or for that latte. We tweet about our first pets and mother’s maiden names, and we Facebook everything. It’s pretty obvious that the weakest link in security, and the reason social engineering can easily exploit them with companies, is us.

    There isn’t a perfect way to protect ourselves, though. Last year my phone got wiped and I lost my Google Authenicator settings. I had secondary login codes for Google itself, but not WordPress.com (I’d never set them up) so I was unable to log in. After skyping and emailing two of my good friends who work there, I was able to get back in, but had they not been able to know it was me, what could have happened?

    Every time someone asks me what I do to be safer online, I tell them this “I am working to eradicate my ability to be stupid.”

  • Save Bacon With ModSecurity

    Save Bacon With ModSecurity

    Earlier this month, my company DreamHost had a small snafu with ModSecurity. The tl;dr is that we had a typo and it stopped some people from being able to access or properly use Jetpack. Thankfully, the WordPress community (including everyone at Jetpack, whom I owe drinks and/or dinner) is filled with amazeballs awesome people who helped us figure out everything and sort out customers who, upon getting what appeared to be a Jetpack error, went there when they needed to go to DreamHost.

    Water hook up for a firetruckThese things happen. Code isn’t perfect, people aren’t perfect, and everyone makes mistakes. Of course, on the internet it’s unreasonable to assume a legit gaff, and I’ve seen people call out “Why was DreamHost pushing out these tweaks?” and “Didn’t they test?” so I thought perhaps it was time to explain why we use Mod Security and why, even though it’s my nemesis, I like it a lot.

    What is ModSecurity anyway?

    ModSecurity (aka modSec or mod_sec) is an open source web application firewall (WAF). That means it sits between your website and the world, blocking all the bad people. When we have those brute force attacks, ModSecurity is key in blocking them. It blocks people who attempt code injection attacks like this:

    http://www.example.com/wp-login.php?username=admin'">DROP%20TABLE%20wp_users--
    

    Now that would never work on WordPress core, but the Bobby Tables attacks have the potential to kill your site if you have a plugin or theme that’s insecure. Most hosts have customized their rules to check for things like hitting the wp-login page improperly or passing through credentials directly. That means if someone tries to log in to your site without clicking the submit button (yes, you can code that), it will block them.

    One of my favorite things about ModSecurity is that you can hook it into another firewall like ConfigServer, Fail2ban, or even the built in linux feature of IPTables, and block any IP that routinely trips your security rules.

    So why was DreamHost monkeying with it anyway?

    Every host is constantly monkeying with ModSecurity. As attack patterns grow and change, your host has to adapt. There’s a team at pretty much every host on the planet who watches logs, studies them, and improves the ModSecurity rules. Heck, we even share our rules with other hosts when the situation calls for it, like that Brute Force attack back in 2012. It was brand new, we were all surprised at the aggressiveness, and we quickly shared information.

    On any given week, your host is creating new rules and testing them in their dev environment, or on specific real servers that are designated “Go ahead, blow me up.” After all, we all know nothing beats real-world testing. And if push came to shove and one specific site was being hammered, we may push an experimental rule to them before we’re done testing everything, because it’s that or your site is down.

    We’re always working and improving. Security is a moving target after all.

    How come a typo slipped through?

    If you can find me someone who makes a 100% perfect product every single time, I’ve got a bridge for you to buy. We tested everything we could think up, and interestingly enough, that Jetpack error didn’t impact all Jetpack users! We have a test box, with Jetpack, and it worked fine there. Go figure.

    Flame from a laternBut I’ve often said your website is a pretty snowflake. It’s unique, and what you do with it is different from what everyone else does. Things I have and do on this server and this domain are wildly different from my other sites on this same server! The need for the site is different, and what it uses is different, so what it does when it communicates with the world? Different.

    I’ve had days where one domain is acting like a prat, but the others are fine. And I’ve sat there thinking “But it’s the same on these domains! They’re on the same server for God’s Sack!” only to realize that the usage pattern of the sites were very much not the same. And that takes everything longer to fix because you have to narrow things down over and over until you actually find out what the heck you did wrong.

    I can’t even tell you this will never happen again because I’m pretty sure someone will make a mistake again sometime in the future.

    Conclusion?

    I wouldn’t run a site without ModSecurity, but there are options.

    In February 2013, Zero Science Lab released a study comparing it to Incapsula and Cloudflare. While ModSecurity came out on top (though it was noted to be more aggressive and caused more false positives), Incapsula has been working hard to fix it’s issues. There was actually a Round 2: Incapsula vs Cloudflare study in October 2013, and in this one, Incapsula is the clear winner. Of note, you won’t get the WAF protection on either for free.

    The studies say, to me, that if you’re master of your own domain and want the firewall on your server to run yourself, use ModSecurity. If you’re going to farm that security out to the cloud, use Incapsula. There are, of course, benefits to putting the firewall on the cloud, and the major one is that you’ll be spared high CPU since the processing of the naughty people is done on their server, not yours. But of course, if they go down, you’re at risk, so you should probably have ModSecurity anyway.

    After all, your website is important, right?