storytelling

While lately I’ve been endlessly streaming the latest news with horrified fascination, this morning my calendar unexpectedly popped up a reminder set over a year ago… Today is the fifteenth anniversary of my big-league blogging debut on the Internet Explorer Team’s blog.

My first post there, “A HTTP Detective Story” remains one of my favorites. Sadly, its topic feels all too familiar: a website took a dependency upon a browser quirk, the Referer and User-Agent headers were critical elements of the repro, and I used Fiddler to root-cause the problem. I’ve learned (and shared) so much more about these topics over the last fifteen years, and I appreciate the readers who’ve followed me from the IEBlog to IEInternals (237 posts) to Telerik’s Fiddler blog (41 posts) to my book, to this, my newest blog, TextSlashPlain (189 posts and counting!).

Here’s to learning and sharing for the next 15 years!

With gratitude,

-Eric

While I do most of my work in an office, from time to time I work on code changes to Chromium at home. With the recent deprecation of Jumbo Builds, building the browser on my cheap 2016-era Dell XPS 8900 (i7-6700K) went from unpleasant to impractical. While I pondered buying a high-end Threadripper, I couldn’t justify the high cost, especially given the limited performance characteristics for low-thread workloads (basically, everything other than compilation).

The introduction of the moderately-priced (nominally $750), 16 Core Ryzen 3950X hit the sweet spot, so I plunked down my credit card and got a new machine from a system builder. Disappointingly, it took almost two months to arrive in a working state, but things seem to be good now.

The AMD Ryzen 3950X has 16 cores with two threads each, and runs around 3.95ghz when they’re all fully-loaded; it’s cooled by a CyberPowerPC DeepCool Castle 360EX liquid cooler. An Intel Optane 905P 480GB system drive holds the OS, compilers, and Chromium code. The key advantage of the Optane over more affordable SSDs is that it has a much higher random read rate (~400% as fast as the Samsung 970 Pro I originally planned to use):

Following the Chromium build instructions, I configured my environment and set up a 32bit component build with reduced symbols:

is_component_build = true
enable_nacl = false
target_cpu = "x86"
blink_symbol_level = 0
symbol_level = 1

Atop Windows 10 1909, I disabled Windows Defender entirely, and didn’t do anything too taxing with the PC while the build was underway.

Ultimately, a clean build of the “chrome” target took just under 53 minutes, achieving 33.3x parallelism.

While this isn’t a fast result by any stretch of the definition, it’s still faster than my non-jumbo local build times back when I worked at Google in 2016/2017 and used a $6000 Xeon 48 thread workstation to build Chrome, at somewhere around half of the cost.

Cloud Compilation

When I first joined Google, I learned about the seemingly magical engineering systems available to Googlers, quickly followed by the crushing revelation that most of those magic tools were not available to those of us working on the Chromium open-source project.

The one significant exception was that Google Chrome engineers had access to a distributed build system called “Goma” which would allow compiling Chrome using servers in the Google cloud. My queries around the team suggested that only a minority of engineers took advantage of it, partly because (at the time) it didn’t generate very debuggable Windows builds. Nevertheless, I eventually gave it a shot and found that it cut perhaps five minutes off my forty-five minute jumbo build times on my Xeon workstation. I rationalized this by concluding that the build must not be very parallelizable, and the fact that I worked remotely from Austin, so any build-artifacts from the Goma cloud would be much further away than from my colleagues in Mountain View.

Given the complexity of the configuration, I stopped using Goma, and spent perhaps half of my tenure on Chrome with forty-five minute build times[1]. Then, one day I needed to do some development on my Macbook, and I figured its puny specs would benefit from Goma in a way my Xeon workstation never would. So I went back to read the Goma documentation and found a different reference than I saw originally. This one mentioned a then unknown to me “-j” command line argument that tells the build system how many cloud cores to use.

This new, better, documentation noted that by default the build system would just match your local core count, but when using Goma you should instead demand ~20x your local core count– so -j 960 for my workstation. With one command line argument, my typical compiles dropped from 45 minutes to around 6.

::suitable_meme_of_wonder_and_fury::

Returning to Edge

