Hacker News new | past | comments | ask | show | jobs | submit login
"@" on Twitter (twitter.com)
504 points by isp on Apr 27, 2018 | hide | past | web | favorite | 137 comments

Slightly related but very interesting: the 2010 Twitter bug where simply tweeting "Accept [username]" would automatically force them to follow you.

My understanding is that for the sake of simpler interfaces such as SMS, which they let hold the whole service back for a long long time, they had a "follow [username]" feature - and if the person had to approve follow requests, it would send one to them. To accept the request, you just sent "accept [username]" and the follow would happen. However, they never actually checked that a request had ever been sent before allowing you to accept it, allowing you to simply force anyone to follow you with a single tweet.

Next time you make a seemingly obvious mistake, don't feel too bad. Even Twitter did it.


Facebook had this bug as far as accepting group requests very early on, maybe around 2010. Early enough that groups were limited to your college.

I wrote a script to accept invitations to every group ID from 1 to 10000. It even added me to groups that didn't exist yet, presumably just adding my ID and the group ID to a table. So when someone created a group to rant about me being in all their groups, I was in it and, as the first member, an admin.

Facebook fixed the bug when I reported it and first kicked me out of my legitimate groups, then fixed that too, though they didn't pay bounties then.

> So when someone created a group to rant about me being in all their groups, I was in it and, as the first member, an admin.

fucking hilarity

gave me a hearty laugh too wp OP

“Move fast and break things” lol

A similarly lulzy but much more sinister-looking bug happened at Facebook, where an index into an array of users was mistakenly treated as a user id, so the message intended for user 4 in the array ended up going to the user with ID 4, aka zuck.

another facebook doozy was their "view my profile as <user>" feature. Apparently for some time after that it was released, when you used it view your profile, you could interact with facebook as <user>; including chatting as them, reading their messages, etc.

but then, I've had my share of turrible bugs too, so i'm not here to poke fun.

That sounds like a pretty PHP-specific bug.

Downvoters: most programming languages don’t silently convert strings (i.e., usernames) to array indices. Even Python doesn’t do this. While this particular bug probably wouldn’t be possible in most other languages, I’m only commenting because it’s rare and amusing to see bugs that are so language specific. I’m not making a generic “lol PHP” joke.

Both array indices and user IDs are numbers.

And it's certainly possible in Python to accidentally use a map as a list or vice versa, if the map has integer keys.

JavaScript does.

  var arr = ["one", "two", "three"];
  arr["2"] === "three"; // true

JavaScript object property keys are always strings, so technically it’s `arr[2]` that has the 2 coerced to a string.

It's true that object keys are strings, but the array and object situation of JavaScript is quite confusing. Arrays are indexed by numbers, but still accept string indices, leading to behavior like this: https://stackoverflow.com/q/9526860

Actually, that is incorrect. Arrays are different in JavaScript. I don't have time to look up the exact reference, but to get an idea: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

> Arrays cannot use strings as element indexes (as in an associative array) but must use integers. Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's object property collection. The array's object properties and list of array elements are separate, and the array's traversal and mutation operations cannot be applied to these named properties.

I've been bitten by this bug before, PHP's associative arrays are pretty strange compared to other languages.

I find it easier to think of them as an "ordered" hash map rather than an array...


First sentence, “An array in PHP is actually an ordered map.”

I just read at least half that page and this idiotic design confirms exactly why I feel PHP should be considered harmful

I don't think it's harmful. You just need to know what you're doing. PHP gets a bad rep round here unfairly. It's actually a very useful language which has proven itself over and over again in the wild. I wonder what you think of JavaScript?

It's harmful exactly because it's ridiculously complex. And because it forces a Map/Dict to conform to an Array/List protocol, making it actually worse than both (it loses the O(1) or O(N) access time of the array/list, plus adds a bunch of complexity)

Disagree, it doesn't force anything to be anything else. It is what it is and it's pretty intuitive. PHP never claimed that arrays behave O(C) when accessing members†. It actually reduces complexity because there's only one container type. "Harmful" is ridiculous hyperbole, that's how the language is designed, you may not like how it's designed but not liking something doesn't make it harmful.

† btw, have you seen this? https://stackoverflow.com/questions/2473989/list-of-big-o-fo... pretty detailed investigation of big-O for PHP arrays

Funny, that was one of the features I really liked about PHP back in the day.

Python doesn’t do any implicit coercion (apart from ints and floats etc), right?

