Archive for the ‘Uncategorized’ Category

Google +1 Chrome extension tracks your https traffic

Thursday, November 3rd, 2011

EDIT: In a response to this post on Google+, Louis Gray says that he’s notified the team. I’ll update this post as I get more information.

The Google +1 extension for the Chrome browser sends an RPC event to Google for every page you visit, https or not.

I hate to be a downer on cool stuff like this, but I really don’t think this is acceptable. It’s even sending the querystring, which could potentially contain a secure session token. All of the communication to the Google servers happens over https, but I don’t think that excuses this. https:// traffic needs to be off-limits for auto-tracking like this.

I’d be OK if the button allowed you to disable auto-reporting of the current +1 count (this can default to ‘on’), and added a default-off option to show +1 counts for https sites.

Below is a screenshot of the RPC request sent to Google’s RPC endpoint, showing the https URL of a bank’s login URL, complete with query-string.

My Interview with Neal Stephenson on the Mongoliad

Wednesday, September 1st, 2010

Neal Stephenson’s latest interactive serial novel project, The Mongoliad, launched last night at midnight. Readers subscribe to the project to receive access to the new material as it becomes available and can interact with fellow readers in the forums. They can also contribute to the book world’s ‘pedia, a wiki focused on events and characters within the story.

I had a chance to ask Neal some questions about the project:

MM: How has the format and the collaboration between yourself and the other authors of the Mongoliad affected the creative process you use for writing?

NS: The most obvious difference, of course, is that this one is collaborative, and so I have the opportunity to throw ideas around with other writers and enjoy the creative and frequently funny discussions that arise during those meetings. The whole medieval-knights-in-armor thing has, of course, been gone over pretty thoroughly by other writers dating at least as far back as Cervantes and Shakespeare, and so you might think we would be discouraged by the existing body of literature on that topic. On the contrary, though, we have been harvesting a lot of energy from our perception that we are able to produce a new twist on the theme.

As far as format is concerned, one of the big differences is that we are able to offload a certain amount of exposition and background material to ‘pedia entries and other material on the site. Normally when writing a novel that is set in an alternate world (fantasy, sf, or historical) a certain amount of energy is drained away worrying about how to incorporate that sort of explanatory content into the prose without bringing the story to a dead stop. In this project we can just keep telling the story and then supply the background in whatever way seems best; the reader can then delve into it as much or as little as it pleases them.

MM: Will the serial story of the Mongoliad end up as a book?

NS: Oh yes, we are all serious book lovers and so it won’t be a real finished project in our minds until we have seen it between the covers of a traditional printed book.

MM: Since the works of the Mongoliad aren’t permanently fixed in type, would you or other authors of the project ever consider reworking a chapter based on feedback from the community?

NS: You have hit on one of the great advantages of this format. The traditional drawback of serialized fiction is that there is no way to go back to chapter 1 and change something that might make chapter 35 much better. With this system we can simply update the chapter and push the new version out to the subscribers’ devices. We have already taken advantage of that to produce several successive rewrites of the chapter in which Haakon fights Zug in the arena.

MM: The Mongoliad is going to be a social experience. When people interact with the Mongoliad, do you expect they will be interacting as themselves with their real names, as themselves behind an alias or as a “role-play” character?

NS: At the moment it’s a discussion forum in which people log in under persistent identities that we assume match up, more or less, to their true identities. The possibility of role playing suggests a more gamelike milieu, and we are definitely thinking about games, but we don’t have anything up and running yet.

MM: At Dorkbot-SF, Jeremy mentioned that the book may evolve according to feedback from the community, or potentially adopt certain bits of well-written fan-faction to varying degrees. How will the project deal with copyright and attribution in the case where material may bubble up from the community?

NS: I’m going to leave that one to Jeremy but the general answer is that if we notice someone who has a knack for fan fiction we’ll probably strike a deal with them that will cover the intellectual property transaction in a way that is clean and mutually understood.

MM: The Mongoliad is experienced and produced differently than existing books today and gives us a hint of what the future of reading may be. What would your ideal world of publishing be 20 years from now- the writing process, the publishing model and the technology used by readers?

NS: We’re trying to build toward that ideal world with this project, and our vision of it changes a little every day as we learn new things. Any future in which people do a lot of reading and writers are able to support themselves by writing seems like a good future to me!

MM: A few days ago, the Oxford English Dictionary’s owner stated that it would likely no longer be printed again. What do you think will happen to the printed word over the next few decades?