I returned to Microsoft as a Program Manager on the Edge team in mid-2018, unaware that replatforming atop Chromium was even a possibility until the day before I started. Just before I began, a lead sent me a 27 page PDF file containing the Edge-on-Chromium proposal. “What do you think?” he asked. I had a lot of thoughts (most of the form “OMG, yes!“) but one thing I told everyone who would listen is that we would never be able to keep up without having a cloud-compilation system akin to Goma. The Google team had recently open-sourced the Goma client, but hadn’t yet open-sourced the cloud server component. I figured the Edge team had engineering years worth of work ahead of us to replicate that piece.

When an engineer on the team announced two weeks later that he had “MSGoma” building Chromium using an Azure cloud backend, it was the first strong sign that this crazy bet could actually pay off.

And pay off it has. While I still build locally from time to time, I typically build Chromium using MSGoma from my late 2018 Lenovo X1 Extreme laptop, with build times hovering just over ten minutes. Cloud compilation is a game changer.

The Chrome team has since released a Goma Server implementation, and several other major Chromium contributors are using distributed build systems of their own design.

I haven’t yet tried using MSGoma from my new Ryzen workstation, but I’ve been told that the Optane drive is especially helpful when performing distributed builds, due to the high incidence of small random reads.

-Eric

[1] This experience recalled a much earlier one: my family moving to Michigan shortly after I turned 11. Our new house featured a huge yard. My dad bought a self-propelled lawn mower and my brother and I took turns mowing the yard weekly. The self-propelled mower was perhaps fifteen pounds heavier than our last mower, and the self-propelling system didn’t really seem to do much of anything.

After two years of weekly mows from my brother and I, my dad took a turn mowing. He pushed the lawn mower perhaps five feet before he said “That isn’t right,” reached under the control panel and flipped a switch. My brother and I watched in amazement and dismay as the mower began pulling him across the yard.

Moral of the story: Knowledge is power.

Prelude

In late 2004, I was the Program Manager for Microsoft’s clipart website, delivering a million pieces of clipart to Microsoft Office customers every day. It was great fun. But there was a problem– our “Clip of the Day” feature, meant to spotlight a new and topical piece of clipart every day, wasn’t changing as expected.

After much investigation (could the browser itself really be wrong?!?), I wrote to the IE team to complain about what looked like bugs in its caching implementation. In a terse reply, I was informed that the handful of people then left on the browser team were only working on critical security fixes, and my caching problems weren’t nearly important enough to even look at.

That night, unable to sleep, I tossed and turned and fumed at the seeming arrogance of the job link in the respondent’s email signature… “Want to change the world? Join the new IE team today!

Gradually, though, I calmed down and reasoned it through… While the product wasn’t exactly beloved, everyone I knew with a computer used Internet Explorer. Arrogant or not, it was probably accurate that there was nothing I could do with my career at that time that would have as big an impact as joining the IE team. And, I smugly realized that if I joined the team, I’d get access to the IE source code, and could go root out those caching bugs myself.

I reached out to the IE lead for an informational interview the following day, and passed an interview loop shortly thereafter.

After joining the team, I printed out the source code for the network stack and sat down with a red pen. There were no fewer than six different bugs causing my “Clip of the Day gets stuck” issue. When my devs fixed the last of them, I mentioned this and my story to my GPM (boss’ boss).

Does this mean you’re a retention risk?” Tony asked.

Maybe after we fix the rest of these…” I retorted, pointing at the pile of paper with almost a hundred red circles.

No one in the world loved IE as much as I did, warts and all. Investigating, documenting, and fixing problems in Internet Explorer was a nearly all-consuming passion throughout my twenties. Internet Explorer pioneered a broad range of (mostly overlooked) innovations, and in rediscovering them, I felt like one of the characters on Lost — a castaway in a codebase whose brilliant designers were long gone. IE9 was a fantastic, best-of-its-time browser, and I’ll forever be proud of it. But as IE9 wound down and the Windows 8 adventure began, it was already clear that its lead would not last against the Chrome juggernaut.

I shipped IE7, IE8, IE9, and IE10, leaving Microsoft in late 2012, shortly after IE10 was finished, to build Fiddler for Telerik.

In 2015, I changed my default browser to Chrome. In 2016, I joined the Chrome Security team. I left Google in the summer of 2018 and rejoined the Microsoft Edge team, and that summer and fall I spent 50% of my time rediscovering bugs that I’d first found in IE and blogged about a decade before.

Fortunately, Edge’s faster development pace meant that we actually got to fix some of the bugs this time, but Chrome’s advantages in nearly every dimension left Edge very much in an underdog status. Fortunately, the other half of my time was spent working on our (then) secret project to replatform the next version of our Edge browser atop the open-source Chromium project.

