diff --git a/rules/java/third_parties/algolia.yml b/rules/java/third_parties/algolia.yml new file mode 100644 index 000000000..7ac7a0bdc --- /dev/null +++ b/rules/java/third_parties/algolia.yml @@ -0,0 +1,83 @@ +imports: + - java_shared_lang_datatype + - java_shared_lang_instance +patterns: + - pattern: $.$($); + filters: + - variable: INDEX + detection: java_third_parties_algolia_index + - variable: METHOD + values: + - saveObject + - saveObjectAsync + - saveObjects + - saveObjectsAsync + - partialUpdateObject + - partialUpdateObjectAsync + - partialUpdateObjects + - partialUpdateObjectsAsync + - replaceAllObjects + - either: + - variable: ENTITY_WITH_DATATYPES + detection: java_third_parties_algolia_object_with_datatypes + - variable: ENTITY_WITH_DATATYPES + detection: java_third_parties_algolia_array_with_dataypes +languages: + - java +auxiliary: + - id: java_third_parties_algolia_index + patterns: + - pattern: | + $.initIndex(); + filters: + - variable: CLIENT + detection: java_third_parties_algolia_client + scope: cursor + - id: java_third_parties_algolia_object_with_datatypes + patterns: + - pattern: $<_>.$($); + filters: + - variable: SETTER_METHOD + regex: \Aset[a-zA-Z]+\z + - variable: DATA_TYPE + detection: java_shared_lang_datatype + - pattern: new $<_>($<...>$$<...>); + filters: + - variable: DATA_TYPE + detection: java_shared_lang_datatype + - pattern: Arrays.asList($<...>$$<...>); + filters: + - variable: DATA_TYPE + detection: java_shared_lang_datatype + - id: java_third_parties_algolia_array_with_dataypes + patterns: + - pattern: Arrays.asList($<...>$$<...>); + filters: + - variable: OBJ_WITH_DATATYPES + detection: java_third_parties_algolia_object_with_datatypes + - id: java_third_parties_algolia_client + patterns: + - pattern: $.create(); + filters: + - variable: CLIENT + regex: \A(com\.algolia\.search\.)?(SearchClient|DefaultSearchClient)\z +skip_data_types: + - "Unique Identifier" +metadata: + description: Leakage of sensitive data to Algolia + remediation_message: | + ## Description + Leaking sensitive data to third-party data tools is a common cause of data + leaks and can lead to data breaches. This rule looks for instances of + sensitive data sent to Algolia. + + ## Remediations + When sending data to third-party services, ensure all sensitive data is removed. + + ## Resources + - [Algolia docs](https://www.algolia.com/doc/) + cwe_id: + - 201 + associated_recipe: Algolia + id: java_third_parties_algolia + documentation_url: https://docs.bearer.com/reference/rules/java_third_parties_algolia diff --git a/tests/java/third_parties/algolia/test.js b/tests/java/third_parties/algolia/test.js new file mode 100644 index 000000000..efb0bfe97 --- /dev/null +++ b/tests/java/third_parties/algolia/test.js @@ -0,0 +1,18 @@ +const { + createNewInvoker, + getEnvironment, +} = require("../../../helper.js") +const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) + +describe(ruleId, () => { + const invoke = createNewInvoker(ruleId, ruleFile, testBase) + + test("algolia", () => { + const testCase = "main.java" + + const results = invoke(testCase) + + expect(results.Missing).toEqual([]) + expect(results.Extra).toEqual([]) + }) +}) \ No newline at end of file diff --git a/tests/java/third_parties/algolia/testdata/main.java b/tests/java/third_parties/algolia/testdata/main.java new file mode 100644 index 000000000..775dc9d2f --- /dev/null +++ b/tests/java/third_parties/algolia/testdata/main.java @@ -0,0 +1,46 @@ +import com.algolia.search.DefaultSearchClient; +import com.algolia.search.SearchClient; +import com.algolia.search.SearchIndex; +import com.algolia.search.models.indexing.Query; +import com.algolia.search.models.indexing.SearchResult; + +public class Program { + public static void bad(User user) { + SearchClient client = DefaultSearchClient.create("YourApplicationID", "YourWriteAPIKey"); + SearchIndex index = client.initIndex("test_index", Contact.class); + // bearer:expected java_third_parties_algolia + Contact contactObj = new Contact().setName(user.name).setEmail(user.email); + + SearchResult results = index.saveObject(contactObj); + } + + public static void bad2(User user) { + SearchClient client = DefaultSearchClient.create("YourApplicationID", "YourWriteAPIKey"); + + SearchIndex index = client.initIndex("test_index", Record.class); + // bearer:expected java_third_parties_algolia + Record record = new Record("test_user", user.email); + index.saveObject(record); + } + + public static void bad3(User currentUser) { + SearchClient client = DefaultSearchClient.create("YourApplicationID", "YourWriteAPIKey"); + SearchIndex index = client.initIndex("test_index", Contact.class); + List contactList = Arrays.asList( + new Contact() + .setId(currentUser.uuid) + // bearer:expected java_third_parties_algolia + .setName(currentUser.name) + .setEmail(currentUser.email) + ) + + SearchResult results = index.saveObjectsAsync(contactList); + } + + public static void good(User user) { + SearchClient client = DefaultSearchClient.create("YourApplicationID", "YourWriteAPIKey"); + SearchIndex index = client.initIndex("test_index", Contact.class); + Contact contact = new Contact("test_user", user.uuid); + index.saveObject(contact); + } +} \ No newline at end of file