NS: With devices such as the Kindle and the iPad doing so well, it seems that the printed word is adapting itself quite well to the electronic world, and so I am actually much more optimistic about this than I was a few years ago before such devices were invented. There is clearly a market for long-form, fully immersive experiences of a sort that only literature can provide, and the fact that such material can be generated by a single person working alone with virtually no equipment means that experimentation is easy and that a colossal range of different themes and experiences can always be made available to readers. The only cause for concern, in my mind, is that writers will go broke as the result of people violating their copyrights, but we hope that we can find a business model in PULP that will make it a no-brainer for readers to subscribe, and show their appreciation for their favorite writers by sending a little bit of coin their way.

MP James Moore calls opponents of Bill C-32 “radical extremists”

Wednesday, June 23rd, 2010

Apparently he denied this remark in messages to Michael Geist (and the video posted on conveniently omits it):

Balanced Copyright for Canada’s daily astroturfing points

Friday, June 18th, 2010

I signed up for a Balanced Copyright for Canada account to see what sort of astroturfing points they had in their “Daily Action Items” section. My account was deleted shortly after taking these screenshots.

You can see that they instruct their members to swarm any anti-Bill-C32 articles as well as engaging anyone who retweets them. Members are instructed to support any pro-Bill-C-32 articles or comments.

While the screenshots here are copyrighted by the owner of, I believe that I have a fair dealing defence for publishing them here for analysis.

The Purpose of the Dealing Is it for research, private study, criticism, review or news reporting? It expresses that “these allowable purposes should not be given a restrictive interpretation or this could result in the undue restriction of users’ rights.” In particular, the Court gave a “a large and liberal interpretation” to the notion of research, stating that “lawyers carrying on the business of law for profit are conducting research”.

First impressions of Safari’s Extensions

Tuesday, June 8th, 2010

First quick impressions of Safari extensions:

  1. Close enough to Chrome extensions that it won’t take much to port something over. (good)
  2. Settings API is interesting. I missed the point originally, but apparently Safari will build you a settings page from these. Will probably work for simple settings, but not sure if it’ll scale.
  3. Different API for buttons/context menus, but no real winner in terms of API design.
  4. Really don’t like having to get a certificate from Apple to develop. Regardless of Apple’s policies, this is the first browser that you need central approval to deploy to (not IE, Firefox, Chrome or Opera needed it).
  5. No solution provided to build from command-line (we had to hand-roll one for Chrome too). Browser vendors need to get their act together here.
  6. The extension builder is a strange experience: you need to drop files in the directory, then head back to the builder to update things.

I can’t imagine it’ll take us longer than a few days to port the DotSpots extension from Chrome to Safari. It’ll take a while for us to integrate this into our automated build process though.

unrEVOked: painless EVO root teaser

Wednesday, June 2nd, 2010

UPDATE: Sprint just pushed an OTA update for these phones that may patch the root hole we’re using. Don’t install any OTA updates yet if you want root!

We (ozzeh, joshua, shadowmite and I) just put the teaser site together for the EVO root. More info coming soon!, Twitter: @unrevoked

Painless root for your HTC EVO 4G.

The sorry state of Avira anti-virus heuristics

Wednesday, March 17th, 2010

UPDATE (July 7, 2010) Daniel Herding sent me a story about his adventures with Avira’s latest version. Looks like they’ve just paved over the problem.

We’ve been seeing a number of reports that our DotSpots Chrome extension is being reported as infected with the HTML/Crypted.Gen malware. There’s not a lot of information on Avira’s site about this malware, except that it’s a ‘trojan’ with ‘low damage potential‘.

I previously submitted a sample of the false positive which solved the problem until we pushed out a new version of our code. Since we can’t submit each of our builds ahead of time to Avira for approval, I had to spend some time figuring out exactly what was causing them to think our code was malicious.

I started by downloading a trial version of their anti-virus product. Immediately after restart, it detected the HTML/Crypted.Gen malware in the Chrome extension that was already installed. I extracted the script from the extension to my desktop and it continued to pop up infection warnings on the file. Now that I had a reliable reproduction case, I could start working on narrowing down what triggered the alert.

I loaded up the file in my trusty analysis tool, Notepad. Starting from the original file, I deleted large swaths of code until it was no longer detected as a virus, then restored those pieces and deleted smalled chunks. Eventually I reduced it down to a couple of lines, which were then reduced down to a few strings of characters. At the end, a file with only a few hundred characters would trigger the signature:


Aside: my original set of pattern strings included “nodeValue” rather than “eval”. The patterns are all case-insensitive and don’t ensure matches happen on JS token boundaries. When I went character-by-character to simplify the triggers further, I discovered that it was the ‘eVal’ in ‘nodeValue’ causing issues.

When I create a file with those six strings in it on a website, Avira will attempt to block the download. This appeared to be the most specific components of the signature. Putting those keywords into Google, I found a few references to the malware it detected. The malicious script seems to construct an iframe from an array of characters, then inserts it into the document to download malware from a third-party site.

