Content Injection in DuoLingo’s TinyCards App for Android [CVE-2017-16905]

[NOTE ADDED 04/29/2019: The term “RCE” – “Remote Code Execution” in this context is taken from the Google Play Security Reward Program (GPSRP) as per their policy here, even though it is not normally used that way. It specifically refers to the ability to inject and run JavaScript within a WebView-based app.

For now, the scope of this program is limited to RCE (remote-code-execution) vulnerabilities and corresponding POCs (Proof of concepts) that work on Android 4.4 devices and higher. This translates to any RCE vulnerability that allows an attacker to run code of their choosing on a user’s device without user knowledge or permission. Examples may include:

  •  Attacker gaining full control, meaning code can be downloaded from the network and executed (download and execute arbitrary code, native, Java code etc. Javascript)
  • UI Manipulation to commit a transaction. For example, causing a banking app to make money transfers on behalf of the user without their consent.
  •  Opening of webview that may lead to phishing attacks. Opening webview without user input or interaction.



The TinyCards Android application provided by DuoLingo can be injected with malicious content by an MITM attacker. Because this application is a web-app framed in an Android WebView, this can lead to JavaScript being executed within the app by running JavaScript [which Google calls remote code execution (RCE)]. The root cause is lack of SSL being used on app startup when the initial web content is loaded into the WebView.

The vendor has fixed this issue in v1.0 (version code 10) that was released via Google Play Store on November 20th, 2017 and users should install the latest version. MITRE has assigned # CVE-2017-16905 to track this issue.

Vulnerability Details

TinyCards is a flashcard application for preparing for tests and memorizing vocabulary. It is made by DuoLingo, which provides a platform for learning new languages. While monitoring network traffic of a test device running Android, we observed that during application startup an initial HTTP call is made to a non-HTTPS site, which then redirects to an HTTPS version. Further research into the application revealed that the application is essentially a thin browser wrapper using Android’s WebView around a web application loaded remotely.

Because the initial call is done without HTTPS, it is possible for an MITM attacker to intercept this traffic and inject their own content.  Since this is a web app, this can result in code execution within the application since all the content is web based. This would be accomplished by injecting and running arbitrary JavaScript.

Screenshots of the captured traffic and relevant source code:


Steps To Replicate (on Ubuntu 17.10)

1. Install the application on the Android device but do not start it.

2. Install dnsmasq and NGINX on the Linux host:

sudo apt-get install dnsmasq nginx

3. Modify the /etc/hosts file to add the following entry to map the domain name to the Linux host:


4. Configure /etc/dnsmasq.conf file to listen on the IP and restart DNSMASQ

sudo /etc/init.d/dnsmasq restart

5. Add a file with malicious content (you may need to use sudo):

cd /var/www/html
echo powned >index.html

6. Modify the settings on the Android test phone to static, set DNS to point to “192.168.1.x”. AT THIS POINT – Android will resolve DNS against the Linux computer and serve the large servers file

7. Open the app on the Android device and observe injected content.

All testing was done on v1.0 (version code 9)  of the Android application using a Linux host running Ubuntu v17.10 and Android test device running Android v7.

Vendor Response and Mitigation

To fix this issue, the vendor has changed the initial URL for web content being loaded within the app to use SSL. The vendor has fixed this issue in v1.0 (version code 10) that was released via Google Play Store on November 20th, 2017 and users should install the latest version.

Bounty Information

DuoLingo doesn’t currently offer bounties, however, this bug has fulfilled the requirements of Google Play Security Reward Program and a bounty has been paid from that program.


CVE-ID: CVE-2017-16905
HackerOne Reports: 281605 (DuoLingo) and 293444 (Google Play Rewards)


We would like to thank the vendor for the quick turnaround and fix for this  vulnerability. Text of the advisory written by Yakov Shafranovich.


2017-10-21: Report opened with the vendor via HackerOne to clarify scope
2017-11-06: Technical details of vulnerability provided to the vendor via HackerOne
2017-11-07: Report triaged and being reviewed by the vendor
2017-11-20: Vendor patched the issue and asked for testing of the fix
2017-11-20: Fix confirmed, communication regarding disclosure
2017-11-28: Report submitted to Google’s Play Rewards program via HackerOne
2017-11-29: Rejection received due to scope, follow-up communication with Google regarding scope
2017-12-04: Follow-up conversation about disclosure with Google and the vendor
2017-12-05: Disclosure requested from DuoLingo via HackerOne
2018-01-04: Public disclosure on HackerOne, and publication of this advisory
2019-04-29: Added clarification for terminology

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.