We’ve now shipped our best browser ever — the Chromium-based Microsoft Edge. I hope you’ll try it out.

It’s with love that I beg you… please let Internet Explorer retire to the great bitbucket in the sky. It’s time. It’s been time for a long time.

Burndown List

Last night, as I read the details of yet another 0-day security bug in Internet Explorer, I posted the following throwaway tweet, which netted a surprising number of interactions:

I expected the usual slew of “Yeah, IE is terrible,” and “IE was always terrible,” and “Somebody tell my {boss,school,parents}” responses, but I didn’t really expect serious replies. I got some, however, and they’re interesting.

Shared Credentials

Internet Explorer shares a common networking stack (WinINET) and Cookie Jar (for Intranet/Trusted sites) with many native code applications on Windows, including Windows Explorer. Tim identifies a scenario where Windows Explorer relies on an auth cookie being found in the WinINET cookie jar, put there by Internet Explorer. We’ve seen similar scenarios in some Microsoft Office flows.

Depending on a cookie set by Internet Explorer might’ve been somewhat reasonable in 2003, but Vista/IE7’s introduction of Protected Mode (and cookie jar partitioning) in 2006 made this a fragile architecture. The fact that anything depends upon it in 2020 is appalling.

Thoughts: I need to bang on some doors. This is depressing.

Certificate Issuance

Developers who apply digital signatures to their apps and server operators who expose their sites over HTTPS do so using a digital certificate. In ideal cases, getting a certificate is automatic and doesn’t involve a browser at all, but some Certificate Authorities require browser-based flows. Those flows often demand that the user use either Internet Explorer or Firefox because the former supports ActiveX Controls for certificate issuance, while Firefox, until recently, supported the Keygen element.

WebCrypto, now supported in all modern browsers, serves as a modern replacement for these deprecated approaches, and some certificate issuers are starting to build issuance flows atop it.

Thoughts: We all need to send some angry emails. Companies in the Trust space should not be built atop insecure technologies.

Banking, especially in Asia

A fascinating set of circumstances led to Internet Explorer’s dominance in Asian markets. First, early browsers had poor support for Unicode and East Asian character sets, forcing website developers to build their own text rendering atop native code plugins (ActiveX). South Korea mandated use of a locally-developed cipher (SEED) for banking transactions[1], and this cipher was not implemented by browser developers… ActiveX again to the rescue. Finally, since all users were using IE, and were accustomed to installing ActiveX controls, malware started running rampant, so banks and other financial institutions started bundling “security solutions” (aka rootkits) into their ActiveX controls. Every user’s browser was a battlefield with warring native code trying to get the upper hand. A series of beleaguered Microsoft engineers (including Ed Praitis, who helped inspire me to make my first significant code commits to the browser) spent long weeks trying to keep all of this mess working as we rearchitected the browser, built Protected Mode and later Enhanced Protected Mode, and otherwise modernized a codebase nearing its second decade.

Thoughts: IE marketshare in Asia may be higher than other places, but it can’t be nearly as high as it once was. Haven’t these sites all pivoted to mobile apps yet?

Reader Survey: Do you have any especially interesting scenarios where you’re forced to use Internet Explorer? Sound off in the comments below!

Q&A

Q: I get that IE is terrible, but I’m an enterprise admin and I own 400 websites running lousy websites written by a vendor in a hurry back in 2004. These sites will not be updated, and my employees need to keep using them. What can I do?

A: The new Chromium-based Edge has an IE Mode; you can configure your users so that Edge will use an Internet Explorer tab when loading those sites, directly within Edge itself.

Q: Uh, isn’t IE Mode a security risk?

A: Any use of an ancient web engine poses some risk, but IE Mode dramatically reduces the risk, by ensuring that only sites selected by the IT Administrator load in IE mode. Everything else seamlessly transitions back to the modern, performant and secure Chromium Edge engine.

Q: What about Web Browser Controls (WebOCs) inside my native code applications?

A: In many cases, WebOCs inside a native application are used to render trusted content delivered from the application itself, or from a server controlled by the application’s vendor. In such cases, and presuming that all content is loaded over HTTPS, the security risk of the use of a WebOC is significantly lower. Rendering untrusted HTML in a WebOC is strongly discouraged, as WebOCs are even less secure than Internet Explorer itself. For compatibility reasons, numerous security features are disabled-by-default in WebOCs, and the WebOC does not run content in any type of process sandbox.