It depends what you mean by coercion. For instance:

  class Foo:
    def __getitem__(self, x):
       return x

  i = iter(Foo())
That works because any object that provides __getitem__ "implements the iterable protocol."[1] I bring up __getitem__ because people familiar with Java are scratching their heads, "not only did you not declare any interfaces, this is just a convention, but there's also an __iter__ method. Huh?"

But interfaces are just one way to declare a type. The question is, did it convert it to a new type?

Well, what type was it before? If you want to talk about LSP[0], you're a bit stuck here since you can't prove anything about a method in python. (And here, we declared its type, and we said nothing about it being iterable or a sequence.) You have to run it because you don't know that a. Foo has __iter__ or __getitem__, b. that they accept the arguments you're going to pass, c. let alone that they're designed to, d. that the object won't simply delete them halfway through.

All that iter() is going to do is look for those methods and make assumptions that if you wrote __getitem__ that you meant it. At which point maybe LSP works, after all, you'll prove that it has that property by running the code and fixing it if it breaks.

But... python nevertheless will nevertheless construct this proxy to use your class based on inspection, which seems an awful lot like coercion to me.

[0]: Quoth Wikipedia: Let 𝜙(𝑥) be a property provable about objects 𝑥 of type T. Then 𝜙(𝑦) should be true for objects 𝑦 of type S where S is a subtype of T.

[1]: https://docs.python.org/3/glossary.html#term-iterable

In Python 2, bytes can be coerced to unicode:

  >>> b'egg' + u'spam'
Unlike the example with bool+int, this can't be justified by LSP.

Well, booleans are integers, so you can do:

    >>> True + 1

  fizzbuzz = lambda n: [print((“fizz” * m % 3 == 0) + (“buzz” * m % 5 == 0) or m) for m in range(n)]
Not sure if this is great or terrible

That's not "coercion", though. That's Python obeying the LSP, because bool is a subclass of int.

I first started using Twitter in the late 2000s and got my friends using it with SMS. We used it similar to a group chat/hangouts.

..it did get annoying after a while.

“Next time you make a seemingly obvious mistake, don't feel too bad. Even Twitter did it.”

There most infamous “mistake”, at least as I see it, was neglecting to backup their database data. That was just unforgivable.

I bet they had a backup, it was just never tested... pretty common mistake

Nope, no backups were even created when Dorsey was in charge: “Oh, and while he was in charge, there was no backup of Twitter’s database.”

From the Fortune article “Let's remember why Jack Dorsey was fired as Twitter's CEO”


what... the fuuuu


At least two usernameless Twitter profiles exist:



