Skip to content

Commit 8aa7580

Browse files
authored
Rename filters to redacted keys for spec compliance (#236)
1 parent 5af6abe commit 8aa7580

File tree

18 files changed

+211
-222
lines changed

18 files changed

+211
-222
lines changed

bugsnag/src/main/java/com/bugsnag/Bugsnag.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,16 @@ public void setEndpoint(String endpoint) {
228228
}
229229

230230
/**
231-
* Set which keys should be filtered when sending metaData to Bugsnag.
231+
* Set which keys should be redacted when sending metaData to Bugsnag.
232232
* Use this when you want to ensure sensitive information, such as passwords
233233
* or credit card information is stripped from metaData you send to Bugsnag.
234234
* Any keys in metaData which contain these strings will be marked as
235-
* [FILTERED] when send to Bugsnag.
235+
* [REDACTED] when send to Bugsnag.
236236
*
237-
* @param filters a list of String keys to filter from metaData
237+
* @param redactedKeys a list of String keys to redact from metaData
238238
*/
239-
public void setFilters(String... filters) {
240-
config.filters = filters;
239+
public void setRedactedKeys(String... redactedKeys) {
240+
config.redactedKeys = redactedKeys;
241241
}
242242

243243
/**

bugsnag/src/main/java/com/bugsnag/BugsnagAppender.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public class BugsnagAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
4848
/** Bugsnag error server endpoint. */
4949
private String endpoint;
5050

51-
/** Property names that should be filtered out before sending to Bugsnag servers. */
52-
private Set<String> filteredProperties = new HashSet<String>();
51+
/** Property names that should be redacted before sending to Bugsnag servers. */
52+
private Set<String> redactedKeys = new HashSet<String>();
5353

5454
/** Exception classes to be ignored. */
5555
private Set<String> ignoredClasses = new HashSet<String>();
@@ -254,8 +254,8 @@ private Bugsnag createBugsnag() {
254254
bugsnag.setTimeout(timeout);
255255
}
256256

257-
if (filteredProperties.size() > 0) {
258-
bugsnag.setFilters(filteredProperties.toArray(new String[0]));
257+
if (redactedKeys.size() > 0) {
258+
bugsnag.setRedactedKeys(redactedKeys.toArray(new String[0]));
259259
}
260260

261261
bugsnag.setIgnoreClasses(ignoredClasses.toArray(new String[0]));
@@ -374,24 +374,24 @@ public void setEndpoint(String endpoint) {
374374
}
375375

376376
/**
377-
* @see Bugsnag#setFilters(String...)
377+
* @see Bugsnag#setRedactedKeys(String...)
378378
*/
379-
public void setFilteredProperty(String filter) {
380-
this.filteredProperties.add(filter);
379+
public void setRedactedKey(String key) {
380+
this.redactedKeys.add(key);
381381

382382
if (bugsnag != null) {
383-
bugsnag.setFilters(this.filteredProperties.toArray(new String[0]));
383+
bugsnag.setRedactedKeys(this.redactedKeys.toArray(new String[0]));
384384
}
385385
}
386386

387387
/**
388-
* @see Bugsnag#setFilters(String...)
388+
* @see Bugsnag#setRedactedKeys(String...)
389389
*/
390-
public void setFilteredProperties(String filters) {
391-
this.filteredProperties.addAll(split(filters));
390+
public void setRedactedKeys(String key) {
391+
this.redactedKeys.addAll(split(key));
392392

393393
if (bugsnag != null) {
394-
bugsnag.setFilters(this.filteredProperties.toArray(new String[0]));
394+
bugsnag.setRedactedKeys(this.redactedKeys.toArray(new String[0]));
395395
}
396396
}
397397

bugsnag/src/main/java/com/bugsnag/Configuration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class Configuration {
3636
public Delivery delivery;
3737
public EndpointConfiguration endpointConfiguration;
3838
public Delivery sessionDelivery;
39-
public String[] filters = new String[]{"password", "secret", "Authorization", "Cookie"};
39+
public String[] redactedKeys = new String[]{"password", "secret", "Authorization", "Cookie"};
4040
public String[] ignoreClasses;
4141
public String[] notifyReleaseStages = null;
4242
public String[] projectPackages;

bugsnag/src/main/java/com/bugsnag/util/FilteredMap.java renamed to bugsnag/src/main/java/com/bugsnag/RedactedMap.java

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
package com.bugsnag.util;
1+
package com.bugsnag;
22

3-
import java.util.ArrayList;
43
import java.util.Collection;
54
import java.util.HashMap;
5+
import java.util.HashSet;
66
import java.util.Map;
77
import java.util.Set;
88

99
/**
10-
* Decorates a map by replacing values of filtered keys.
10+
* Decorates a map by replacing values of redacted keys.
1111
*/
12-
public class FilteredMap implements Map<String, Object> {
12+
class RedactedMap implements Map<String, Object> {
1313

14-
private static final String FILTERED_PLACEHOLDER = "[FILTERED]";
14+
private static final String REDACTED_PLACEHOLDER = "[REDACTED]";
1515

16-
private final Map<String, Object> filteredCopy;
17-
private final Collection<String> keyFilters = new ArrayList<String>();
16+
private final Map<String, Object> redactedCopy;
17+
private final Collection<String> redactedKeys = new HashSet<>();
1818

19-
public FilteredMap(Map<String, Object> map, Collection<String> keyFilters) {
20-
this.keyFilters.addAll(keyFilters);
21-
this.filteredCopy = createCopy(map);
19+
RedactedMap(Map<String, Object> map, Collection<String> redactedKeys) {
20+
this.redactedKeys.addAll(redactedKeys);
21+
this.redactedCopy = createCopy(map);
2222
}
2323

2424
private Map<String, Object> createCopy(Map<? extends String, ?> map) {
@@ -36,84 +36,87 @@ private Map<String, Object> createCopy(Map<? extends String, ?> map) {
3636

3737
@Override
3838
public int size() {
39-
return filteredCopy.size();
39+
return redactedCopy.size();
4040
}
4141

4242
@Override
4343
public boolean isEmpty() {
44-
return filteredCopy.isEmpty();
44+
return redactedCopy.isEmpty();
4545
}
4646

4747
@Override
4848
public boolean containsKey(Object key) {
49-
return filteredCopy.containsKey(key);
49+
return redactedCopy.containsKey(key);
5050
}
5151

5252
@Override
5353
public boolean containsValue(Object value) {
54-
return filteredCopy.containsValue(value);
54+
return redactedCopy.containsValue(value);
5555
}
5656

5757
@Override
5858
public Object get(Object key) {
59-
return filteredCopy.get(key);
59+
return redactedCopy.get(key);
6060
}
6161

6262
@Override
6363
public Object put(String key, Object value) {
6464
if (value == null) {
65-
return filteredCopy.put(key, null);
65+
return redactedCopy.put(key, null);
6666
}
6767
Object transformedValue = transformEntry(key, value);
68-
return filteredCopy.put(key, transformedValue);
68+
return redactedCopy.put(key, transformedValue);
6969
}
7070

7171
@Override
7272
public Object remove(Object key) {
73-
return filteredCopy.remove(key);
73+
return redactedCopy.remove(key);
7474
}
7575

7676
@Override
7777
public void putAll(Map<? extends String, ?> mapValues) {
7878
Map<String, Object> copy = createCopy(mapValues);
79-
filteredCopy.putAll(copy);
79+
redactedCopy.putAll(copy);
8080
}
8181

8282
@Override
8383
public void clear() {
84-
filteredCopy.clear();
84+
redactedCopy.clear();
8585
}
8686

8787
@Override
8888
public Set<String> keySet() {
89-
return filteredCopy.keySet();
89+
return redactedCopy.keySet();
9090
}
9191

9292
@Override
9393
public Collection<Object> values() {
94-
return filteredCopy.values();
94+
return redactedCopy.values();
9595
}
9696

9797
@Override
9898
public Set<Entry<String, Object>> entrySet() {
99-
return filteredCopy.entrySet();
99+
return redactedCopy.entrySet();
100100
}
101101

102102
@SuppressWarnings("unchecked")
103103
private Object transformEntry(Object key, Object value) {
104104
if (value instanceof Map) {
105-
return new FilteredMap((Map<String, Object>) value, keyFilters);
105+
return new RedactedMap((Map<String, Object>) value, redactedKeys);
106106
}
107-
return shouldFilterKey((String) key) ? FILTERED_PLACEHOLDER : value;
107+
return shouldRedactKey((String) key) ? REDACTED_PLACEHOLDER : value;
108108
}
109109

110-
private boolean shouldFilterKey(String key) {
111-
if (keyFilters == null || key == null) {
110+
private boolean shouldRedactKey(String key) {
111+
if (key == null) {
112112
return false;
113113
}
114-
115-
for (String filter : keyFilters) {
116-
if (key.contains(filter)) {
114+
// Check for common keys first before looping through all
115+
if (redactedKeys.contains(key)) {
116+
return true;
117+
}
118+
for (String redactedKey : redactedKeys) {
119+
if (key.contains(redactedKey)) {
117120
return true;
118121
}
119122
}

bugsnag/src/main/java/com/bugsnag/Report.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
import com.bugsnag.serialization.Expose;
44

5-
import com.bugsnag.util.FilteredMap;
6-
75
import java.util.ArrayList;
8-
import java.util.Arrays;
96
import java.util.HashMap;
107
import java.util.List;
118
import java.util.Map;
9+
import java.util.Set;
1210

1311
public class Report {
1412

@@ -126,7 +124,7 @@ public Map<String, String> getUser() {
126124

127125
@Expose
128126
public Map<String, Object> getMetaData() {
129-
return new FilteredMap(diagnostics.metaData, Arrays.asList(config.filters));
127+
return new RedactedMap(diagnostics.metaData, Set.of(config.redactedKeys));
130128
}
131129

132130
@Expose

bugsnag/src/test/java/com/bugsnag/AppenderTest.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ public void testBugsnagConfig() {
144144
assertEquals("gradleTask", config.appType);
145145
assertFalse(config.shouldAutoCaptureSessions());
146146

147-
assertEquals(2, config.filters.length);
148-
ArrayList<String> filters = new ArrayList<String>(Arrays.asList(config.filters));
149-
assertTrue(filters.contains("password"));
150-
assertTrue(filters.contains("credit_card_number"));
147+
assertEquals(2, config.redactedKeys.length);
148+
ArrayList<String> redactedKeys = new ArrayList<String>(Arrays.asList(config.redactedKeys));
149+
assertTrue(redactedKeys.contains("password"));
150+
assertTrue(redactedKeys.contains("credit_card_number"));
151151

152152
assertEquals(2, config.ignoreClasses.length);
153153
ArrayList<String> ignoreClasses
@@ -274,15 +274,15 @@ public void testAppType() {
274274
}
275275

276276
@Test
277-
public void testFilters() {
277+
public void testRedactedKeys() {
278278

279-
// Add some meta data which should be filtered by key name
279+
// Add some metadata which should be redacted by key name
280280
Bugsnag.addThreadMetaData("myTab", "password", "password value");
281281
Bugsnag.addThreadMetaData("myTab", "credit_card_number", "card number");
282-
Bugsnag.addThreadMetaData("myTab", "mysecret", "not filtered");
282+
Bugsnag.addThreadMetaData("myTab", "mysecret", "not redacted");
283283

284284
// Send a log message
285-
LOGGER.warn("Exception with filtered meta data", new RuntimeException("test"));
285+
LOGGER.warn("Exception with redacted meta data", new RuntimeException("test"));
286286

287287
// Check that a report was sent to Bugsnag
288288
assertEquals(1, delivery.getNotifications().size());
@@ -291,9 +291,9 @@ public void testFilters() {
291291
assertTrue(notification.getEvents().get(0).getMetaData().containsKey("myTab"));
292292
Map<String, Object> myTab = getMetaDataMap(notification, "myTab");
293293

294-
assertEquals("[FILTERED]", myTab.get("password"));
295-
assertEquals("[FILTERED]", myTab.get("credit_card_number"));
296-
assertEquals("not filtered", myTab.get("mysecret"));
294+
assertEquals("[REDACTED]", myTab.get("password"));
295+
assertEquals("[REDACTED]", myTab.get("credit_card_number"));
296+
assertEquals("not redacted", myTab.get("mysecret"));
297297
}
298298

299299
@Test
@@ -316,7 +316,7 @@ public void beforeNotify(Report report) {
316316
});
317317

318318
// Send a log message
319-
LOGGER.warn("Exception with filtered meta data", new RuntimeException("test"));
319+
LOGGER.warn("Exception with redacted meta data", new RuntimeException("test"));
320320

321321
// Check that a report was sent to Bugsnag
322322
assertEquals(1, delivery.getNotifications().size());
@@ -412,7 +412,7 @@ private SessionTracker getSessionTracker(Bugsnag bugsnag) {
412412
}
413413

414414
/**
415-
* Gets a hashmap key from the meta data in a notification
415+
* Gets a hashmap key from the metadata in a notification
416416
*
417417
* @param notification The notification
418418
* @param key The key to get

bugsnag/src/test/java/com/bugsnag/BugsnagTest.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ public void close() {
164164
}
165165

166166
@Test
167-
public void testFilters() {
168-
bugsnag.setFilters("testfilter1", "testfilter2");
167+
public void testRedactedKeys() {
168+
bugsnag.setRedactedKeys("testredact1", "testredact2");
169169
bugsnag.setDelivery(new Delivery() {
170170
@SuppressWarnings("unchecked")
171171
@Override
@@ -175,10 +175,10 @@ public void deliver(Serializer serializer, Object object, Map<String, String> he
175175
(Map<String, Object>) report.getMetaData().get("firsttab");
176176
final Map<String, Object> secondTab =
177177
(Map<String, Object>) report.getMetaData().get("secondtab");
178-
assertEquals("[FILTERED]", firstTab.get("testfilter1"));
179-
assertEquals("[FILTERED]", firstTab.get("testfilter2"));
180-
assertEquals("secretpassword", firstTab.get("testfilter3"));
181-
assertEquals("[FILTERED]", secondTab.get("testfilter1"));
178+
assertEquals("[REDACTED]", firstTab.get("testredact1"));
179+
assertEquals("[REDACTED]", firstTab.get("testredact2"));
180+
assertEquals("secretpassword", firstTab.get("testredact3"));
181+
assertEquals("[REDACTED]", secondTab.get("testredact1"));
182182
}
183183

184184
@Override
@@ -188,16 +188,16 @@ public void close() {
188188
assertTrue(bugsnag.notify(new Throwable(), new Callback() {
189189
@Override
190190
public void beforeNotify(Report report) {
191-
report.addToTab("firsttab", "testfilter1", "secretpassword");
192-
report.addToTab("firsttab", "testfilter2", "secretpassword");
193-
report.addToTab("firsttab", "testfilter3", "secretpassword");
194-
report.addToTab("secondtab", "testfilter1", "secretpassword");
191+
report.addToTab("firsttab", "testredact1", "secretpassword");
192+
report.addToTab("firsttab", "testredact2", "secretpassword");
193+
report.addToTab("firsttab", "testredact3", "secretpassword");
194+
report.addToTab("secondtab", "testredact1", "secretpassword");
195195
}
196196
}));
197197
}
198198

199199
@Test
200-
public void testFilterHeaders() {
200+
public void testRedactHeaders() {
201201
bugsnag.setDelivery(new Delivery() {
202202
@SuppressWarnings("unchecked")
203203
@Override
@@ -209,9 +209,9 @@ public void deliver(Serializer serializer, Object object, Map<String, String> he
209209
Map<String, Object> headersMap =
210210
(Map<String, Object>) requestTab.get("headers");
211211

212-
assertEquals("[FILTERED]", headersMap.get("Authorization"));
212+
assertEquals("[REDACTED]", headersMap.get("Authorization"));
213213
assertEquals("User:Password", headersMap.get("authorization"));
214-
assertEquals("[FILTERED]", headersMap.get("Cookie"));
214+
assertEquals("[REDACTED]", headersMap.get("Cookie"));
215215
assertEquals("123456ABCDEF", headersMap.get("cookie"));
216216
}
217217

bugsnag/src/test/java/com/bugsnag/JakartaServletCallbackTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ public void testRequestMetadataAdded() {
100100
assertEquals("some-data-1,some-data-2", headers.get("X-Custom-Header"));
101101

102102
// Make sure that actual Authorization header value is not in the report
103-
assertEquals("[FILTERED]", headers.get("Authorization"));
103+
assertEquals("[REDACTED]", headers.get("Authorization"));
104104

105105
// Make sure that actual cookies are not in the report
106-
assertEquals("[FILTERED]", headers.get("Cookie"));
106+
assertEquals("[REDACTED]", headers.get("Cookie"));
107107

108108
assertTrue(request.containsKey("params"));
109109
Map<String, String[]> params = (Map<String, String[]>) request.get("params");

0 commit comments

Comments
 (0)