diff --git a/rules/S6291/common/recommended-java-kotlin.adoc b/rules/S6291/common/recommended-java-kotlin.adoc new file mode 100644 index 00000000000..aa62e413629 --- /dev/null +++ b/rules/S6291/common/recommended-java-kotlin.adoc @@ -0,0 +1 @@ +The encryption password should not be hard-coded in the application. There are different approaches how the password can be provided to encrypt and decrypt the database. In the case of `EncryptedSharedPreferences` the Android Keystore can be used to store the password. Other databases can rely on `EncryptedSharedPreferences` to store passwords. The password can also be provided dynamically by the user of the application or it can be fetched from a remote server if the other methods are not feasible. diff --git a/rules/S6291/dart/metadata.json b/rules/S6291/dart/metadata.json new file mode 100644 index 00000000000..17971333806 --- /dev/null +++ b/rules/S6291/dart/metadata.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/rules/S6291/dart/rule.adoc b/rules/S6291/dart/rule.adoc new file mode 100644 index 00000000000..c02bbc15393 --- /dev/null +++ b/rules/S6291/dart/rule.adoc @@ -0,0 +1,62 @@ +:example_libraries: sqflite and sqflite_sqlcipher + +include::../description.adoc[] + +include::../ask-yourself.adoc[] + +include::../recommended.adoc[] + +The encryption password should not be hard-coded in the application. There are different approaches how the password can be provided to encrypt and decrypt the database, such as using https://pub.dev/packages/flutter_secure_storage[`flutter_secure_storage`]. The password can also be provided dynamically by the user of the application or it can be fetched from a remote server if the other methods are not feasible. + +== Sensitive Code Example + +For the https://pub.dev/packages/sqflite[`sqflite` package]: + +[source,dart] +---- +import 'package:sqflite/sqflite.dart'; + +void openDb() async { + final db = await openDatabase("test.db"); // Noncompliant: no password support + await db.execute("CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)"); +} +---- + +For the https://pub.dev/packages/sqflite_sqlcipher[`sqflite_sqlcipher` package]: + +[source,dart] +---- +import 'package:sqflite_sqlcipher/sqflite.dart'; + +void openDb() async { + final db = await openDatabase("test.db"); // Noncompliant: missing password + await db.execute("CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)"); +} +---- + +== Compliant Solution + +Instead of the `openDatabase` function of the `sqflite` package, you can use the equivalent function in the https://pub.dev/packages/sqflite_sqlcipher[`sqflite_sqlcipher` package], that comes with a `password` parameter to encrypt the database: + +[source,dart] +---- +import 'package:sqflite_sqlcipher/sqflite.dart'; + +void openDb() async { + final db = await openDatabase("test.db", password: "password"); // Compliant + await db.execute("CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT)"); +} +---- + +include::../see.adoc[] + + +ifdef::env-github,rspecator-view[] + +''' +== Implementation Specification +(visible only on this page) + +include::../message.adoc[] + +endif::env-github,rspecator-view[] diff --git a/rules/S6291/description.adoc b/rules/S6291/description.adoc index f68ea925b91..673f4be8156 100644 --- a/rules/S6291/description.adoc +++ b/rules/S6291/description.adoc @@ -1 +1,3 @@ -Storing data locally is a common task for mobile applications. Such data includes preferences or authentication tokens for external services, among other things. There are many convenient solutions that allow storing data persistently, for example SQLiteDatabase, SharedPreferences, and Realm. By default these systems store the data unencrypted, thus an attacker with physical access to the device can read them out easily. Access to sensitive data can be harmful for the user of the application, for example when the device gets stolen. +Storing data locally is a common task for mobile applications. Such data includes preferences or authentication tokens for external services, among other things. There are many convenient solutions that allow storing data persistently, for example {example_libraries}. + +By default these systems store the data unencrypted, thus an attacker with physical access to the device can read them out easily. Access to sensitive data can be harmful for the user of the application, for example when the device gets stolen. diff --git a/rules/S6291/java/rule.adoc b/rules/S6291/java/rule.adoc index d740f809f3b..b22d1a43ff7 100644 --- a/rules/S6291/java/rule.adoc +++ b/rules/S6291/java/rule.adoc @@ -1,9 +1,13 @@ +:example_libraries: SQLiteDatabase, SharedPreferences, and Realm + include::../description.adoc[] include::../ask-yourself.adoc[] include::../recommended.adoc[] +include::../common/recommended-java-kotlin.adoc[] + == Sensitive Code Example For https://developer.android.com/reference/kotlin/android/database/sqlite/SQLiteDatabase[SQLiteDatabase]: diff --git a/rules/S6291/kotlin/rule.adoc b/rules/S6291/kotlin/rule.adoc index bdfc4113812..2bc7a064dd1 100644 --- a/rules/S6291/kotlin/rule.adoc +++ b/rules/S6291/kotlin/rule.adoc @@ -1,9 +1,13 @@ +:example_libraries: SQLiteDatabase, SharedPreferences, and Realm + include::../description.adoc[] include::../ask-yourself.adoc[] include::../recommended.adoc[] +include::../common/recommended-java-kotlin.adoc[] + == Sensitive Code Example For https://developer.android.com/reference/kotlin/android/database/sqlite/SQLiteDatabase[SQLiteDatabase]: diff --git a/rules/S6291/recommended.adoc b/rules/S6291/recommended.adoc index cbbc621002f..b6017247b85 100644 --- a/rules/S6291/recommended.adoc +++ b/rules/S6291/recommended.adoc @@ -1,5 +1,3 @@ == Recommended Secure Coding Practices It's recommended to password-encrypt local databases that contain sensitive information. Most systems provide secure alternatives to plain-text storage that should be used. If no secure alternative is available the data can also be encrypted manually before it is stored. - -The encryption password should not be hard-coded in the application. There are different approaches how the password can be provided to encrypt and decrypt the database. In the case of `EncryptedSharedPreferences` the Android Keystore can be used to store the password. Other databases can rely on `EncryptedSharedPreferences` to store passwords. The password can also be provided dynamically by the user of the application or it can be fetched from a remote server if the other methods are not feasible.