Looking forward, the new Chromium-based WebView2 control should be preferred over WebOCs for scenarios that require the rendering of HTML content within an application.

Q: Does this post mean anything has changed with regard to Internet Explorer’s support lifecycle, etc?

A: No. Internet Explorer will remain a supported product until its support lifecycle runs out. I’m simply begging you to not use it except to download a better browser.

Footnotes

[1] The SEED cipher wasn’t just a case of the South Korean government suffering from not-invented-here, but instead a response to the fact that the US Government at the time forbid export of strong crypto.

In Windows 10 RS5 (aka the “October 2018 Update”), the venerable XSS Filter first introduced in 2008 with IE8 was removed from Microsoft Edge. The XSS Filter debuted in a time before Content Security Policy as a part of a basket of new mitigations designed to mitigate the growing exploitation of cross-site scripting attacks, joining older features like HTTPOnly cookies and the sandbox attribute for IFRAMEs.

The XSS Filter feature was a difficult one to land– only through the sheer brilliance and dogged persistence of its creator (David Ross) did the IE team accept the proposal that a client-side filtering approach could be effective with a reasonable false positive rate and good-enough performance to ship on-by-default. The filter was carefully tuned, firing only on cross-site navigation, and in need of frequent updates as security researchers inside and outside the company found tricks to bypass it. One of the most significant technical challenges for the filter concerned how it was layered into the page download pipeline, intercepting documents as they were received as raw text from the network. The filter relied evaluating dynamically-generated regular expressions to look for potentially executable markup in the response body that could have been reflected from the request URL or POST body. Evaluating the regular expressions could prove to be extremely expensive in degenerate cases (multiple seconds of CPU time in the worst cases) and required ongoing tweaks to keep the performance costs in check.

In 2010, the Chrome team shipped their similar XSS Auditor feature, which had the luxury of injecting its detection logic after the HTML parser runsdetecting and blocking reflections as they entered the script engine. By throttling closer to the point of vulnerability, its performance and accuracy is significantly improved over the XSS Filter.

Unfortunately, no matter how you implement it, clientside XSS filtration is inherently limited– of the four classes of XSS Attack, only one is potentially mitigated by clientside XSS filtration. Attackers have the luxury of tuning their attacks to bypass filters before they deploy them to the world, and the relatively slow ship cycles of browsers (6 weeks for Chrome, and at least a few months for IE of the era) meant that bypasses remained exploitable for a long time.

False positives are an ever-present concern– this meant that the filters have to be somewhat conservative, leading to false-negative bypasses (e.g. multi-stage exploits that performed a same-site navigation) and pronouncements that certain attack patterns were simply out-of-scope (e.g. attacks encoded in anything but the most popular encoding formats).

Early attempts to mitigate the impact of false positives (by default, neutering exploits rather than blocking navigation entirely) proved bypassable and later were abused to introduce XSS exploits in sites that would otherwise be free of exploit (!!!). As a consequence, browsers were forced to offer options that would allow a site to block navigation upon detection of a reflection, or disable the XSS filter entirely.

Surprisingly, even in the ideal case, best-of-class XSS filters can introduce information disclosure exploits into sites that are free of XSS vulnerabilities. XSS filters work by matching attacker-controlled request data to text in a victim response page, which may be cross-origin. Clientside filters cannot really determine whether a given string from the request was truly reflected into the response, or whether the string is naturally present in the response. This shortcoming creates the possibility that such a filter may be abused by an attacker to determine the content of a cross-origin page, a violation of Same Origin Policy. In a canonical attack, the attacker frames a victim page with a string of interest in it, then attempts to determine that string by making a series of successive guesses until it detects blocking by the XSS filter. For instance, xoSubframe.contentWindow.length exposes the count of subframes of a frame, even cross-origin. If the XSS filter blocks the loading of a frame, its subframe count is zero and the attacker can conclude that their guess was correct.

In Windows 10 RS4 (April 2018 update), Edge shipped its implementation of the Fetch standard, which redefines how the browser downloads content for page loads. As a part of this massive architectural shift, a regression was introduced in Edge’s XSS Filter that caused it to incorrectly determine whether a navigation was cross-origin. As a result, the XSS Filter began running its logic on same-origin navigations and skipping processing of cross-origin navigations, leading to a predictable flood of bug reports.