Unfortunately, these keywords also end up in the compiled Javascript of nearly every Google Web Toolkit application, giving Avira anti-virus users false-positives when viewing many of these applications.

I posted a report to the GWT contributor Google Group with my findings. I had expected that since I posted the offending signature in the message, Avira would warn me that the web page I was reading was malicious. It didn’t.

I ran the message page through the same process that I used to figure out what triggered the signature, this time looking for the smallest piece of text that disables detection of the virus. It turns out that this text is the phrase google. So, the heuristic looks for the presence of the six character strings above, but also the absence of the word Google.

It’s a little disappointing to see how poorly this anti-virus product implements heuristic detection of this particular scripting pattern. It was trivial for me to figure out the pattern. I could have worked around any number of ways- by adding whitespace to the array of zeros, using Math['min'], or String['from' + 'CharCode'], all of which breaks this pattern recognition. Having the phrase ‘google’ disable detection of the virus made my job even easier. It’s possible that there are a set of other safewords that do the same thing. If I were writing malware or viruses, I’d definitely spend time altering it to work around this sort of heuristic.

Considering that the risk of false positives is so high (and users might be trained to ignore other, potentially valid virus warnings), I’d say that users are worse off with this virus definition than they are without.

You can find me on twitter as @mmastrac

A decade and three blogging platforms later

Sunday, March 14th, 2010

Looking back through the history of, I realized that I’ve used three off-the-shelf products to blog over the last decade: CityDesk, Typo (a Ruby blog engine) and WordPress.

My favorite of the three was CityDesk. It was a very simple CMS with a decent custom scripting engine. Its big disadvantages were 1) that its data was stored in a Microsoft Access database 2) its data was basically a big binary blob that didn’t work well at all with source control, 3) I couldn’t push stuff into it from the command-line (ie: various testing snippets that I like to save) and 4) the scripting language was too limited at times to do what I wanted.

Typo was a great engine, but terribly slow on my webhost, 1&1. A few years in I managed to accidentally delete the .htaccess file that configured the Ruby magic and couldn’t get it working again.

WordPress is both fast and stable, but I find that it’s near-impossible to customize it as I like, not being terribly experienced with PHP.

I’ll probably be migrating off WordPress to something a little more custom in the next few weeks. I’d like to go through my entire blog history (from 1998 to present) and put it into a single, source-controlled repository that I can use going forward.

I reserve the right to remove some of the more embarrassing posts from the Internet entirely, however. :)


Tuesday, March 9th, 2010

I’ve been searching for a complete EBNF for XML 1.1 without much success. I found one for XML 1.0, but I was hoping to avoid manually patching it for the XML 1.1 changes.

In the end, I decided that it would be easiest to just parse the EBNF directly out of the specification. Here it is, for reference:

[1] document ::= prolog element Misc* ) - ( CharRestrictedChar Char* )
[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]
[3] S ::= (#x20 | #x9 | #xD | #xA)+
[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
[5] Name ::= NameStartChar (NameChar)*
[6] Names ::= Name (#x20 Name)*
[7] Nmtoken ::= (NameChar)+
[8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
[9] EntityValue ::= '"' ([^%&"] | PEReferenceReference)* '"'
|  "'" ([^%&'] | PEReferenceReference)* "'"
[10] AttValue ::= '"' ([^<&"] | Reference)* '"'
|  "'" ([^<&'] | Reference)* "'"
[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
[15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
[16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
[17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
[18] CDSect ::= CDStart CData CDEnd
[19] CDStart ::= '<![CDATA['
[20] CData ::= (Char* - (Char* ']]>' Char*))
[21] CDEnd ::= ']]>'
[22] prolog ::= XMLDecl Misc* (doctypedecl Misc*)?
[23] XMLDecl ::= '<?xml' VersionInfo EncodingDeclSDDeclS? '?>'
[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
[25] Eq ::= S? '=' S?
[26] VersionNum ::= '1.1'
[27] Misc ::= CommentPIS
[28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>' [VC: Root Element Type]
[WFC: External Subset]
[28a] DeclSep ::= PEReferenceS [WFC: PE Between Declarations]
[28b] intSubset ::= (markupdeclDeclSep)*
[29] markupdecl ::= elementdeclAttlistDeclEntityDeclNotationDeclPIComment [VC: Proper Declaration/PE Nesting]
[WFC: PEs in Internal Subset]
[30] extSubset ::= TextDeclextSubsetDecl
[31] extSubsetDecl ::= markupdeclconditionalSectDeclSep)*
[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) [VC: Standalone Document Declaration]
[39] element ::= EmptyElemTag
STag content ETag [WFC: Element Type Match]
[VC: Element Valid]
[40] STag ::= '<' Name (S Attribute)* S? '>' [WFC: Unique Att Spec]
[41] Attribute ::= Name Eq AttValue [VC: Attribute Value Type]
[WFC: No External Entity References]
[WFC: No < in Attribute Values]
[42] ETag ::= '</' Name S? '>'
[43] content ::= CharData? ((elementReferenceCDSectPICommentCharData?)*
[44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' [WFC: Unique Att Spec]
[45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>' [VC: Unique Element Type Declaration]
[46] contentspec ::= 'EMPTY' | 'ANY' | Mixedchildren
[47] children ::= (choiceseq) ('?' | '*' | '+')?
[48] cp ::= (Namechoiceseq) ('?' | '*' | '+')?
[49] choice ::= '(' ScpS? '|' Scp )+ S? ')' [VC: Proper Group/PE Nesting]
[50] seq ::= '(' ScpS? ',' Scp )* S? ')' [VC: Proper Group/PE Nesting]
[51] Mixed ::= '(' S? '#PCDATA' (S? '|' SName)* S? ')*'
| '(' S? '#PCDATA' S? ')' [VC: Proper Group/PE Nesting]
[VC: No Duplicate Types]
[52] AttlistDecl ::= '<!ATTLIST' S Name AttDefS? '>'
[53] AttDef ::= S Name S AttType S DefaultDecl
[54] AttType ::= StringTypeTokenizedTypeEnumeratedType
[55] StringType ::= 'CDATA'
[56] TokenizedType ::= 'ID' [VC: ID]
[VC: One ID per Element Type]
[VC: ID Attribute Default]
| 'ENTITY' [VC: Entity Name]
| 'ENTITIES' [VC: Entity Name]
| 'NMTOKEN' [VC: Name Token]
| 'NMTOKENS' [VC: Name Token]
[57] EnumeratedType ::= NotationTypeEnumeration
[58] NotationType ::= 'NOTATION' S '(' SName (S? '|' SName)* S? ')' [VC: Notation Attributes]
[VC: One Notation Per Element Type]
[VC: No Notation on Empty Element]
[VC: No Duplicate Tokens]
[59] Enumeration ::= '(' SNmtoken (S? '|' SNmtoken)* S? ')' [VC: Enumeration]
[VC: No Duplicate Tokens]
[60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED'
| (('#FIXED' S)? AttValue) [VC: Required Attribute]
[VC: Attribute Default Value Syntactically Correct]
[WFC: No < in Attribute Values]
[VC: Fixed Attribute Default]
[WFC: No External Entity References]
[61] conditionalSect ::= includeSectignoreSect
[62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' [VC: Proper Conditional Section/PE Nesting]
[63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>' [VC: Proper Conditional Section/PE Nesting]
[64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
[65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
[66] CharRef ::= '&#' [0-9]+ ';'
| '&#x' [0-9a-fA-F]+ ';' [WFC: Legal Character]
[67] Reference ::= EntityRefCharRef
[68] EntityRef ::= '&' Name ';' [WFC: Entity Declared]
[VC: Entity Declared]
[WFC: Parsed Entity]
[WFC: No Recursion]
[69] PEReference ::= '%' Name ';' [VC: Entity Declared]
[WFC: No Recursion]
[70] EntityDecl ::= GEDeclPEDecl
[71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
[72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
[74] PEDef ::= EntityValueExternalID
[75] ExternalID ::= 'SYSTEM' S SystemLiteral
| 'PUBLIC' S PubidLiteral S SystemLiteral
[76] NDataDecl ::= S 'NDATA' S Name [VC: Notation Declared]
[77] TextDecl ::= '<?xml' VersionInfoEncodingDecl S? '?>'
[78] extParsedEnt ::= TextDeclcontent ) - ( CharRestrictedChar Char* )
[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* /* Encoding name contains only Latin characters */
[82] NotationDecl ::= '<!NOTATION' S Name S (ExternalIDPublicIDS? '>' [VC: Unique Notation Name]
[83] PublicID ::= 'PUBLIC' S PubidLiteral

Google News is Testing a New Layout

Sunday, February 14th, 2010

I was surprised a few days ago with a new layout for Google News on one of the machines I use. I haven’t seen it reported anywhere yet. I came across it tonight while testing and grabbed a few screen captures in case it disappears.

The biggest change is that each story now has a bordered box around it and the stars introduced recently have been moved to the right-hand side of the story. Each story has a drop-down menu associated with it, but the only option in there is “Email”. This drop-down has the class “share-icons” – possibly a new location for a “share in reader/buzz” option.

Looking through the DOM, it appears that this is called the new “blended” story style.

Here’s a couple of screenshots: