As you develop on the Twitter platform, we want to remind you of the danger of hackers, who aim to spread spam, install malware and generally promote mayhem across the web. This page is to inform you of some good practices you can use to help keep your application as safe as possible.
If there’s anything you believe should be added to this page, please let us know.
If you’ve discovered a security issue that directly affects Twitter itself, we have a bug bounty program for Vulnerabilities.
The following threats are applicable no matter what your platform. Please keep them in mind as you build into the Twitter platform, and elsewhere across the internet.
Do not retain passwords. Use OAuth tokens where possible. Encrypt other sensitive data as needed.
Don’t assume that your users will provide you with valid, trustworthy data. Sanitize all data, checking for sane string lengths, valid file types, etc. Twitter attempts to sanitize data POSTed to our APIs, but a little client-side help goes a long way. Whitelist the types of input that are acceptable to your application and discard everything that isn’t on the whitelist.
Twitter provides all REST API methods over TLS. Whenever your code might be operating on an untrusted network (that is, if you’re developing a client application), please make use of SSL for all authenticated or sensitive requests. For example, posting a status, requesting recent Direct Messages, and updating profile attributes must all be performed over TLS in a Twitter client. Service-to-service communication should also be encrypted wherever possible.
Tokens and Secrets
Twitter APIs rely on OAuth for authorizing each call. When working with an access token and token secret, be sure to encrypt them (and other sensitive data) as safely as possible.
Exposed Debugging Information
Be sure that you’re not exposing sensitive information through debugging screens/logs. Some web frameworks make it easy to access debugging information if your application is not properly configured. For desktop and mobile developers, it’s easy to accidentally ship a build with debugging flags or symbols enabled. Build checks for these configurations into your deployment/build process.
Ensure that your tests check not just that you can do what should be able to do, but that bad guys can’t do what they shouldn’t be able to do. Put yourself in an attacker’s mindset, and whip up some evil tests.
Not Letting People Help
Have you set up firstname.lastname@example.org? Do those emails go right to your phone? Make it easy for people to contact you about potential security issues with your application. If someone does report a security flaw to you, be nice to them; they’ve just done you a huge favor. Thank them for their time and fix the issue promptly. It’s fairly common for security researchers to write about vulnerabilities they’ve discovered once the hole has been closed, so don’t be upset if your application ends up in a blog post or research paper. Security is hard, and nobody is perfect. As long as you’re fixing the issues that are reported to you, you’re doing right.
Consider hiring security professionals to do an audit and/or penetration test. You can’t depend solely on the kindness of strangers; for every vulnerability that someone was nice enough to report to you, there’s ten more that malicious hackers have found. A good security firm will dig deep to uncover issues. Look for firms and individual consultants that do more than run a few automated tools.
If your application is (going to be) handling money, you may be required by law to adhere to certain security practices and regulations. Find out what’s applicable to you and make sure you’re up to code.
Web Application Security
Unfiltered Input, Unescaped Output
One easy-to-remember approach to input validation is FIEO: Filter Input, Escape Output. Filter anything from outside your application, including Twitter API data, cookie data, user-supplied form input, URL parameters, data from databases, etc. Escape all output being sent by your application, including SQL sent to your database server, HTML to you send to users’ browsers, JSON output sent to other systems, and commands sent to shell programs.
Cross-Site Scripting (XSS)
If your application makes use of a database, you need to be aware of SQL injection. Anywhere you accept input is a potential target for an attacker to break out of their input field and into your database. Use database libraries that protect against SQL injection in a systematic way. If you break out of that approach and write custom SQL, write aggressive tests to be sure you aren’t exposing yourself to this form of attack.
The two main approaches to defending against SQL injection are escaping before constructing your SQL statement, and using parameterized input to create statements. The latter is recommended, as it’s less prone to programmer error.
Cross-Site Request Forgery (CSRF)
Are you sure that requests to your application are coming from your application? CSRF attacks exploit this lack of knowledge by forcing logged-in users of your site to silently open URLs that perform actions. In the case of a Twitter app, this could mean that attackers are using your app to force users to post unwanted Tweets or follow spam accounts.
The most thorough way to deal with CSRF is to include a random token in every form that’s stored someplace trusted; if a form doesn’t have the right token, throw an error. Modern web frameworks have systematic ways of handling this, and might even be doing it by default if you’re lucky. A simple preventative step (but by no means the only step you should take) is to make any actions that create, modify, or destroy data require a POST request.
Lack of Rate Limiting
Use CAPTCHAs where appropriate to slow down potential spammers and attackers.
Lack of Information about Threats
If you think there’s an issue with your web application, how do you find out for sure? Have critical exceptions and errors emailed to you and keep good logs. You may want to put together a dashboard of critical statistics so that you can see at a glance if something is going wrong (or staying right).
Unencrypted Storage of Credentials
You should be using OAuth. Once you have an access token with which to make requests on behalf of a user put it in an encrypted store managed by your operating system. On macOS this would be the Keychain. In the GNOME desktop environment, there’s the Keyring. In the KDE desktop environment, there’s KWallet.