In the process of triaging these reports and working to address the regression, we concluded that the XSS Filter had long been on the wrong side of the cost/benefit equation and we elected to remove the XSS Filter from Edge entirely, matching Firefox (which never shipped a filter to begin with).

We encourage sites that are concerned about XSS attacks to use the client-side platform features available to them (Content-Security-Policy, HTTPOnly cookies, sandboxing) and the server-side patterns and frameworks that are designed to mitigate script injection attacks.

-Eric Lawrence

I rejoined Microsoft as a Principal Program Manager for the web networking team on June 4th, 2018.

TravellogForward

June2018

 

Spoiler alert

If you haven’t read For a Lark yet, please go read that first.

 


What If?

I like to think.

Well, actually, I’m not sure I like to think, but I find it really hard to relax and let my brain rest… given a few minutes of idle time, I usually find myself deep in thought about some random nonsense. One topic that I’ve gone back to for years is thinking of vignettes to write in my years-overdue memoir, which started as a pleasant diversion into nostalgia but now haunts me with its incompleteness as I continually fail to translate those thoughts into text. But nevertheless, I still love to write and when I play with the thought experiment “What if I was born a hundred years ago? Or a hundred years from now, what would I do for a living?” I often come up with “I’d write, if I could make a living at it.”

I spend a lot of time thinking about “What if” scenarios, most of which you wouldn’t consider remotely interesting.

Bitcoin, however, is interesting, and I keep coming back to “What if…” questions about it.

My boss at Telerik was almost obsessed with Bitcoin back in 2014 and finally I ended up buying six Bitcoins just so I’d feel slightly invested in the topic and might manage to avoid rolling my eyes when he talked excitedly about it.

Screen Shot 2017-12-06 at 10.03.49 AM

I watched Bitcoin’s price float around through 2014 and 2015. A blog post published in January 2016 by one of the early Bitcoin developers persuaded me to sell five of my six Bitcoins at a small profit (I recouped what I paid for the six, effectively keeping the last coin “for free”).

I later decided that perhaps I’d sold prematurely, but not having enough “play money” to buy another Bitcoin in July of 2016, I instead bought twenty Ethereum, a new and more exotic cryptocurrency which had recently started trading on Coinbase.

Screen Shot 2017-12-06 at 10.16.11 AM

After watching it grow, I bought Litecoin almost as soon as it became available on Coinbase, buying 20 at just under $20 each.
Screen Shot 2017-12-06 at 10.19.43 AM

Over time, I increased my holdings a bit, swapping between the coins and cashing out as they appreciated to recover my initial USD investments. So, at this point, my coin holdings are pure, unrealized profit.

Screen Shot 2017-12-06 at 10.21.52 AM

Almost 40 grand worth, assuming that I cash them out before they crash. And crashing seems almost certain, considering the underlying nature of the currencies. Bitcoin is a venture-capital backed ponzi scheme, a legal casino open 24/7/365 and as close as your nearest mobile phone or tablet. It’s also pretty terrible for the environment.

But that doesn’t make Bitcoins any less fun from a “What if” perspective. I recently found myself thinking about what I’d’ve done if I had any inkling of the eventual price of Bitcoins back in 2010. I quickly settled on the idea of giving out small gifts of 100 BTC to everyone I knew. To minimize taxes, I’d have to give out the coins when they were without value, and somehow prevent the recipient from cashing them out too early. 100 BTC seemed like a good amount, where recipients would be ecstatic but not crippled by their sudden wealth.

It’s too easy when playing “What if” to imagine some trivial change (“Aluminum was priced 15% lower in 1935”) spiraling into the root cause of World War III, or whatever, but I think the Bitcoin story is interesting in how little impact it would’ve had globally– a few people would get a bit richer, but beyond their immediate circles, nobody would even necessarily know it had happened.

Eventually, I decided I’d write up the idea as a short story, changing the amount to 1000 BTC to make things more interesting and perhaps somewhat less believable. I wrote it from the point-of-view of a recipient, because the story isn’t very interesting from the perspective of the giver.

Random factoids:

  • Bitcoin has appreciated 160 million percent since “David” bought or mined his coins in the summer of 2010.
  • If the recipient of the gift had sold it as soon as Coinbase started trading in 2013, they’d reap a windfall of $13300 and be overjoyed at receiving such a wonderful gift.
  • Sales in the following years would be similarly joyful.
  • That joy would likely turn to crippling dismay or horror as the price rose to $11M when the story-teller opened the card last week. Or, $12.5M today.
  • Bitcoin profit would be taxed at the long-term capital gains rate, meaning recipients selling today would clear a cool $10 Million after taxes.
  • The Bitcoin Pizza account tracks the value of the 10000 bitcoins an early user spent on two pizzas; currently around $120M. An early Bitcoin buyer who forgot he’d bought 5000 coins spent a fifth of his Bitcoin on an apartment in 2013; that Bitcoin has appreciated about 14x since then.
  • “David” in my story is an amalgamation of a few engineers I worked with at Microsoft; Dave is a super-smart guy who’s into all sorts of geeky projects, Christine went to Africa to work with the Peace Corps, and Herman left to go do a startup in San Francisco.
  • My wife, reading the story, deemed it implausible. “Why?” I asked. “Because in the story you cleaned the garage not once, but twice!” she retorted.

After publishing the story, I got a few kind words about it being a nice story, but it seemed that not everyone recognized it as fiction. I later realized that my blog theme displays a post’s “Tags” but not its “Categories”, so the post didn’t show up with the storytelling category. However, some of the reactions were so interesting that I decided not to explicitly correct anyone. Most reactions were of the form “Wow, congrats” which I deemed ambiguous (maybe they liked the story?).

A few people asked whether it was fact or fiction. An early direct message hit upon one of the themes I was trying to convey with the story:

If that article is real, congrats! Amazing story either way, draws parallels to what planting a small seed or a small act of kindness can flourish into. I think about things like that every time I get to help newer folks learn new tech like git. And seeing what things they do later always makes me proud that I might have had a part in what they’ve accomplished

But overall, there were very few comments, even from people who believed the story was true. Only one person (a Microsoft colleague) asked “which David was the gift giver,” and no one asked about the fate of the other gifts David was handing out. I was amused at the idea that people who know me would think I’d casually announce on Twitter that I was suddenly worth over ten million dollars. Nobody asked for money.

Nobody asked what I’d do with the money. While I’d probably brainstorm a million ideas, I think reality would turn out to be pretty boring. Why? When Telerik acquired Fiddler, my offer came with what seemed like a comically small number of stock options at an absurdly high price. When I asked, no one was willing to tell me how many shares the non-public company had issued, what fraction my stake might represent, or when the company might go public. I then naturally valued the options at zero (which is approximately how much I made from options when hired at Microsoft) and ignored them for years. Then, Telerik got acquired by Progress at the end of 2014 and my options were bought out for a bit over half what I paid for my house. I came home and that night I asked my wife “Hey, remember those worthless options? Well…” and eagerly awaited her reaction and the inevitable brainstorming of what we’d do with the sudden windfall. Ultimately, we bought a case of our favorite wine and put the remainder into savings.

-Eric

 

Happy Holidays” David said as he poked his head into my office, handing me an unwrapped holiday card featuring a kitten in a Santa hat. As I took it, I nearly dropped a small white envelope that dropped out from inside. The inscription in the card read simply “Best wishes, David – 2010.”

Uh, thanks, you too!” I replied, both surprised and a bit uncomfortable that my colleague had gotten me a card. We were friendly but not friends. We’d only worked together a few times over the prior year, and it would’ve never occurred to me to get him anything for Christmas. He seemed like an archetypal geek, so we shared an interest in technology and science fiction, but we didn’t hang out or anything like that. Fortunately, he had a stack of cards in his hands, so it wasn’t like I’d been singled out or anything. Hoping he hadn’t gotten me anything fancy, I asked “What’s this?” as I flipped over the rigid envelope. In small print near the flap, it read “Do not open until Christmas 2017.”

His eyes twinkled and he grinned mischievously, an expression I’d never seen from him before. “Just a tiny gift. Well, maybe sort of a test. It’s very important that I give it to you now. But if you open it before 2017, it’ll be the crummiest gift you ever got. If you can wait, maybe it’ll be pretty nice.

I furrowed my brow. “So, like some sort of Savings bond thing?” I asked, thinking back to the bonds I’d gotten from far-off relatives as a little kid… I’d recently stopped dragging them around from apartment to apartment and taken them to the bank to collect the princely sum of $261, two decades after I’d ungratefully wished they were some action figures or a book instead.

