+
+
+ Android applications with the appropriate permissions can write files either to the device external storage or the application internal storage, depending on the application's needs. However, sensitive information should not be saved in cleartext. Otherwise it can be accessed by any process or user in rooted devices, or can be disclosed through chained vulnerabilities, like unexpected access to the private storage through exposed components.
+
+
+
+
+
+ Consider using the EncryptedFile class to work with files containing sensitive data. Alternatively, use encryption algorithms to encrypt the sensitive data being stored.
+
+
+
+
+
+ In the first example, sensitive user information is stored in cleartext using a local file.
+
+
+ In the second and third examples, the code encrypts sensitive information before saving it to the filesystem.
+
+
+
+
+
+
+ Android Developers:
+ Work with data more securely
+
+
+ Android Developers:
+ EncryptedFile
+
+
+
diff --git a/java/ql/src/Security/CWE/CWE-312/CleartextStorageAndroidFilesystem.ql b/java/ql/src/Security/CWE/CWE-312/CleartextStorageAndroidFilesystem.ql
new file mode 100644
index 00000000000..a8c32f9aeff
--- /dev/null
+++ b/java/ql/src/Security/CWE/CWE-312/CleartextStorageAndroidFilesystem.ql
@@ -0,0 +1,23 @@
+/**
+ * @name Cleartext storage of sensitive information in the Android filesystem
+ * @description Cleartext storage of sensitive information in the Android filesystem
+ * allows access for users with root privileges or unexpected exposure
+ * from chained vulnerabilities.
+ * @kind problem
+ * @problem.severity warning
+ * @precision medium
+ * @id java/android/cleartext-storage-filesystem
+ * @tags security
+ * external/cwe/cwe-312
+ */
+
+import java
+import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
+
+from SensitiveSource data, LocalFileOpenCall s, Expr input, Expr store
+where
+ input = s.getAnInput() and
+ store = s.getAStore() and
+ data.flowsTo(input)
+select store, "Local file $@ containing $@ is stored $@. Data was added $@.", s, s.toString(), data,
+ "sensitive data", store, "here", input, "here"
diff --git a/java/ql/src/change-notes/2021-09-01-cleartext-storage-filesystem-query.md b/java/ql/src/change-notes/2021-09-01-cleartext-storage-filesystem-query.md
new file mode 100644
index 00000000000..7c60c03ebf4
--- /dev/null
+++ b/java/ql/src/change-notes/2021-09-01-cleartext-storage-filesystem-query.md
@@ -0,0 +1,4 @@
+---
+category: newQuery
+---
+* A new query "Cleartext storage of sensitive information in the Android filesystem" (`java/android/cleartext-storage-filesystem`) has been added. This query finds instances of sensitive data being stored in local files without encryption, which may expose it to attackers or malicious applications.
diff --git a/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected b/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected
index f2eac05e6de..d1cf0fe3254 100644
--- a/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected
+++ b/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected
@@ -1,4 +1,3 @@
-| java.io.PrintStream#println(Object) | 3 |
| java.lang.Class#isAssignableFrom(Class) | 1 |
| java.lang.String#length() | 1 |
| java.time.Duration#ofMillis(long) | 1 |
diff --git a/java/ql/test/query-tests/security/CWE-312/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-312/AndroidManifest.xml
new file mode 100644
index 00000000000..d8af1947bd7
--- /dev/null
+++ b/java/ql/test/query-tests/security/CWE-312/AndroidManifest.xml
@@ -0,0 +1,13 @@
+