On the Security Implications of Suggested Snippets in TextExpander

August 21, 2015

Synopsis

Suggested snippets in TextExpander 5.0 and 5.1 are stored in plain text and synchronize to the cloud and other devices in kind. This may be unexpected given the current wording of the “Privacy Details” section of the help file (below). This may seem harmless, but if not configured carefully to exclude certain apps (e.g., Terminal, iTerm 2, Emacs) then TextExpander may unintentionally save passwords you type as suggested snippets, which then are stored in plain text and will propagate to the cloud and other devices. I contacted Smile support about this, since I thought it must be a bug or an oversight given what I read in the documentation. They kindly clarified the behavior and indicated that they will consider updating the documentation or adding an FAQ entry to address these points. Read more below for additional background, suggested configuration changes, and details on how to remove any such sensitive information that may have been stored in Dropbox as a result.

Background and Details

TextExpander from Smile is a Mac (and iOS) application that allows one to define short abbreviations for longer words and phrases. A TextExpander “snippet” consists of an abbreviation, content (the full-text associated with the abbreviation), and rules about how and when the abbreviation can be used. TextExpander then watches what you type and when an abbreviation is noticed it automatically replaces the abbreviation with the content, provided that the rules are satisfied.

This is only a basic description the program. More advanced snippets can include date and time arithmetic, scripts, fill-in forms with drop-down menus and optional sections, etc. Because of this, TextExpander is one of a core set of utilities that I install on every Mac I work on (and every iOS device).

Snippet Suggestion

TextExpander 5.x Preferences: Snippet Suggestion
TextExpander 5.x Preferences: Snippet Suggestion

In TextExpander 5.0, released in May 2015, Smile added a new feature called “Suggestions” whereby TextExpander will automatically suggest new snippets based on things you frequently type. This raises obvious privacy and security concerns, which are addressed as follows in the TextExpander 5.1 documentation:

Privacy Details

TextExpander observes your keystrokes, as well as the contents of the pasteboard when you Paste using ⌘V.

TextExpander will track how many times you repeat the same group of characters and create a new suggestion after a certain amount of repetition. However, it does not save the tracking of what you type so the tracking is lost with each TextExpander restart. Therefore, frequent restarting of TextExpander won’t result in many suggestions. None of what you type is saved by TextExpander except for the snippets listed in the Suggested snippets group.

“Tracking” does not mean TextExpander keeps a list of the actual characters you type. Instead, it keeps an encoded record (called a “hash”) of that group of characters, similar to the way a password is securely stored so that no one reading it knows what it is. You might type “yourpetsname” but what TextExpander sees and records is “1739405847385.”

Source: TextExpander 5.1 Help.

After reading this, I was fully reassured about any potential security risks. If TextExpander only keeps an encoded record of what I type and that record doesn’t persist across restarts, then I assumed it only kept the information in memory and that nothing would be stored in the cloud.

Insecure Text Input and Snippet Suggestion

There are measures in place to prevent TextExpander from storing potentially sensitive text, like passwords. However, on my system it still managed to occasionally suggest a passwords as new snippets. I admit to being slightly terrified every time a notification popped up to suggest that I add one of my important, paranoia-grade passwords as a snippet, but at least they weren’t being stored in plain text anywhere, or so I thought.

To understand why TextExpander was able to see my passwords in the first place, it helps to know a little more about how text input in a modern OS X application works. Developers can flag certain text fields for secure text input (e.g., password fields that don’t display what you type). The operating system won’t allow TextExpander to see what you type in those fields and therefore it could not feasibly suggest snippets based on that input. Applications such as 1Password and Safari (for properly written web forms) have no problem properly flagging secure text fields.

In other cases, it’s nearly impossible for OS X to know when secure text is being requested. Consider a terminal emulator like Terminal or iTerm 2, or a programmable text editor like Emacs. These applications can run arbitrary, cross-platform code that is not specifically written for OS X and hence does not flag secure text entry in the way that OS X recognizes. Consider logging in to a remote server via SSH on the command line. When you type your password in the terminal, unless your terminal emulator is in the list of excluded apps, TextExpander will take note that you typed a certain string, one that happens to be your password. If you do that often enough and you have snippet suggestion turned on, then your password becomes a suggested snippet. Therefore, one has to be careful to exclude all applications where passwords and other sensitive information might be entered but not marked as secure text. Primary examples are Terminal, iTerm 2, Emacs, and so on.