David smiled. “Sure, sorta. Don’t lose it. Don’t get it wet. And don’t open it early!

“Uh, I won’t… Thanks?” I promised, and with that, David disappeared into Rob’s office next door to start his spiel all over.

Weird. Well, I’d already bought my direct reports gift cards for the IPic movie theatre and I had one extra left over… I’ll put that in a New Year’s card for David and leave it in his office sometime next week, I resolved. I tossed the card and envelope into the stack of RFC printouts on my bookshelf and went back to the email I was writing, hoping to get everything squared away before leaving for a short Christmas vacation.

The envelope sat on my bookshelf undisturbed, buried in an ever growing pile of paper. I might’ve remembered it the following year, but David had left the company that summer, off to do a volunteer tour with the Peace Corps before joining some startup out in San Francisco. Still buried in a pile of paper when I left the company two years later, the card made its way into an unsorted moving box labeled “office stuff” as we moved across the country to Texas. It then sat quietly in the box in my garage for five more years.

In the summer of 2017, I finally got around to digging through the garage, trashing what I could in an effort to make way for the growing proliferation of tricycles, big wheels, wagons, bikes, and pool toys that our two Texas-born children had collected. I spent a quiet Saturday afternoon in July mired in nostalgia, poring through boxes full of old books and papers and remembering a life before kids and so many responsibilities.

When I eventually uncovered the kitten card in the pile, I snorted and stretched to toss it in the “Recycle” pile before I remembered the weird little envelope. Sure enough, it was still inside, forgotten and untouched for the better part of a decade. I ignored the admonition of the faded green warning and tore it open, long-forgotten curiosity mounting.

The envelope contained a pile of papers folded in thirds. The outermost of these was a cleanly cut sheet of wax paper of the sort that was used for sandwiches back before ziplock bags took over the world. Odd, I mused as I discarded it. The next was a folded sheet of thick white cardstock, taped closed, which bore a short paragraph printed in Christmas-colored ink. It read simply:

Is it Christmas 2017 yet?

If so, happy holidays! Enjoy your present.
If not, please google ‘Marshmallow experiment’ and wait patiently.
You’ve been warned.

I paused as the marshmallow reference tickled something in my memory … some university lecture I’d forgotten long ago? Mildly annoyed, I dragged out my phone and searched as instructed. Oh yeah, that Stanford study about delayed gratification. It’s not like anyone will ever know… I mused as I put down my phone and started to peel back the tape holding the cardstock shut.

The door to the garage opened. “Nap’s over, Nate’s up.” my wife called, and I tossed the letter back in the box, eagerly grabbing the large pile of recycling I’d generated to show her my progress. Dancing around, building lego cars, and wrestling with my two kids, I completely forgot about David’s weird little present for another few months.

In December, off work for a two week winter holiday vacation, I resolved to finish cleaning out the garage. Thirty minutes into the job, I came across the card. I tore open the cardstock. Inside lay a single laser-printed page with a letter printed on one side. The opening paragraph read:

Happy holidays, friend!

I hope you’ve waited patiently for this small gift and aren’t too annoyed at the oddity of its presentation, but it’s all for a purpose.

My accountant has instructed me to make it very clear that this is a GIFT, granted freely without any restrictions, from me to you on December 17th, 2010. It has an approximate market value of $250. Relax– it only cost me about 8 bucks, and it may well be worthless by the time you open it. (Market value is only possibly important for tax purposes) 

Beneath the card was a black and white picture, one inch square, full of smaller squares, the sort of bar code you’ll find on the back of shampoo bottles.

code

The letter continued and I read on, confused but intrigued.

This is a QR code containing the private key for a digital wallet containing bitcoin. Bitcoins are a virtual currency that I’ve been playing with this year, and I thought it would be a lark to give some out as a present. (I’m not clever at picking presents– growing up, I got a new leather wallet every year for Christmas.)

Perhaps in 2017 bitcoins have become worthless (that seems like the most likely outcome), but I have a hunch that perhaps they’ll continue to appreciate over the years. If you’ve been patient, maybe it’s enough to buy you a nicer present now.

If so, happy holidays! If not, I hope my folly brings you at least a chuckle. :)

My heart started to pound in my chest. The page concluded with David’s signature, preceded by 7 hand-scrawled characters.

1000 BTC

Hands shaking with the instant weight of the letter, I dropped it and the universe entered slow motion as the paper fluttered to the ground.