+
+
+ 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 000000000000..a8c32f9aeff5
--- /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 000000000000..7c60c03ebf44
--- /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 f2eac05e6dec..d1cf0fe32542 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 000000000000..d8af1947bd71
--- /dev/null
+++ b/java/ql/test/query-tests/security/CWE-312/AndroidManifest.xml
@@ -0,0 +1,13 @@
+