(credit: https://twitter.com/FakeUnicode/status/989868697660477440 )

It is possible to retweet-with-quote the tweets, but not to retweet directly or (as far as I can tell) to link to individual tweets directly.

EDIT: It is possible to link to individual tweets. Added links.

The user says (tweet_id 989794618467409920 - https://twitter.com/i/web/status/989794618467409920 ) that there are "many bugs" using the account in various clients.

tweet_id 829989674353573889 ( https://twitter.com/i/web/status/829989674353573889 ) may be my all-time favourite tweet. (A tweet by @, with name @, contents @)

How could such an account have been created?

I asked somebody who used to work there, and the answer I got was that there are a bunch of accounts from back before validation was as tight as it is now.

Which seems reasonable to me. At-replies were not something that Twitter started with, but instead were community-driven with software support added later:


It's a good reminder that it's always easier to relax restrictions than to tighten them.

But then again, if Twitter early on were run by the sort of people who were inclined to lock down everything, it might not have evolved enough to be really useful to people. I hazily remember the Friendster guy getting really mad that people were creating accounts for non-human things that they loved, like cities and bars and companies. I think he went on a banning spree. Instead of saying, "Look how much people love my platform! Let me support them in their efforts."

If I recall correctly, when Google Plus was new and people were excited about it, a whole bunch of companies flocked to the site to set up accounts for their businesses. But Google hadn't launched the "business account" functionality yet, so they banned them all.

I guess Google Plus and Friendster are good examples of how that mindset works out.

Facebook did the same thing.

I remember having to merge multiple "person" Facebook accounts into a single "business" Facebook account for a client once business accounts became available.

It was extra hard not only because FB made the process cumbersome, but because everyone in the company seemed to have taken it upon themselves at some time in the past to create a person account for the business. Sales people, the owner, various marketing people no longer with the company, etc...

Exactly. Shouting, "YOU USERS ARE DOING IT WRONG" rarely accomplishes anything, and misunderstands how business works. The goal isn't to make users do what you imagined they would. It's to find something valuable you can do for users.

Because nobody could conceivably impersonate a business and cause all sorts of legal and PR issues.

That is in the category of "nice problem to have".

Friendster definitely doesn't have that problem, because despite being a pioneering social network, one that existed before MySpace or Facebook, it is now defunct.

Just like nobody could impersonate a person?

That's already a given. We are all, in a way, impersonating other (mostly insufferable) persons.

It does seem surprising that they haven’t contacted the affected users and invited them to change their usernames.

How many programmers have been surprised (pleasantly or not) by unintended/unexpected uses of their code?

Possibly a difference in implementation of unicode between validation and persistence/use. Validates successfully due to one or more "valid" unicode characters -> translated to zero characters due to stripping of invalid unicode character at some point after validation.

Maybe related to MySQL's 3-byte "utf8" charset which doesn't actually support unicode properly? (you are supposed to use "utf8mb4" nowadays though a lot of material still refers to "utf8")

Found this out when someone pushed a git commit message with a 4byte emoji and it broke our CI server -_-

Hard to say without knowing the code, but one common problem is to do something like length checking a username to ensure it is a certain length, and then later stripping out illegal characters.

MVP mania perhaps? You know, the old chestnut about "You have to get the shoddiest, most ethereal, stuck together with sticky tape and chewing gum version of your app out there to get market validation before you do some serious development work on it" ideology that is always being touted in the startup world... It tends to lead to this sort of technical debt.

MVP doesn't necessarily mean a product is buggy. It means a product excludes nice-to-have features that doesn't add immediate value.

Basic validation is something I've always pushed for even for MVPs as that often goes hand in hand with platform security (another thing I still push for in MVPs)

To be honest at least in this case it’s probably worth it. It great to have something delivered so we don’t waste enormous energy on building features no one ends up wanting.

Regex gone bad?

For a while I had my display name (as opposed to @ handle) on Twitter set to the empty string. It didn't cause major issues as far as I could tell, though it would cause some Twitter clients to display my tweets unusually.

I achieved this by entering a greater than symbol (>) in the input field. Twitter presumably tried stripping any HTML tags, which resulted in an empty string. I'm not sure if this still works; they might have fixed that bug. Presumably something similar happened with the accounts that have empty @ handles.

> I achieved this by entering a greater than symbol (>) in the input field. Twitter presumably tried stripping any HTML tags, which resulted in an empty string. I'm not sure if this still works; they might have fixed that bug.

I just tried it and got the following error:

> Name can't include 'invalid characters'

Note how it doesn’t define "invalid characters".

It seems a bit gross when usernames and normal pages are mashed into the same namespace, e.g.


I guess Github does the same:


Reddit has the nice /u/... thing, but I suppose that is a bit awkward when saying URLs out loud.

This is a real problem. It's also a security issue.

One of the reasons why we created this database of huge disallowed usernames: https://github.com/dsignr/disallowed-usernames

I usually just say “u slash username” or “r slash subredditname.” Not terribly awkward.

Especially since it forces you to basically map out your entire site before letting users register accounts. Or you rename users squatting your routes later on, which seems like a terrible idea.

Or, you take advantage of lists like this[0] and make sure users can’t pick names that would be “problematic”.

[0] https://zimbatm.github.io/hostnames-and-usernames-to-reserve...

Ah thanks, I was looking for that earlier and couldn't find it :)

Anecdotally, practically anyone who's part of "US internet culture" of my generation (I'm 28) understands what you mean when you say "arr slash worldnews" and how to navigate there.

Reminds me on the old Commodore 64 Quantum-Link service (former version of AOL), there was a hack called 'Q-Armor' where you could get a username of all spaces, and no sysops or any chat room managers could kick you, or do anything to your account.

For some time you could steal AOL usernames by registering i.e. 'obar' or 'oobar', and using client side hacks could switch the registration to the already registered username 'foobar' which would then belong to you.

This only worked if 'obar' or 'oobar' was unregistered, but it was a pretty nifty way to steal single word usernames, and speaks to some strange validation/truncation somewhere in the code.

people griefing in online games (hacks/aimbots) often run with nicks like ||||||||||II||I|||||||||||||II1111|||||||IIIIIIIIII||||||||||||

In the StarCraft community these are known as "barcode users". They often tend to be professional players on another account, to ensure that they aren't recognised and their opponents can't learn their playstyle.

My friends AIM account back in the day was essentially this. He basically had to find you.

I used to use aim chat booters by a blog named 'esoteric code' program was called subterfuge. Familiar with it by any chance? I thought it was brilliant.

(not downvoting you, but your comment makes no sense at all to me)

Because they couldn't determine how many spaces your username was or because of some other bug?

Presumably because whitespace is stripped between command arguments, so something like "KICK <USERNAME>" would be useless.

Q-Link was great for its time.

That must be Bobby Droptables twitter account :-)

Classic! We named our guild in EQ "NULL", as a joke. People would comment that we had a problem when they saw us running around with "<NULL>" running over our head. It bit us on the ass when someone went to Sony's EQ con one year, and they literally couldn't print out their badge because "your guild name is NULL? Really?"

> they literally couldn't print out their badge

I still don't quite get how this doesn't work. Why are they handling "NULL" as a special case? What's coercing "NULL" into null?

It was due to the way they exported the data. They used a SQL statement, and if you weren’t in a guild then the SQL would produce NULL. That output was then used to generate PDF badges, and it tried to do some filtering for NULL guilds. The person writing that script clearly did not anticipate there actually being a guild named NULL.

NULL or ‘NULL’? There’s a clear and obvious difference there.

Bad coding.

It reminded me of a Wired article from 2015 about a guy with the last name "Null" - https://www.wired.com/2015/11/null/

The modern twist to that seems to be little miss Infinity https://www.reddit.com/r/javascript/comments/8f57i1/psa_ther...

Do I get this right that jQuery, for developer convenience, content-sniffs the value of "data-" attributes?

I.e., if the value looks like JSON, it will parse it and return the object tree, otherwise it will return the original value as a string?

This sounds like a horrible idea in general - I'd say the authors of this forgetting that certain english words by themselves are valid JSON is a nice cherry on top but hardly the worst problem caused by this.

Sort of - there's a jQuery API that does content sniffing called .data(), it's for storing and retrieving arbitrary data on elements. The problem was that they used this API to read from an element where they should have used .attr(), which returns a string.

Now I want to change my name to NaN

you probably don't, if the story about the cars with plates on a variations of "NO PLATE" is any indication https://www.snopes.com/fact-check/licensed-to-bill/

Wow. Problem one: applicant writes "no plate" instead of leaving it blank or writing in a crossed line. Problem two: so do the law enforcement officials! The former is a silly mistake; the latter should be a learning opportunity.

How big is twitter’s engineering department? Their mobile website doesn’t even load the content of the tweet. Yesterday it was throwing an error that the api was rate limited. For their own site! They’ve been systematically destroying their own foundation by alienating the developer community for years and they can’t even get their own product to work reliably.

Mobile Twitter is maybe the single most useless website I’ve ever had to use lol.

Clicking on a link to a tweet has 1/20 chance of ever actually loading the tweet. All other occurrences are evenly split between loading nothing except the top bar and calling it a day, and throwing an error message. Reloading the directly or using the reload button they provide will usually result in the rate limiting message.

I don’t even bother clicking on twitter links anymore. I just hope it worked for someone else and they paste the contents in the comments.

> Mobile Twitter is maybe the single most useless website I’ve ever had to use lol.

Pinterest would be up there too. It's useless if you don't have an account on mobile and desktop.

‘Useless’ isn’t a strong enough word. The way it’s broken Google image search puts it way into negative a value.

Try adding -site:pinterest.com to your search query.

Edit: Just tried it myself, might want to add a -site:pinterest.co.uk as well.

Im amazed googles allowed them to pull those seo tricks so long considering they put the hammer down on ehow with the panda update.

I get that I can exclude results, but it’s a little like “you’re holding it wrong”. On mobile it’s prticularly horrible. Maybe this is exactly what a clipboard manager is for.

I turned off Javascript and it worked fantastically.

Couldn’t agree more. I’ve had to learn to use frameworks like React for work, but I’ll never be a fan. I’ll always be prefer to build websites as simply and close to the metal as I can.

I feel like every week I get another reason to turn JS off.

Really says a lot doesn’t it.

The downside is the (disquietingly common frequency of) sites which return a jumbled mess of incoherent elements or a blank page(!) when Javascript is disabled.

I blame SPA’s.

Nearly impossible to test properly (or was), breaks the whole html model, results in bugs just like this one.

This bug has nothing to do with Twitter's SPA-ness; it's a failed server-side validation.

I've seen the rate limit message a lot. Almost seems like it always happens when there is a Referer header. If you refresh after the error, it usually works. Not sure why they would punish people for linking to tweets...

It's definitely because of the Referer header. It has only happened to me when I am linked to a tweet from somewhere else and refreshing always solves the problem. I think Twitter wants you to download their app instead of using your phone's web browser.

It may be from your cell network's NAT hitting rate limits on their IP.

My network’s NAT is my router in the basement. There is no CGNAT, and yet I hit rate limits. No one else in our house accesses twitter, logging at the router reveals usually one to two attempts of accessing twitter per day.

And yes, rate limits.

... And they literally just have to show you 280 characters. Thank God they are not building flying cars..

And to show you that 280 characters they need to download about 6 kbyte css, 4 kbyte javascript, 17 kbyte Google analytics, 26 kbyte jquery, 1.5 kbyte favicon, and some images... Total about 100 kbytes.

It's almost as if "they literally just have to show you 280 characters" is a bit of an oversimplification.

I think the point they were making was that they do all this extraneous stuff as well: if I’m looking at a single tweet, why on earth does it need to serve that much JS up? Why on earth is it not a simple HTML page with the information on it?

Mobile twitter site is shit, but the real irony here?

Twitter came up with the ui framework "Bootstrap" long ago and it was a game changer for responsive frontend layouts.

Reminds me of some artists who included a script tag in their book title so that when the book got listed on online shops it would make the page spawn a JavaScript alert()

Here's a talk by said artists (sorry about the title) that talks about this and their other work https://media.ccc.de/v/34c3-9278-ecstasy_10x_yellow_twitter_...

In the very early days of Google, searching for $@ or $* or some other shell-sensitive character combos produced strange results.

I never did push it to the point of security exploitation.

I've seen a similar bug in a web forum where someone wondered why "ke$ha" is rendered as "ke". "ke$DB" was quite interesting.

It's a lesson for us to learn when building services that people create accounts on.

There's another one, https://twitter.com/@home. It redirects back to Twitter's home page.

I discovered this while looking for "@home", which is a homeware store.

That will happen for any reserved names where it is used for a page rather than registered by a user. e.g.: http://twitter.com/@search

Michael from Vsauce mentioned this on his Twitter today and mere minutes later @ replied "Hiya!" and I burst out laughing.


I thought it was funny and kind of charming that Vsauce is the single account they follow.

I love how the routing is all borked and you can't properly interact with that account.

So, it seems like it's not possible to view this person's profile (at least on the web app in Safari)?

Also can't retweet them.

Perhaps we should go back to Usenet and IRC?

Simple things are hard to monetize.

Hear, hear! Glory days.

Is product quality degrading on the internet over time?

It used to be that once a week or longer I would find some amusing bug. But now it's not uncommon for that I encounter dozens of bugs daily on various popular services that are worth $millions or $billions, which is just obnoxious. Not only that, but usually the services have no way of filing a bug report or getting in touch with support.

It seems like internet giants are becoming too big for their britches, and also they're forcing each other into this insane cycle of "ship first, fix later" just to stay competitive.

What can we do about this, if anything?

Nothing. It seems the secret to success in software is shipping as fast as possible, and so far the market has proven that users are extremely forgiving of bad quality. And bad security. And hostile privacy practices. Users suck.

Exactly, you could be killing a baby for each HTTP request and they wouldn't care, as long as its useful and don't costs them a dollar.

You probably do more on the internet now. Both spending more time, and also using services that have more functionality. The more functionality there is, the more surface area there is for bugs to sneak in.

You encounter dozens of bugs daily? That doesn’t really pass the smell test.

There are several services I use daily which have bugs I encounter regularly, and have for years - just have to know the workaround. I built some of them :)

Across multiple services 5hat seems right. So much stuff has broken or buggy UI it's not funny.

Consider that the bare minimum for dozens is 24...

There are _a lot_ of ui bugs. I easily hit 24 an hour with some products.

I probably hit at least 24 bugs a day on my phone. Apps crashing. Back not working right. Apps popping up and disappearing. Unexpected latency causing wrong things to be clicked on. They're all just papercuts, but there are so many of them.

Nobody can write perfect software yet, as far as I know. And popular software has a bunch of engineers that need something to do so they often change/add features for no great reason. In the process they add/change/remove bugs.

So, did the devs programming the username field forget to sanitize text input, or were they just working without a spec? Neither scenario would be particularly surprising.

This XKCD[1] to my mind.

[1] https://xkcd.com/1963/


Another case in the land of per client validation handled differently and mostly incorrectly.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact