Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,28 @@ private static void merge(JSONArray requestJsonArray, JSONArray openRtbJsonArray
}
}

/**
* Removes the fields that the SDK computes itself, so that the publisher provided
* global ORTB config can't override them.
* <p>
* Each list is applied at the level where the SDK actually writes the field, i.e.
* {@code regs.ext.gdpr} is stripped from {@code regs.ext} and not from {@code regs}.
*/
private static void removeSensitiveData(@NonNull JSONObject openRtbJson) {
JSONObject userJson = openRtbJson.optJSONObject("user");
JSONObject extJson = userJson != null ? userJson.optJSONObject("ext") : null;
removeFields(extJson, FIELDS_USER_EXT);
removeFieldsWithExt(openRtbJson.optJSONObject("regs"), FIELDS_REGS, FIELDS_REGS_EXT);
removeFieldsWithExt(openRtbJson.optJSONObject("user"), FIELDS_USER, FIELDS_USER_EXT);

removeFields(openRtbJson.optJSONObject("regs"), FIELDS_REGS);
removeFields(openRtbJson.optJSONObject("geo"), FIELDS_GEO);
// "device" has no separate ext list, FIELDS_DEVICE drops the whole "device.ext" object.
removeFields(openRtbJson.optJSONObject("device"), FIELDS_DEVICE);
}

private static void removeFieldsWithExt(@Nullable JSONObject json, String[] fields, String[] extFields) {
if (json == null) return;

removeFields(json, fields);
removeFields(json.optJSONObject("ext"), extFields);
}