TextExpander Preferences: Applications to Exclude from Snippet Suggestion
TextExpander Preferences: Applications to Exclude from Snippet Suggestion

Suggested Snippet Storage and Synchronization

It turns out that suggestions are stored in plain text in an XML file in the TextExpander settings bundle (a directory called Settings.textexpandersettings). The file is named group_<uuid>.xml, where <uuid> is a long string of numbers and letters, and is associated with the “Suggested Snippets” group. Furthermore, if you have sync enabled (via Dropbox, iCloud, etc.) then these suggestions also sync in plain text. Because I have Dropbox sync enabled, the group_<uuid>.xml file is stored on Dropbox. As an example, in the Settings.textexpandersettings directory in my Dropbox account, I found the following entry in an XML file:

<dict>
    <key>abbreviation</key>
    <string></string>
    <key>abbreviationMode</key>
    <integer>0</integer>
    <key>creationDate</key>
    <date>2015-06-17T17:18:54Z</date>
    <key>extraInfo</key>
    <dict>
        <key>pendingSuggestionDate</key>
        <date>2015-06-17T17:18:54Z</date>
    </dict>
    <key>label</key>
    <string></string>
    <key>modificationDate</key>
    <date>2015-06-17T17:18:54Z</date>
    <key>plainText</key>
    <string>REDACTED</string>
    <key>snippetType</key>
    <integer>0</integer>
    <key>uuidString</key>
    <string>9EFC26DA-8536-4D3E-A002-983E792EDBAD</string>
</dict>

Notice this section in particular:

<key>plainText</key>
<string>REDACTED</string>

Indeed, rather than REDACTED the value of the plainText key was actually one my most important passwords–all 47-characters in full, plain text glory.

In retrospect, I should have been much more vigilant in many ways. I should have excluded any apps that might result in insecure text being added as a snippet. The terminal entry weakness wasn’t obvious to me at first though. It also wasn’t obvious to me that the suggested snippets were being synchronized across machines because there tend to be a large number of suggestions to filter through and, since I type similar things on multiple machines, some similarities across machines are to be expected.

While I still think the documentation on suggested snippets and privacy is incomplete and potentially misleading, here is a more thorough description of the behavior I received from Smile support:

The help text you cited refers to the tracking of keystrokes up to the point at which a suggestion is made. Once a suggestion is made, yes, it is stored in the settings in plain text. TextExpander remembers the suggestions it’s found for later, so as to not keep suggesting them again. The Help text may need clarification, but in essence it is exactly true. The log of all keystrokes (tracking) is discarded and only suggestions are kept.

Clean Up and Prevention

If this happened to you as well and you want to clean things up, try the following:

  1. Disable snippet suggestion in the TextExpander for any apps that might not flag all secure text entry by adding them to the list of excluded apps, as discussed above.

  2. Note the name of the XML file in your settings bundle corresponding to the “Suggested Snippets” group. You’ll need to find this file on the Dropbox website later. This step can be tricky since Finder hides the contents of the setting bundle by default.

    One option is to control-click the bundle in finder and click “Show package contents”. Then preview the group_<uuid>.xml files until you find the one containing <key>name</key> followed by <string>Suggested Snippets</string>.

    Another option, if you’re comfortable on the command line, is to cd to the Settings.textexpandersettings directory and grep for "Suggested Snippets" to find the right file. For example:

    cd ~/Dropbox/TextExpander/Settings.textexpandersettings
    grep "Suggested Snippets" group*.xml
    
  3. Turn off snippet suggestions in the TextExpander preferences and delete the Suggested Snippets group.

  4. The previous step should delete the corresponding XML file, but you’ll also want to remove the Dropbox version history for the file. On the Dropbox website, navigate to the settings bundle and click the trashcan icon to show deleted files. Command-click (or right click) the deleted XML file and click “Permanently delete”.

  5. Optionally, re-enable snippet suggestion.

Permanently Delete Files in Dropbox
Permanently Delete Files in Dropbox