Login with root and no password on any mac running macOS High Sierra

This tweet is currently making rounds on Twitter:

And yes, that actually works: enter root as a username, leave the password empty, and *BOOM* you’re in.

The exploit also works at the login screen, and with remote management (Screen Sharing, etc).

UPDATE 2017.11.29: Apple has released a security update, fixing this nasty bug. Open AppStore.app and check the updates section to download it. No reboot required.

As Mattias detailed a root with no pass gets created upon testing this. Awaiting a security patch from apple you can lock this user down by explicitly setting a password for its account (using Terminal.app):

sudo passwd -u root

If you’re not too fond of the shell, follow the instructions from this video.

And to say Apple already had a huge security slip-up with that Disk Utility Bug which showed the password instead of the password hint but this one is much, much worse … #functionalhighground aye?

Elsewhere , , , , Leave a comment

Better Cross-Platform React Native Components

Good article by Nick Wientge on correctly creating Cross-Platform React Native Components:

In this post we’ll look at some tools and techniques we can use to make our components look right at home on both iOS and Android — without sacrificing code reuse.

The article revolves around building a button, but with respect for how each platform (Android vs. iOS) works, regarding:

  • Typography
  • Iconography
  • Styling and Theming
  • Touchable Interactions

Better Cross-Platform React Native Components →

Elsewhere , , Leave a comment

End-to-end Tests that Don’t Suck with Puppeteer

Good introduction to using Puppeteer for your e2e tests:

One of the most popular tools for e2e testing is Selenium, which is a tool for automating web browsers. Selenium sounds cool in theory: write one set of tests that run on all browsers and devices, woohoo! Jk. In practice, Selenium tests are slow, brittle, and costly. So, on Ropig we are using Puppeteer – the official headless Chrome library.


We are using Jest as our test runner, but you can use any testing tools you want with Puppeteer.

An example test would be this:

test('can create new user account', async () => {
    await page.goto(routes.public.register);
    await page.waitForSelector('[data-testId="userAccountForm"]');
    await page.click('[data-testId="userRegisterInputWithEmail"]');
    await page.type(user.email);
    await page.click('[data-testId="userRegisterInputWithPassword"]');
    await page.type(user.password);
    await page.click('[data-testId="userAccountSubmitButton"]');
    await page.waitForSelector('[data-testId="userSettingsForm"]');

Yes, you better get your async/await mojo on for this 😉

End-to-end Tests that Don’t Suck with Puppeteer →

Elsewhere , , , Leave a comment

“A-Frame Tutorials” Video Series

Alexandra Etienne has published a 7-part video series on working with A-Frame on YouTube:

A-Frame is a framework for building rich 3D experiences on the web. It’s built on top of three.js, an advanced 3D JavaScript library that makes working with WebGL extremely fun. The cool part is that A-Frame lets you build WebVR apps without writing a single line of JavaScript (to some extent). You can create a basic scene in a few minutes writing just a few lines of HTML.

A-Frame Tutorials →

Elsewhere , , Leave a comment

Dynamically import ES modules with “dynamic import()

One of the recent ECMAScript proposals that landed in Chrome 63 is dynamic import():

Dynamic import() introduces a new function-like form of import, which allows one to import on demand. It returns a promise for the module namespace object of the requested module, which is created after fetching, instantiating, and evaluating all of the module’s dependencies, as well as the module itself.

Say you have a lightbox or dialogbox. You could offload its importing to the very moment it is needed:

button.addEventListener('click', async (event) => {
    try {
        const dialogBox = await import('./dialogBox.mjs');
    } catch (error) {
        // …

Note that we’re using await here, as it’s better than the typical promise code which uses .then().

Google Developers: Dynamic import()

Elsewhere , , 3 Comments

TIP: Enable Two Factor Authentication (2FA) with your NPM account

Since early October it’s possible to enable Two Factor Authentication with your NPM account.

2FA is another layer of defense for your account, preventing third parties from altering your code even if they steal or guess your credentials. This is one of the easiest and most important ways to ensure that only you can access to your npm account.

To enable it, run npm profile enable-2fa with one of these two options:

  1. auth-only: enable it for any login attempt
  2. auth-and-writes: enable it for any login attempt, publish event, profile change, etc.

Once enabled use an authentication application like Google Authenticator or Authy to generate your One-Time-Password.

Additional security measurements announced along with 2FA is the possibility to have read-only tokens — useful for all your CI/CD needs.

Note that NPM 5.5.1 or higher is required.

Protect your npm account with two-factor authentication and read-only tokens →
NPM: Using Two Factor Authentication →

Elsewhere , , Leave a comment

Strava Global Heatmap

Strava has released a Global Heatmap powered by Mapbox GL, plotting all locations where their users go run / go cycle / do water activities / do winter activities.

The raw input activity streams data comes from a Spark/S3/Parquet data warehouse. This data includes every one of the 3 trillion GPS points ever uploaded to Strava. Several algorithms clean up and filter this data.


The full global heatmap was built across several hundred machines in just a few hours, with a total compute cost of only a few hundred dollars.

I like the fact that it’s possible to filter on activity type, revealing some hotspots like Wielercentrum Eddy Merckx for cycling, and the adjacent Watersportbaan and Blaarmeersen for running in Gent.

Strava Global Heatmap →
Strava Engineering: The Global Heatmap, Now 6x Hotter →

Elsewhere , , , Leave a comment

SQIP – SVG-Based Image Placeholder

In an in-depth analysis on how Medium loads up their images, José M. Pérez explains how their “blur-up technique” works:

  1. Display a resized version of the original at the original size, with a blur filter on top to hide the artifacts.
  2. Load in the bigger one.
  3. Once the big version is loaded, replace the small image with the big one.

Now, at Medium they don’t just swap out the small image for the big one, but animate between the two. For this they render everything on a <canvas> element. The author of the post has recreated the animation using CSS filters:

See the Pen Reproducing Medium loading image effect by José Manuel Pérez (@jmperez) on CodePen.

In a follow-up post on using SVGs as placeholders he researches how SVGs can be used as placeholders.

Now I must say his self-made results aren’t that satisfying … the jump between the lo-res SVG and the original is too big. What caught my eye in said article however, is the mention of SQIP which yields some very – very – nice results:

It makes use of Primitive to generate a SVG consisting of several simple shapes that approximate the main features visible inside the image, optimizes the SVG using SVGO and adds a Gaussian Blur filter to it. This produces a SVG placeholder which weighs in at only ~800–1000 bytes, looks smooth on all screens and provides an visual cue of image contents to come.

# Generate a SVG placeholder and print an example <img> tag to stdout
sqip input.jpg

# Save the placeholder SVG to a file instead of printing the <img> to stdout
sqip -o output.svg input.jpg

# Customize the number of primitive SVG shapes (default=8) to influence bytesize or level of detail
sqip -n 4 input.jpg

There’s also a Node implementation available.

SQIP – SVG-Based Image Placeholder →

UPDATE 2017.12.03: There’s an article available over at perfplanet on how to combine SQIP with the Intersection Observer.

Elsewhere , , , , Leave a comment

JSON5 – JSON for Humans

JSON isn’t the friendliest to write. Keys need to be quoted, objects and arrays can’t have trailing commas, and comments aren’t allowed — even though none of these are the case with regular JavaScript today.

JSON5 is a proposed extension to JSON that allows these kinds of things. Here’s an example showcasing most of its features:

    foo: 'bar',
    while: true,

    this: 'is a \
multi-line string',

    // this is an inline comment
    here: 'is another', // inline comment

    /* this is a block comment
       that continues on another line */

    hex: 0xDEADbeef,
    half: .5,
    delta: +10,
    to: Infinity,   // and beyond!

    finally: 'a trailing comma',
    oh: [
        "we shouldn't forget",
        'arrays can have',
        'trailing commas too',

Note that the JSON5 proposal is in no way official (technically a new MIMEType is required), and – I fear – most likely won’t get that much adoption/traction with things like YAML already floating around…

JSON5 JS Parser →
JSON5 PHP Parser →

Elsewhere , Leave a comment

Accessing a tweet using only its ID (and without the Twitter API)

Today I learned that Twitter totally ignores the username in the “tweet detail route” on their website. This allows you to view details of a (public) tweet when knowing only its ID, without needing to access the Twitter API (which is the default geeky approach I was first going to take).

Twitter’s tweet detail route has the form of https://twitter.com/{userName}/status/{tweetId}. When passing in a tweetId with a non-matching/invalid userName, the Twitter website will automatically redirect to the URL with the correct userName

Example: To see the contents of the tweet with id 932586791953158144 just visit https://twitter.com/anyuser/status/932586791953158144 and you’ll be redirected to its actual URL: https://twitter.com/bramus/status/932586791953158144

Handy 😊

Elsewhere , Leave a comment