private static void removeFields(@Nullable JSONObject json, String... fields) {
if (json == null) return;

Expand All @@ -119,29 +131,27 @@ private static void removeFields(@Nullable JSONObject json, String... fields) {
}


private static final String[] FIELDS_USER = {
"geo"
};

private static final String[] FIELDS_USER_EXT = {
"consent"
};

private static final String[] FIELDS_REGS = {
"gdpr",
"us_privacy",
"coppa"
"coppa",
"gpp",
"gpp_sid"
};

private static final String[] FIELDS_GEO = {
"lat",
"lon",
"type",
"accuracy",
"lastfix",
"country",
"region",
"regionfips104",
"metro",
"city",
"zip",
"utcoffset"
/**
* Note: "tfua" is intentionally not protected. The global ORTB config is the only way
* for publishers to send it (see issue #997).
*/
private static final String[] FIELDS_REGS_EXT = {
"gdpr",
"us_privacy"
};

private static final String[] FIELDS_DEVICE = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public class Regs extends BaseBid {
private JSONArray gppSid;

/**
* When you add a new field to this list, don't forget to add it to the {@link org.prebid.mobile.OpenRtbMerger}.
* When you add a new field to this list, don't forget to protect it in the
* {@link org.prebid.mobile.OpenRtbMerger}: FIELDS_REGS for the fields written here,
* FIELDS_REGS_EXT for the ones written into {@link #getExt()}.
*/
public JSONObject getJsonObject() throws JSONException {
JSONObject jsonObject = new JSONObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public class Geo extends BaseBid {
public Integer utcoffset = null;

/**
* When you add a new field to this list, don't forget to add it to the {@link org.prebid.mobile.OpenRtbMerger}.
* No per-field list is needed in the {@link org.prebid.mobile.OpenRtbMerger}: the whole
* "geo" object is protected by its parent ("device" via FIELDS_DEVICE, "user" via FIELDS_USER).
*/
public JSONObject getJsonObject() throws JSONException {
JSONObject jsonObject = new JSONObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,56 @@ public void mergeSensitiveData_fullRequest_requestFieldsAreNotChanged() throws J
assertJsonEquals(request, mergedJson.toString());
}

@Test
public void mergeSensitiveData_regsExtConsentFields_areNotOverridden() throws JSONException {
String request = "{\"regs\":{\"ext\":{\"gdpr\":1,\"us_privacy\":\"1YNN\"}}}";
String openRtb = "{\"regs\":{\"ext\":{\"gdpr\":0,\"us_privacy\":\"1---\"}}}";

JSONObject mergedJson = merge(request, openRtb);

assertJsonEquals(request, mergedJson.toString());
}

@Test
public void mergeSensitiveData_regsExtConsentFields_areNotAddedToEmptyRequest() throws JSONException {
String request = "{}";
String openRtb = "{\"regs\":{\"ext\":{\"gdpr\":0,\"us_privacy\":\"1---\"}}}";

JSONObject mergedJson = merge(request, openRtb);

assertJsonEquals("{\"regs\":{\"ext\":{}}}", mergedJson.toString());
}

@Test
public void mergeSensitiveData_regsExtTfua_passesThrough() throws JSONException {
String request = "{\"regs\":{\"ext\":{\"gdpr\":1}}}";
String openRtb = "{\"regs\":{\"ext\":{\"tfua\":1,\"gdpr\":0}}}";

JSONObject mergedJson = merge(request, openRtb);

assertJsonEquals("{\"regs\":{\"ext\":{\"gdpr\":1,\"tfua\":1}}}", mergedJson.toString());
}

@Test
public void mergeSensitiveData_regsCoppaGppAndGppSid_areNotOverridden() throws JSONException {
String request = "{\"regs\":{\"coppa\":1,\"gpp\":\"real\",\"gpp_sid\":[7]}}";
String openRtb = "{\"regs\":{\"coppa\":0,\"gpp\":\"fake\",\"gpp_sid\":[1,2]}}";

JSONObject mergedJson = merge(request, openRtb);

assertJsonEquals(request, mergedJson.toString());
}

@Test
public void mergeSensitiveData_userGeo_isNotOverridden() throws JSONException {
String request = "{\"user\":{\"geo\":{\"lat\":1.5,\"lon\":2.5}}}";
String openRtb = "{\"user\":{\"geo\":{\"lat\":9.9,\"lon\":8.8},\"keywords\":\"new\"}}";

JSONObject mergedJson = merge(request, openRtb);

assertJsonEquals("{\"user\":{\"geo\":{\"lat\":1.5,\"lon\":2.5},\"keywords\":\"new\"}}", mergedJson.toString());
}

@Test
public void merge_differentTypes() throws JSONException {
String request = "{}";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
{
"user": {
"ext": {
}
"ext": {}
},
"regs": {
"ext": {}
},
"geo": {
},
"device": {
}
}
"device": {}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
{
"user": {
"geo": {
"lat": "fake",
"lon": "fake"
},
"ext": {
"consent": "fake"
}
},
"regs": {
"gdpr": "fake",
"us_privacy": "fake",
"coppa": "fake"
},
"geo": {
"lat": "fake",
"lon": "fake",
"type": "fake",
"accuracy": "fake",
"lastfix": "fake",
"country": "fake",
"region": "fake",
"regionfips104": "fake",
"metro": "fake",
"city": "fake",
"zip": "fake",
"utcoffset": "fake"
"coppa": 1,
"gpp": "fake",
"gpp_sid": "fake",
"ext": {
"gdpr": 0,
"us_privacy": "fake"
}
},
"device": {
"ua": 123,
Expand All @@ -30,29 +24,29 @@
"fake": "fake"
},
"ip": "fake",
"ipv6": "fake",
"ipv6": "fake",
"devicetype": "fake",
"make": "fake",
"make": "fake",
"model": "fake",
"os": "fake",
"os": "fake",
"osv": "fake",
"hwv": "fake",
"hwv": "fake",
"flashver": "fake",
"language": "fake",
"language": "fake",
"carrier": "fake",
"mccmnc": "fake",
"mccmnc": "fake",
"ifa": "fake",
"didsha1": "fake",
"didsha1": "fake",
"didmd5": "fake",
"dpidsha1": "fake",
"dpidsha1": "fake",
"dpidmd5": "fake",
"h": "fake",
"h": "fake",
"w": "fake",
"ppi": "fake",
"ppi": "fake",
"js": "fake",
"connectiontype": "fake",
"connectiontype": "fake",
"pxratio": "fake",
"geo": "fake",
"geo": "fake",
"ext": "fake"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,56 +1,50 @@
{
"user": {
"geo": {
"lat": "real",
"lon": "real"
},
"ext": {
"consent": "real"
}
},
"regs": {
"gdpr": "real",
"us_privacy": "real",
"coppa": "real"
},
"geo": {
"lat": "real",
"lon": "real",
"type": "real",
"accuracy": "real",
"lastfix": "real",
"country": "real",
"region": "real",
"regionfips104": "real",
"metro": "real",
"city": "real",
"zip": "real",
"utcoffset": "real"
"coppa": "real",
"gpp": "real",
"gpp_sid": "real",
"ext": {
"gdpr": "real",
"us_privacy": "real"
}
},
"device": {
"ua": "real",
"dnt": "real",
"lmt": "real",
"lmt": "real",
"ip": "real",
"ipv6": "real",
"ipv6": "real",
"devicetype": "real",
"make": "real",
"make": "real",
"model": "real",
"os": "real",
"os": "real",
"osv": "real",
"hwv": "real",
"hwv": "real",
"flashver": "real",
"language": "real",
"language": "real",
"carrier": "real",
"mccmnc": "real",
"mccmnc": "real",
"ifa": "real",
"didsha1": "real",
"didsha1": "real",
"didmd5": "real",
"dpidsha1": "real",
"dpidsha1": "real",
"dpidmd5": "real",
"h": "real",
"h": "real",
"w": "real",
"ppi": "real",
"ppi": "real",
"js": "real",
"connectiontype": "real",
"connectiontype": "real",
"pxratio": "real",
"geo": "real",
"geo": "real",
"ext": "real"
}
}
}
Loading