<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ed Holloway-George on Medium]]></title>
        <description><![CDATA[Stories by Ed Holloway-George on Medium]]></description>
        <link>https://medium.com/@sp4ghetticode?source=rss-1e7c83978135------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*GP8wHftLd8OFs_fqAJRHuA.jpeg</url>
            <title>Stories by Ed Holloway-George on Medium</title>
            <link>https://medium.com/@sp4ghetticode?source=rss-1e7c83978135------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 06 Jun 2026 04:58:02 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sp4ghetticode/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[What’s new in AndroidX DataStore 1.3.0-alpha07: Encrypt your DataStore]]></title>
            <link>https://sp4ghetticode.medium.com/whats-new-in-androidx-datastore-1-3-0-alpha07-encrypt-your-datastore-25ca02b0b0e7?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/25ca02b0b0e7</guid>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[mobile-security]]></category>
            <category><![CDATA[jetpack-datastore]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Sun, 19 Apr 2026 15:50:45 GMT</pubDate>
            <atom:updated>2026-04-20T08:23:05.058Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pu-dODChEgShSp3r" /><figcaption>Photo by <a href="https://unsplash.com/@switch_dtp_fotografie?utm_source=medium&amp;utm_medium=referral">Lucas van Oort</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Background</h3><p>It’s been quite a while since I thought about my old friend EncryptedSharedPreferences 😅</p><p>Like most Android developers, the relationship I had with EncryptedSharedPreferences was a complicated one. It was a library that initially saw a flurry of excitement, support and adoption, then over time faced a slow and gradual demise with minimal updates, a lack of official guidance, and a whole heap of frustration from the library’s consumers as the updates slowly dried up.</p><p>Finally, after what felt like an eternity, the most recent updates <em>eventually</em> brought some clarity via a long-overdue deprecation. But, this left many devs confused at what, if anything, would or should replace it!</p><p><a href="https://proandroiddev.com/securing-the-future-navigating-the-deprecation-of-encrypted-shared-preferences-91ce3c20ae8d">Securing the Future: Navigating the deprecation of Encrypted Shared Preferences</a></p><p>I’ve written and spoken about this saga several times before, most recently back in May 2024, and to the best of my knowledge, <em>that</em> was when the story had its final chapter all wrapped up. <em>I was quite wrong</em> 🙃</p><p>This post explores the interesting and quite surprising development of encryption support being added within <a href="https://developer.android.com/jetpack/androidx/releases/datastore#1.3.0-alpha07">AndroidX DataStore 1.3.0-alpha07</a>, how it works, why it exists and if it’s the right tool for your apps.</p><p>I apologise, I have <strong><em>a lot</em></strong> to say. So, get nicely caffeinated and let’s dive in✨☕️</p><h3>What’s New: A case of Déjà vu!?</h3><p>As part of AndroidX’s regular release cadence, <a href="https://developer.android.com/jetpack/androidx/releases/datastore#1.3.0-alpha07">AndroidX DataStore 1.3.0-alpha07</a> was recently launched on April 11th 2026, with the following noteworthy extract contained within its release notes:</p><blockquote>Encryption Support: Introduced the new androidx.datastore:datastore-tink artifact which provides support for encryption of your datastore using the <a href="https://github.com/tink-crypto/tink-java">Tink</a> library</blockquote><p>For the sake of brevity, I will assume you are generally familiar with DataStore and how it works. However, if you aren’t, the <a href="https://developer.android.com/topic/libraries/architecture/datastore">official docs</a> are a great place to get caught up.</p><p>The new androidx.datastore:datastore-tink dependency exposes the AeadSerializer class, which is created by wrapping an <em>existing</em> Serializer instance used to handle the read/write operations. During write events, the plaintext data is encrypted by AeadSerializer utilising Tink&#39;s Aead (more on that shortly!) with the encrypted bytes of the ciphertext being then passed to the existing Serializer to consume. During read events, the AeadSerializer uses the Aead and decrypts the encrypted ciphertext bytes read from the wrapped Serializer back to the original plaintext.</p><p>The example code below is lifted directly from the release notes and shows the minimum code required to use AeadSerializer in its current initial alpha release¹.</p><pre>val keysetHandle =<br>    AndroidKeysetManager.Builder()<br>        .withSharedPref(applicationContext, &quot;keyset&quot;, &quot;keyset_prefs&quot;)<br>        .withKeyTemplate(KeyTemplate.createFrom(PredefinedAeadParameters.AES256_GCM))<br>        .withMasterKeyUri(&quot;android-keystore://master_key&quot;)<br>        .build()<br>        .keysetHandle<br><br>val aeadSerializer = AeadSerializer(<br>    aead =<br>        keysetHandle.getPrimitive(<br>            RegistryConfiguration.get(),<br>            Aead::class.java,<br>        ),<br>    wrappedSerializer = SomeExistingSerializer,<br>    associatedData = &quot;settings.json&quot;.encodeToByteArray(),<br>)<br><br>val dataStore = dataStore(<br>    fileName = &quot;settings.json&quot;,<br>    serializer = aeadSerializer,<br>    scope = scope,<br>)</pre><p>But how does this actually work? 🧐 Under the hood, the cryptography is achieved via Tink’s <a href="https://developers.google.com/tink/aead">Authenticated Encryption with Associated Data (AEAD)</a> primitive, a widely adopted, industry-standard approach that combines encryption and integrity protection into a single operation.</p><p>In short, this works great for this use case as AEAD ensures that data remains confidential while also guaranteeing that neither the encrypted content nor any related unencrypted metadata, known as ‘associated data’, has been modified. It does this by producing an ‘authentication tag’ that is cryptographically bound to both the ciphertext and the associated data, allowing the verification of their integrity before decryption. If any part of the input has been altered, verification fails, and the data is considered tampered with.</p><p>Of course, this is a <em>huge</em> simplification². But, in fairness, I am not a cryptographer! 😅 Nevertheless, the takeaway here is we should sleep easier knowing the approach taken looks to be a solid one!</p><p>But<em>,</em> and you must forgive me, this all feels a little bit <em>too</em> familiar. Our old sidekick EncryptedSharedPreferences also utilised Tink under the hood, including Aead, but then suffered from years of sporadic updates to bump Tink, which led to an eventual downward spiral to what could only be described as “<a href="https://en.wikipedia.org/wiki/Abandonware">abandonware</a>” status.</p><p><em>“Well, what’s different this time?” </em>I rightfully hear you cry…</p><h3>Why is this library needed?</h3><p>It’s worth reminding ourselves that this is the very first alpha release of this new capability, so naturally, several unanswered questions will likely become clearer as time progresses.</p><p>At this time, the burning unanswered question is <em>what</em> the primary use case for this functionality is considered to be. In a past life, I used EncryptedSharedPreferences for a fintech application to ensure we met certain compliance regulations, and this feels like one of the small number of potential ‘valid’ use cases that I can personally envision. I’d certainly be interested to see what the AndroidX team considers a valid use of this library 😎</p><p>I think it’s also noteworthy that with 950 “+1” votes, the closed <a href="https://issuetracker.google.com/issues/167697691">feature request</a> for the addition of encryption was DataStore’s single most popular item within <a href="https://issuetracker.google.com/issues/167697691">Google’s issue tracker</a> by a significant margin. However, I suppose that’s <em>slightly</em> less impressive when the request had itself been open for 5½ years 🙃</p><p>So, was this just a case of ‘giving the people what they want’ or is there another motive behind this addition? That remains to be seen at this stage, but I am certainly excited to find out more as future releases become available.</p><p>For full transparency, I <em>did</em> reach out (via a mutual connection) to one of the authors of the new code to hear their perspective, but they have yet to respond as of the time of writing. I will add an update here should that change 💪</p><h3>Sure, but is this functionality for me? 🫣</h3><p>The TL;DR is <em>probably</em> <em>not</em>.</p><p>As of Android 10, file-based encryption is enforced at the OS level, and Android’s app sandboxing model ensures that, under normal conditions, one app cannot access another app’s files, including DataStore, Preferences, etc. Therefore, to compromise such files, it likely would require <strong><em>extreme</em></strong> measures such as physical access to the device, rooting the device, or having malware present in order to do so. These sorts of attacks are <em>extremely</em> difficult to pull off successfully, and unless you are working on a high-risk application with the highest level of scrutiny placed on your app’s security, I would argue it’s more than likely encrypting your DataStore’s contents is overkill and probably unnecessary.</p><p>That said, an obvious counterargument would be something akin to “it’s improving the overall security of my application”, which at first glance <em>feels</em> like a valid position.</p><p>However, as it was with EncryptedSharedPreferences, I still believe my primary reservation with these encrypted persistence APIs is that their existence often inadvertently <em>encourages</em> developers with a poor understanding of mobile security to store sensitive data on-device rather than guiding them to consider whether it should be stored at all.</p><blockquote><strong><em>Please, please, please stop storing sensitive data on-device 🙏 </em></strong><br>- Me, <em>Literally all the time</em></blockquote><p>It should hopefully go without saying that, whenever possible, storing sensitive data should <strong><em>always</em></strong> be avoided on-device. Therefore, creating APIs that make violating this principle trivial feels like a step in the wrong direction (at least to me). This is also especially true if said APIs are available <em>without</em> the associated documentation needed to advise developers of the dangers of storing sensitive data.</p><p>EncryptedSharedPreferences was super guilty of this, but let’s wait and see if androidx.datastore:datastore-tink falls foul as well 😬</p><h3>Conclusion</h3><p>While my thoughts on this new API may seem a tad pessimistic, I am aware that at this early stage, there’s plenty of scope for <strong><em>significant</em></strong> change.</p><p>For some developers, this addition will be fantastic news as the void left by EncryptedSharedPreferences ‘s departure is now seemingly being filled with an officially maintained alternative.</p><p>However, I hope the AndroidX team uses this opportunity to not only provide the missing value that EncryptedSharedPreferences enabled for the small number of legitimate use cases where encrypting DataStore data makes sense, but also make a huge effort through documentation in educating the majority of users where it <strong><em>doesn’t</em></strong>.</p><p>But with that all being said, I am reminded of a famous quote that captures my initial thoughts rather more succinctly</p><blockquote><strong><em>Those who cannot remember the past are condemned to repeat it</em></strong><br>- George Santayana, <em>The Life of Reason</em>, 1905</blockquote><p>I am quite hopeful and quietly confident that this <em>can</em> and <em>will</em> be a change for good, and the harsh lessons the EncryptedSharedPreferences saga taught us has been learned from. But I suppose in reality, only time will tell 🤞</p><p>Let me know if and what <strong>you</strong> plan to use androidx.datastore:datastore-tink<em> </em>for 💪 Happy data-storing!</p><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to contact me with any feedback at</em> <a href="https://linktr.ee/sp4ghetticode"><em>@Sp4ghettiCode</em></a> <em>and don’t forget to clap, like, share, star etc — It really helps!</em></p><h4>Footnotes</h4><p>[1]: This API may change significantly. Please check the release notes for the latest docs<br>[2]: Here’s a great <a href="https://ochagavia.nl/blog/what-the-heck-is-aead-again/">blog post by Adolfo Ochagavía</a> to learn more about AEAD ✨</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=25ca02b0b0e7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Whats new in… ‘AndroidX Text — 1.0.0-alpha01’]]></title>
            <link>https://proandroiddev.com/whats-new-in-androidx-text-1-0-0-alpha01-2de960ee921b?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/2de960ee921b</guid>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[jetpack-compose]]></category>
            <category><![CDATA[android-development]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Tue, 23 Sep 2025 14:43:13 GMT</pubDate>
            <atom:updated>2025-09-23T15:13:36.054Z</atom:updated>
            <content:encoded><![CDATA[<h3>Whats new in… ‘AndroidX Text — 1.0.0-alpha01’</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*25-NPdRFcEWVDPqIt5Q_0g.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@galen_crout?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Galen Crout</a> on <a href="https://unsplash.com/photos/white-cherry-blossom-hanging-from-a-tree-over-an-asian-style-roof-0_xMuEbpFAQ?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><h3>Prologue</h3><p>こんにちは and welcome! 👋</p><p>Before we dive into this article, we need to quickly discuss the Japanese language. Why? Well, that will all become apparent shortly!</p><p>For some context, over the last 12 months, I have slowly been learning Japanese. It’s been an incredibly rewarding experience, but one that has been no easy task for someone who <em>never really</em> mastered English (despite being born and raised in the UK 😅).</p><p>Unlike English, which uses a single character-based alphabet, Japanese has three main writing systems. These all have slightly different purposes, and a simplified overview of this is as follows:</p><ul><li>“Hiragana” which is commonly used for Japanese words and has symbols (known as kana) that represent specific syllables<br> — e.g. いぬ — pronounced ‘inu’, meaning dog 🐶</li><li>“Katakana” which is commonly used for ‘loan words’, i.e. words borrowed from languages outside of Japanese. It is similar to hiragana in that it shares the syllables it represents but uses different kana.<br> — e.g. ホットドッグ — pronounced ‘hotto doggu’, meaning hot dog 🌭 ¹</li><li>Finally, you also have “Kanji” which, as the odd one out, is derived primarily from Chinese characters. A single kanji symbol can represent an entire word or a concept, while multiple can represent a lot of information all in a very small text footprint. In fact, there are around 50,000 kanji, and even the most literate Japanese speakers know a mere fraction of them! As a novice Japanese student, <em>these</em> are what keep me up at night 🥲<br> — e.g. 犬 — pronounced ‘inu’ which, as you now know, means dog 🐶</li></ul><p>Given kanji can often be difficult even for native speakers, in certain settings, you will often find they are written down with their pronunciations in hiragana annotations above each symbol.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/917/1*ow_WtjgyKvo1TW5xKUe_ag.png" /></figure><p>This concept of showing these annotative pronunciations is known as <a href="https://en.wikipedia.org/wiki/Furigana">Furigana</a> in Japanese and <a href="https://en.wikipedia.org/wiki/Ruby_character">ruby characters</a> more generally within typography. Pretty useful right?! We’ll come back to this 😌 ²</p><p>Moving on, the other interesting (and relevant) fact about Japanese is, like English, it is commonly written and read horizontally left-to-right <em>but</em> depending on the context and medium, can be written vertically where it is then read in the opposite right-to-left direction. <br>This vertical writing style is called tategaki (縦書 / たてがき) and is most commonly used in Japanese typography within books, newspapers and manga. However, if you, like me, have ever picked up manga and tried to read it like an English book only to then spoil the surprise ending, you <em>might</em> have already realised this 😂</p><p>Let’s hold those thoughts, as with that knowledge we can now move onto the main event ✨🙇</p><h3>So, what’s actually new in AndroidX?</h3><p>On August 27th 2025, the brand new androidx.text library group was <a href="https://developer.android.com/jetpack/androidx/releases/text#1.0.0-alpha01">released</a> with a single library, androidx.text:text-vertical:1.0.0-alpha01, a new dependency providing enhanced support for ‘vertical writing capabilities’. ³</p><p>As of the time of writing (early Sept 2025), and as with most of the very earliest releases of AndroidX libraries, extremely limited documentation outside of the commits and release notes exists. However, to understand what this library introduces, let’s explore the code and the small <a href="https://android.googlesource.com/platform/frameworks/support/+/b45fe036b64ac1fcbaa71a6532feb1536e3665f0/text/text-vertical">sample app</a> that accompanied the release within the AndroidX codebase.</p><h4>What’s in text-vertical:1.0.0-alpha01</h4><p>One immediate noteworthy quirk with this new library androidx.text:text-vertical is that, unlike the majority of AndroidX libraries, it has a minSdk 36 (Android 16) requirement.</p><p>This does unfortunately mean the library currently only caters for the very latest Android version, but digging a little deeper shows this is due to the introduction of Paint.VERTICAL_TEXT_FLAG in Android 16 which is used by the library to ensure the text rendering does indeed perform vertical text layout calculations correctly. So it is worth noting that does likely mean backwards compatibility to meet AndroidX’s more general minSdk 23 (Android 6.0) support might not be forthcoming in future. However, from my testing, should the AndroidX developers find a backward compatible alternative for the flag, it <em>may</em> allow for the library to be minSdk 24 (Android 7.0).</p><p>The main entry-point for this library is the VerticalTextLayout class which, despite the name, is not to be confused with a layout in either the traditional XML/ View system sense or the more contemporary compose-based approach either. The class exposes a Builder for construction and, once built, requires consumers to call a method to draw the VerticalTextLayout result to a Canvas.</p><p>This is achieved in Jetpack Compose using an approach that is showcased within the sample app:</p><pre>@Composable<br>fun VerticalText(text: Spanned, paint: TextPaint, modifier: Modifier = Modifier) {<br>    var vTextLayout by remember { mutableStateOf&lt;VerticalTextLayout?&gt;(null) }<br>    Layout(<br>        modifier =<br>            modifier.fillMaxSize().drawWithContent {<br>                drawIntoCanvas { c -&gt;<br>                    // Draw method used to draw text to Canvas<br>                    vTextLayout?.draw(c.nativeCanvas, c.nativeCanvas.width.toFloat(), 0f)<br>                }<br>            },<br>        content = {},<br>    ) { _, constraints -&gt;<br>        vTextLayout =<br>            VerticalTextLayout.Builder(<br>                text = text,<br>                start = 0,<br>                end = text.length,<br>                paint = paint,<br>                height = constraints.maxHeight.toFloat(),<br>            )<br>                .build()<br>        layout(constraints.maxWidth, constraints.maxHeight) {}<br>    }<br>}</pre><p>At this time, there is no current official example of how to also do this using a View <em>but</em> if that is something you need, you can find my crude attempt at implementing a similar approach <a href="https://gist.github.com/ed-george/4104855f66d9e2ba720006c2ca7eedd1">here</a>. ⁴</p><h4>A Basic Example — Vertical Spans</h4><p>Within the sample application, a very simple DSL style API is applied to aid the building of the vertical text. It elegantly applies the new library’s newly supported spans which can be demonstrated using this basic example using my name and some numbers:</p><pre>@Composable<br>fun SpanExampleText(<br>    paint: TextPaint,<br>    modifier: Modifier = Modifier<br>) {<br>    VerticalText(<br>        buildVerticalText {<br>            // Basic spans examples<br>            // text(&quot;エド 123\n&quot;)<br>            // Upright(&quot;エド 123\n&quot;)<br>            // Sideways(&quot;エド 123\n&quot;)<br>            // TateChuYoko(&quot;エド 123\n&quot;)<br><br>            // Example with emphasis<br>            withStyle(textColor = Color.Red) { text(&quot;エド 123\n&quot;) }<br>            withStyle(textColor = Color.Blue) { Upright(&quot;エド 123\n&quot;) }<br>            withStyle(textColor = Color.Magenta) { Sideways(&quot;エド 123\n&quot;) }<br>            withStyle(textColor = Color.DarkGray) { TateChuYoko(&quot;エド 123\n&quot;) }<br>        },<br>        paint,<br>        modifier,<br>    )<br>}</pre><p>This renders the following output, which shows some subtle differences (and remember we read this top-to-bottom, right-to-left!)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/336/0*GGcvk5171ND9IBw_.png" /></figure><ul><li>The red text is the most basic example where the text’s paint has the Paint.VERTICAL_TEXT_FLAG applied and no other spans. As you can see, the text is displayed vertically <em>but</em> numbers are displayed vertically and rotated to display ‘sideways’ at 90 degrees. You should note that this isn’t typically how numbers are normally displayed in this writing style, but we’ll discuss that in a second!</li><li>The blue text is set to use the TextOrientationSpan.Upright() span behind the scenes and displays text in the same orientation as the previous example and now also renders numbers in the same style. As I understand it, there are occasions where this style is used but it is still not primarily how numbers are displayed.</li><li>The magenta text utilises TextOrientationSpan.Sideways() as displays all characters rotated 90 degrees to be sideways. The docs note that this “may be useful for orienting text horizontally when the surrounding text is vertical”.</li><li>The grey text displays text in a common style used to display horizontal text within a vertical flow using TextOrientationSpan.TextCombineUpright(). In Japanese, this style is known as 縦-中横 (たて-ちゅう よこ) ‘tate-chū yoko’ which translates to “horizontal in vertical” and is primarily used for legibility using half-width characters. Tate-chū yoko is how numbers are primarily displayed within a vertical span.</li></ul><h4>Final Example — Adding Emphasis</h4><p>The final example highlights two additional features the library currently supports (as well as my extremely bad Japanese, sorry!)</p><ul><li>‘Bouten’ 傍点 (ぼうてん), which are marks or dots placed above text to add emphasis to a phrase, similar to the use of italics in English</li><li>Font shear, which displays text at a 15-degree angle, akin to italics and is also used in situations where emphasis is needed</li></ul><pre>@Composable<br>fun FinalExampleText(paint: TextPaint, modifier: Modifier = Modifier) {<br>    VerticalText(<br>        buildVerticalText {<br>            text(<br>                text = &quot;私はアンドロイド開発者です。&quot;,<br>                rubyMap = mapOf(&quot;私&quot; to &quot;わたし&quot;, &quot;開発者&quot; to &quot;かいはつしゃ&quot;)<br>            )<br>            text(text = &quot;\n&quot;)<br>            TateChuYoko(text = &quot;5&quot;)<br>            text(<br>                text = &quot;歳の犬を飼っています。&quot;,<br>                rubyMap = mapOf(&quot;歳&quot; to &quot;さい&quot;, &quot;飼&quot; to &quot;か&quot;, &quot;犬&quot; to &quot;いぬ&quot;)<br>            )<br>            text(text = &quot;\n&quot;)<br>            text(<br>                text = &quot;人間の年齢に換算すると&quot;,<br>                rubyMap = mapOf(<br>                    &quot;人間&quot; to &quot;にんげん&quot;,<br>                    &quot;年齢&quot; to &quot;ねんれい&quot;,<br>                    &quot;換算&quot; to &quot;かんさん&quot;<br>                )<br>            )<br>            TateChuYoko(text = &quot;36&quot;)<br>            text(text = &quot;歳です。\n&quot;, rubyMap = mapOf(&quot;歳&quot; to &quot;さい&quot;))<br>            <br>            // Add emphasis with bouten<br>            withEmphasis(style = EmphasisSpan.STYLE_DOT) { text(text = &quot;すごい&quot;, rubyMap = mapOf(&quot;歳&quot; to &quot;さい&quot;)) }<br>            text(&quot;ですね。\n&quot;)<br>            <br>            // Add emphasis with font shear<br>            withFontShear { text(text = &quot;読んでくれてありがとう。&quot;, rubyMap = mapOf(&quot;読&quot; to &quot;よ&quot;)) }<br>        },<br>        paint,<br>        modifier,<br>    )<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/403/0*x_Y3XWNOUCIr450v.png" /></figure><h3>Is this library for me?</h3><p>Ok, let’s be honest, this is currently a niche library heavily tailored to Japanese specifics which may see limited use outside of the handful of use-cases where the specific vertical writing system is needed. So, based on my knowledge of my post’s regular audience, it’s <em>probably not</em> something you’ll be using anytime remotely soon 😅</p><p>However, as a developer with a keen interest in equality and user-friendly software, I hope you’d agree this <em>is</em> exciting to see Android evolve ever further and start allowing developers to cater for their audiences needs with a consistent experience, even if those needs are unique geographically, culturally or otherwise.</p><p>If you like me found this subject interesting, I highly recommend the Netflix engineering blog post <a href="https://netflixtechblog.com/implementing-japanese-subtitles-on-netflix-c165fbe61989">‘Implementing Japanese Subtitles on Netflix’</a> from 2017. It highlights some of the other quirks of implementing Japanese typography and was a great resource while investigating this topic.</p><p>In closing, I’m very excited to see what’s next for the androidx.text suite of libraries. I highly doubt androidx.text:word-art is coming anytime soon, but fingers crossed just in case… ⁵</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/384/0*vDwYQYvFFOmtsXjs.png" /></figure><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to contact me with any feedback at</em> <a href="https://linktr.ee/sp4ghetticode"><em>@Sp4ghettiCode</em></a> <em>and don’t forget to clap, like, share, star etc — It really helps!</em></p><h3>Footnotes</h3><p>1: After checking online, inu in katakana (イヌ) <em>is</em> occasionally used in certain specialised contexts such as biology. So, for completeness, you have now learned to write dog in all three writing styles, you are welcome!</p><p>2: If this looks useful, you should definitely check out <a href="https://github.com/mainrs/android-compose-furigana">android-compose-furigana</a> by <a href="https://github.com/mainrs">@mainrs</a> on GitHub!</p><p>3: If you read the prologue, you probably know where this is going 😌</p><p>4: I can’t remember the last time I wrote a View, so please take this with a pinch of salt 😂</p><p>5: 📎💬 <em>It looks like you’re trying to write a blog conclusion… would you like some help?</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2de960ee921b" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/whats-new-in-androidx-text-1-0-0-alpha01-2de960ee921b">Whats new in… ‘AndroidX Text — 1.0.0-alpha01’</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to have “Crystal Clear Certificates”]]></title>
            <link>https://proandroiddev.com/how-to-have-crystal-clear-certificates-950f1afa2f66?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/950f1afa2f66</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[certificate-transparency]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[mobile-security]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Mon, 21 Apr 2025 20:56:34 GMT</pubDate>
            <atom:updated>2025-04-23T13:27:54.748Z</atom:updated>
            <content:encoded><![CDATA[<h4>Securing your Android Apps using Certificate Transparency</h4><figure><img alt="Three clear wine glasses, stacked in a symetrical way" src="https://cdn-images-1.medium.com/max/1024/1*aQ1uLiG-pyFWR5xX_DRBjQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@clickmanic?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Ramakant Sharda</a> on <a href="https://unsplash.com/photos/three-clear-wine-glasses-P8IJxF4FK30?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><h3>Background</h3><p>🎉 Excellent news, everyone! After what feels like a long wait, we are <em>finally</em> seeing progress with <a href="https://certificate.transparency.dev/howctworks/">Certificate Transparency (CT)</a> being made readily available to developers via official APIs as of Android 16.</p><p>In this blog post, we’ll discuss what this means, the pros/cons, and of course, how to implement certificate transparency in your applications for Android 16+ and older devices.</p><h4>What even is Certificate Transparency? 📜</h4><p>Before discussing what changes are available in Android 16, we should take a few minutes to remind ourselves what CT <em>actually</em> <em>is</em> and why it is important via some useful background info, followed by a quick history lesson. I won’t be detailing all the nuts and bolts or how/why certificates are used, but instead some key details that will help us understand where CT becomes relevant.</p><p>Firstly, when talking about certificates, I should probably point out that I am <em>not</em> talking about paper certificates you may have received as a kid for swimming 50 meters or being top of the class. No, I am of course talking about the <strong>digital certificates</strong> that are deeply ingrained within modern secure web browsing and are used by our browsers and networking tools to verify the identity of domains. In complete layperson terms, the certificates are part of the process that underpins that little padlock icon in your browser’s address bar 🔐 You know the one right?</p><p>Next, we need to discuss entities known as <a href="https://www.techtarget.com/searchsecurity/definition/certificate-authority#:~:text=A%20certificate%20authority%20(CA)%20is,entity%20with%20a%20public%20key.">certificate authorities (CA)</a>. A CA forms an important role in this verification process as their responsibility essentially boils down to being a ‘trusted source’ that can perform the verification of both a server’s certificate and determine if secure access to it is possible. Browsers and operating systems usually ship with a list of CAs that they consider trusted sources, and along with that responsibility, there’s a mutual understanding that all CAs follow the most stringent security best practices to ensure their verification process is legitimate and trustworthy. <strong>Trust</strong> is the key word here, and with that in mind, this segues nicely into our brief history lesson.</p><h4>Certificate Transparency History 101 👨‍🏫</h4><p>In 2011, a Dutch CA called <a href="https://en.wikipedia.org/wiki/DigiNotar">DigiNotar</a> <em>was</em> hacked 😅<br>This was far from ideal for several reasons:</p><ul><li>At the time, DigiNotar was considered a trusted CA by pretty much <em>all</em> major browsers and mobile/desktop operating systems</li><li>Thanks to a pretty big lapse in their own security practices, a breach went unnoticed by DigiNotar for around 5 weeks and led to the attackers issuing around 500 fraudulent certificates for popular sites</li><li>The breach was only brought to DigiNotar’s attention when attackers used these forged certificates to perform a man-in-the-middle (MITM) attack and eavesdrop on Iranian civilians’ Gmail accounts via a fake *.google.com certificate</li><li>All affected applications (browsers/OS, etc) then had to scramble and immediately push security updates to remove DigiNotar from their trusted CA lists and prompt their users to update</li></ul><p>If you want to learn more about the DigiNotar hack, there’s a great <a href="https://open.spotify.com/episode/638vkxv3bwXDaDhmvvay9M?si=4d1ec59093424227">Darknet Diaries episode</a> which dives deeper. Give it a listen!</p><p>So, in short, DigiNotar swiftly became “DigiNoMore” (they went bust) and the landscape of secure browsing suddenly needed to change to account for any future cases of untrustworthy CAs.</p><h4>Who watches the watchers? 👀</h4><p>When the DigiNotar hack occurred, the fallout was great enough that it triggered a change in attitude towards certificates.</p><p><em>How could a fraudulent certificate be issued for a domain by a trusted CA and be spotted quickly?</em></p><p>The answer, of course, is ✨ certificate transparency ✨</p><p>The ‘transparency’ aspect is now achieved by CAs publicly logging when they have issued a new certificate to a number of log servers. Critically, these log servers are ‘append only’ and cryptographically hashed, meaning CAs can only <em>add</em> new data to them and cannot be tampered with.</p><p>The use of public log servers allows for the auditing of certificate authorities to occur, which in turn means any discrepancies can be caught quickly and dealt with in a timely fashion. Many of the popular browser vendors perform such audits, as well as large tech companies such as Google and Facebook, thus making it significantly harder for any forged or unexpected certificates to be incorrectly issued through a CA.</p><h4>Well, what about pinning? 📌</h4><p><em>Ok, so what?</em> You’ve possibly heard of “certificate pinning” before; it’s supported by Android already, and that’s probably good enough, right?</p><p>Well, no. Not quite.</p><p>Certificate pinning is different in that only a specific certificate’s public key for a given domain is checked against. This is problematic, particularly in mobile apps, as if the wrong certificate is pinned, or a developer forgets to rotate the pins before a certificate expires, the application will no longer be able to communicate with that endpoint, and an immediate app update would be required. Yikes.</p><p>In this scenario, CT works far better. When a new certificate from a CA is issued, the log server also issues a signed certificate timestamp (SCT) which can then be verified by a client. As there is no longer a reliance on the public keys of certificates, the need to release an app when certificates rotate is eliminated and a new certificate’s authenticity can be checked without disruption.</p><p>While this overview glosses over a lot of finer details, Matt Dolan’s talk <a href="https://www.youtube.com/watch?v=p0K_mIxD3a4">“Move over certificate pinning. Certificate Transparency is here!”</a> gives an <strong>excellent</strong> insight into both certificate pinning and transparency. So don’t just take my word for it!</p><h3>Android 16 Changes 🆕</h3><p>So, with a lot of preamble out of the way, what has <em>actually</em> changed as of Android 16 (API 36)?</p><p>The <a href="https://developer.android.com/privacy-and-security/security-config#FileFormat">Network Security Config file</a> now contains acertificateTransparency tag allowing CT to be enabled <em>globally</em> or <em>per domain </em>for Android 16+ devices.</p><p>Adding this to your existing security configuration is super straightforward and can be done with just a couple of additional lines.</p><p><strong>Per-Domain:</strong></p><pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br>&lt;network-security-config&gt;<br>  &lt;domain-config&gt;<br>    &lt;domain includeSubdomains=&quot;true&quot;&gt;example.com&lt;/domain&gt;<br>      &lt;certificateTransparency enabled=&quot;true&quot;/&gt;<br>  &lt;/domain-config&gt;<br>&lt;/network-security-config&gt;</pre><p><strong>Globally:</strong></p><pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br>&lt;network-security-config&gt;<br>  &lt;base-config cleartextTrafficPermitted=&quot;false&quot;&gt;<br>    &lt;certificateTransparency enabled=&quot;true&quot;/&gt;<br>  &lt;/base-config&gt;<br>&lt;/network-security-config&gt;</pre><p>While this is a quick-win, it is worth noting that enabling this feature may interfere with your setup if you are currently allowing user or custom certificates. Given that those certificates may not be public, certificate transparency <strong>will not work</strong>.</p><p>You can read the docs for further information <a href="https://developer.android.com/privacy-and-security/security-config#certificateTransparency">here</a>.</p><h4>What about pre-Android 16?</h4><p>With official Android 16+ support available long term, what support is available to enable CT for pre-Android 16?</p><p>The de facto go-to library for this is <a href="https://github.com/appmattus/certificatetransparency">Matt Dolan’s Certificate Transparency lib</a>, which provides support for Java projects as well as Android 4.4 (API 19) and above.</p><p>The library provides support for certificate transparency within WebViews via a custom <a href="https://docs.oracle.com/javase/8/docs/api/java/security/Provider.html">Java Security Provider</a> and also allows for CT with simple integrations for common networking libraries, such as OkHttp, via an HttpInterceptor.</p><p><strong>Basic integration:</strong></p><pre>val interceptor = certificateTransparencyInterceptor()<br><br>val client = OkHttpClient.Builder().apply {<br>    addNetworkInterceptor(interceptor)<br>}.build()</pre><p>Importantly, the library also attempts to address the issue of certificate revocation by <a href="https://github.com/appmattus/certificatetransparency?tab=readme-ov-file#certificate-revocation">providing an interceptor</a> to allow developers to manually define revoked certificates. As Matt points out in his README, you can read more about the problem this attempts to solve <a href="https://scotthelme.co.uk/revocation-is-broken//">here</a>.</p><h3>Summary ✨</h3><p>In conclusion, certificate transparency is certainly an upgrade to certificate pinning and is now officially supported as of Android 16+, bringing Android up-to-date with security best practices <em>and</em> iOS, which has had support since around 2016.</p><p>If you, like me, are a security-conscious developer, then enabling certificate transparency is a quick win that makes your apps more secure with minimal effort.</p><p>So, with all that said, it’s my hope you too will see the clear benefits of transparency 💪</p><h3>Thanks 🌟</h3><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to contact me with any feedback at </em><a href="https://linktr.ee/sp4ghetticode"><em>@Sp4ghettiCode</em></a><em> and don’t forget to clap, like, share, star etc — It really helps!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=950f1afa2f66" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/how-to-have-crystal-clear-certificates-950f1afa2f66">How to have “Crystal Clear Certificates”</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Here’s what we learned at Google I/O Connect Berlin]]></title>
            <link>https://medium.com/asos-techblog/heres-what-we-learned-at-google-i-o-connect-berlin-503163f8139c?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/503163f8139c</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[apps]]></category>
            <category><![CDATA[tech]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Wed, 17 Jul 2024 08:15:39 GMT</pubDate>
            <atom:updated>2025-10-02T07:57:47.205Z</atom:updated>
            <content:encoded><![CDATA[<h3>Learnings from Google I/O Connect Berlin</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7v181ROw_p_-xYoEkATKoA.jpeg" /><figcaption>📸 : <a href="https://medium.com/u/1e7c83978135">Ed Holloway-George</a></figcaption></figure><p><em>This month, Google hosted the first of its follow-up series of events for their annual Google I/O conference. In this post, </em><a href="https://sp4ghetticode.medium.com/"><em>Ed Holloway-George</em></a><em> highlights what he learned at the I/O Connect event held in Berlin, Germany.</em></p><p>As an Android developer and self-proclaimed tech nerd, the <a href="https://en.wikipedia.org/wiki/Google_I/O">Google I/O conference</a> is one of the dates I <em>always</em> look forward to on my calendar each year.</p><p>Held at the impressive Shoreline Amphitheatre in Mountain View, California, it’s usually Google’s primary showcase of all the exciting announcements they have to share across their software, hardware and other digital products. In years gone by, we’ve seen major announcements including the launch of Google Assistant, Google Home, numerous Android versions and of course, the ill-fated and slightly ahead of its time, <a href="https://en.wikipedia.org/wiki/Google_Glass">Google Glass</a>.</p><p>However, this year’s edition held on May 14th had from the offset a <em>very specific </em>focus — <strong>AI</strong>. As the hottest topic in tech right now, it comes as no surprise that Google is also going all-in with its <a href="https://ai.google/">AI offerings</a> this time around. In fact, so much so, that “AI” was mentioned <a href="https://techcrunch.com/2024/05/14/google-mentioned-ai-120-times-during-its-i-o-keynote">at least 120 times</a> during the main keynote presentation 😅 That aside, there were also many other announcements in the mobile, cloud and web spaces for developers and consumers to look forward to. If you missed any of these yourself, you should check out <a href="https://io.google/2024/">the official site</a> and catch up 👀</p><p>Whilst the main conference was primarily focused on announcements, Google also has several smaller developer-focused follow-up events known as I/O Connect. The idea behind I/O Connect events is to get the new technologies announced at the main conference in the hands of developers, have Google employees (Googlers) readily available to take questions as well as present additional content and of course, for developers from across the world to meet up and share a common passion for Google’s tech.</p><p>Being a <a href="https://developers.google.com/profile/u/spaghetticode">Google Developer Expert for Android</a>, I was fortunate enough to be invited to this year’s European instalment of I/O Connect, held in a swelteringly hot Berlin 🤒</p><p>So, to completely misquote the Ramones, “I/O let’s go!”…</p><figure><img alt="An artificial indoors river with a boat in the foreground and lush green riverbanks and a white bridge with the Google I/O Connect logo on spanning it" src="https://cdn-images-1.medium.com/max/1024/1*tX2npGr037PlrDTj35E8Xw.jpeg" /><figcaption>I’d never seen an artificial indoor river before either!</figcaption></figure><h4>What I learned at I/O Connect 24</h4><p>In my experience, there’s no such thing as a dull Google event. I/O Connect this year comes as no exception with an indoor artificial river installation being the centrepiece of the event’s location within a converted warehouse complex. With multiple auditoriums, workshop spaces and free barista-made coffee, the stage was <em>already</em> set for a great developer event.</p><p>But what did we learn? There were <a href="https://developers.googleblog.com/en/bringing-the-io-magic-to-berlin/">some amazing announcements</a>, but here’s a summary of some of my personal key takeaways!</p><ul><li><strong>Google’s investment in AI is scaling up</strong></li></ul><p>Google used I/O Connect’s keynote to <a href="https://blog.google/technology/developers/google-gemma-2/">announce their latest “Gemma 2” suite of models</a>. The newly available models boast the ability to support either 9 billion or 27 billion parameters and have performance metrics that surpass known industry leaders such as the popular Llama-3 offering from Meta. The rapid release of Google’s AI products and the mind-boggling numbers associated with them is a testament to how much effort they are focusing on this area and it continues to be at the forefront of developer’s minds.</p><p>A live demo of Google’s Gemini AI being used in developer tooling to aid the investigation of a bug in software was incredibly popular with the Keynote’s crowd and despite another AI live demo going a bit wrong, the sentiment with most is that AI is not just something to benefit end-users but something that can be used at <strong>all stages</strong> of software development.</p><p>Like many tech-centric companies, we are no strangers to AI’s benefits as we’ve previously blogged about a <a href="https://medium.com/asos-techblog/transforming-recommendations-at-asos-254b95c6a07a">real-world application of AI/ML</a> used here at ASOS and also our process of looking into <a href="https://medium.com/asos-techblog/asos-gen-ai-hack-day-a-tale-of-innovation-b1583ab545dd">new ways to use Gen AI through hackathons</a>. Google’s recent announcements have all but reinforced our belief that the future is AI ✨</p><ul><li><strong>Kotlin Multiplatform continues to thrive</strong></li></ul><p><a href="https://www.jetbrains.com/kotlin-multiplatform/">Kotlin Multiplatform (KMP)</a> are the words on many mobile developer’s lips right now. The ability to effectively share code between iOS, Android, Desktop and Web sounds almost too good to be true, but the KMP model is one that is growing in popularity and shows no signs of slowing down its adoption at scale.</p><p>Google recently announced a series of changes to some of their core <a href="https://developer.android.com/kotlin/multiplatform">Android ‘Jetpack’ libraries</a> that allows their popular libraries such as ViewModel, Paging and Room to now be used in a KMP context. I/O Connect was an opportunity to revisit these announcements, see them in action and have a discussion with Googlers about their future plans for KMP support. As it was made clear in their presentations, Google is now fully endorsing ‘KMP for shared business logic between Android &amp; iOS’ which is an exciting prospect for many mobile developers.</p><p>I am pleased to reveal that our mobile teams at ASOS have recently been exploring KMP for shared business logic between our iOS and Android apps and have been actively trialling the use of shared ASOS KMP libraries in our most recent Android release (with iOS coming very soon). If you’d like to find out more about how this went, our approach and results, then perhaps keep an eye out for a future blog post! 👀</p><ul><li><strong>Performance in mobile is still key</strong></li></ul><p>Another key area of focus within Google’s Android ecosystem right now is that of app performance. I/O Connect was no exception with hands-on workshops and tech-talks focussing on performance libraries such as <a href="https://developer.android.com/topic/performance/baselineprofiles/overview">Baseline Profiles</a> and <a href="https://developer.android.com/topic/performance/baselineprofiles/measure-baselineprofile">Macrobenchmarks</a>.</p><p>This was an awesome opportunity to chat, raise any issues and pair program directly with the Googlers involved in these libraries and had great feedback from all involved. Sadly, a conflict with another event commitment meant I wasn’t able to attend directly — but I am told it was incredibly useful!</p><p>App performance is something we are always looking to improve at ASOS and I am pleased to say we have a roadmap to introduce these libraries into the Android app in the very near future. Watch out Usain Bolt, we are coming for your speed record 🏃‍♂️💨</p><ul><li><strong>The wider tech community continues to be impressive</strong></li></ul><p>With over 100 countries represented from across Europe, the Middle East and Africa, Google’s I/O Connect event embodied the very best of the tech community and brought together people who all share a common passion; <em>To make the world a better place through technology.</em></p><p>ASOS is one of many companies that actively work with cutting-edge technologies, such as those announced at I/O, to deliver better results and experiences to our customers. We’ll continue to keep on top of the rapidly changing tech landscape and we are all excited to share more about our advancements in these areas in future posts!</p><p>In closing, I hope you found this insightful and join me in looking forward to seeing what else comes from the remaining I/O Connect events in Bengaluru — India and Beijing — China later this summer.</p><p>I hope to catch <strong>you</strong> at next year’s events wherever they might be! 🗺️</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hDKI8VlHwLK2q2fMXjeLhg.jpeg" /></figure><p><em>Hi, I am </em><a href="https://linktr.ee/sp4ghetticode"><em>Ed Holloway-George</em></a><em> an Android Lead here at ASOS and Google Developer Expert for Android. I joined the company in 2021 and when I’m not sweating buckets at developer events abroad, I can be found </em><a href="https://www.spght.dev/talks/"><em>talking</em></a><em> about Mobile Security or </em><a href="https://twitter.com/sp4ghetticode"><em>tweeting</em></a><em> pictures of my dog </em>🐶</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=503163f8139c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/asos-techblog/heres-what-we-learned-at-google-i-o-connect-berlin-503163f8139c">Here’s what we learned at Google I/O Connect Berlin</a> was originally published in <a href="https://medium.com/asos-techblog">ASOS Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Securing the Future: Navigating the deprecation of Encrypted Shared Preferences]]></title>
            <link>https://proandroiddev.com/securing-the-future-navigating-the-deprecation-of-encrypted-shared-preferences-91ce3c20ae8d?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/91ce3c20ae8d</guid>
            <category><![CDATA[jetpack]]></category>
            <category><![CDATA[mobile-security]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[security]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Tue, 28 May 2024 14:13:53 GMT</pubDate>
            <atom:updated>2024-05-28T14:13:53.204Z</atom:updated>
            <content:encoded><![CDATA[<h3>Securing the Future: Navigating the Deprecation of Encrypted Shared Preferences</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1ayXeepgVkEPLlrVJ5WnxQ.jpeg" /><figcaption>Photo credit: <a href="https://unsplash.com/photos/brown-metal-padlock-BwnrxTVn_uU">Annie Spratt</a></figcaption></figure><h4>Background</h4><p>Sad news everyone. Very recently the Jetpack Security (JetSec) team at Google <a href="https://twitter.com/Sp4ghettiCode/status/1786033489675944311">quietly deprecated</a> the androidx.security:security-crypto dependency (aka “JetSec Crypto”), the library responsible for popular classes such as EncryptedSharedPreferences</p><p>The knock-on effect is that this move is causing some developers to ask <em>“What does this deprecation mean for my app and its security?”</em> and begin frantically looking into alternatives 😬</p><p>In this post, we’ll take a look at what this news <em>really</em> means for those who have previously embraced EncryptedSharedPreferences and also for those who may have been looking to adopt it.</p><h3>Ed Holloway-George 🍝 on Twitter: &quot;RIP JetSec Crypto 😢 You were a fun little library with big ambitions#AndroidDev pic.twitter.com/9sqt7RT07L / Twitter&quot;</h3><p>RIP JetSec Crypto 😢 You were a fun little library with big ambitions#AndroidDev pic.twitter.com/9sqt7RT07L</p><h4>A recap on JetSec Crypto 🔏</h4><p>I’ve previously talked about JetSec Crypto <a href="https://www.spght.dev/articles/04-06-2022/owasp-m2">in more detail before</a>, but in case you missed that, let’s quickly re-acquaint ourselves.</p><p>The library began life in alpha releases in May 2019, went stable 1.0.0 in April 2021 and has seen infrequent 1.1.0 pre-releases from that date forward before the recent deprecation.</p><p>JetSec Crypto consists of only a small handful of classes, primarily wrappers around popular storage mechanisms, (i.e. EncryptedSharedPreferences and EncryptedFile) that offer convenient methods to encrypt/decrypt the data held within them. The library also provides a wrapper around Google&#39;s cryptography library <a href="https://developers.google.com/tink">Tink</a> through the MasterKeys class which, via a straightforward API, allows developers to create secure keysets for the encryption process utilising best practices for Android.</p><p>Despite being a relatively infrequently updated and small library, JetSec Crypto has seemingly been widely adopted, thanks namely to the ‘added security’ it provides and the simplistic familiar APIs.</p><p>So in light of this news, what are the cases for and against using EncryptedSharedPreferences in 2024 post-deprecation?</p><h4>Why NOT JetSec Crypto in 2024?</h4><p>Firstly, why would we not want to use JetSec Crypto post-deprecation?</p><p>To some extent, using EncryptedSharedPreferences should be seen as a red flag that <em>perhaps</em> your app isn’t following security best practices in the first place 🚩</p><p>Ask yourself, are you using the library for storing data locally on a device that’s <strong>sensitive</strong>? This would include data such as personally identifiable information, financial data, credentials, etc. If you are, <em>should you be</em>? Chances are, <strong>no</strong> <strong>— you shouldn’t</strong>. Any sensitive data should ideally be server-side, only fetched when required, and require some form of authentication to access.</p><p>So if EncryptedSharedPreferences was your solution to storing sensitive data on the device, you might have bigger problems…</p><p>Additionally, now the library is deprecated it’s certainly worth considering that there will (likely) be no further updates. Any <a href="https://issuetracker.google.com/u/1/issues?q=status:open%20componentid:618647&amp;s=created_time:desc">existing bugs</a>, performance issues, etc will remain and <strong>not</strong> be patched.</p><p>That said, given this library is so small there’s no reason to fret, as you could consider pulling the <a href="https://android.googlesource.com/platform/frameworks/support/+/7905a13172f3d0479aef27e86a7b83d9c4d25640/security/security-crypto">key classes out of the current version</a> and manually maintaining them within your project directly. <br>⚠️ However, this approach is not recommended unless you know what you’re doing! Doing this and <em>just</em> keeping Tink up to date is a good start, but be aware that any additional changes may put your app at risk if you aren’t already knowledgeable about cryptography and the Android APIs used by JetSec Crpyto. You <strong>have</strong> been warned!</p><p>Finally and arguably most importantly, you might just need to ask yourself “What does EncryptedSharedPreferences <em>really</em> do for me that SharedPreferences doesn’t?”</p><p>It sounds silly, but given SharedPreferences are held locally on the device in the app’s own folder which isn’t accessible by default, is EncryptedSharedPreferencesreally adding that much. Additionally, as of Android 10 (Q), all devices encrypt user data on the filesystem by <em>default</em>, adding another level of security.<br>A common rebuttal to this is “Well, what about rooted users?” and yes, a user with root access <em>would</em> be able to read cleartext SharedPreferences but once the device’s integrity is compromised is <em>anything</em> really safe, EncryptedSharedPreferencesincluded? Many experts (and I), would argue that it isn’t. 🥲 Some food for thought there!</p><h4>Why JetSec Crypto in 2024?</h4><p>Ok, so we’ve heard a few reasons why EncryptedSharedPreferencesmight not be the best choice going forward. However, there are undoubtedly still some positives and a handful of reasons to use it!</p><p>Firstly, if you have already adopted EncryptedSharedPreferences there’s certainly no <em>immediate</em> need to move away from it or seek an alternative. The library won’t stop working overnight and you can still manually update the transitive Tink dependency via your project’s Gradle dependency management. If it’s working for you in the short term, great! Just be aware that in the long term, there will be no updates. If that’s an acceptable level of risk for you and your app, then you are all good 😊</p><p>Another often-overlooked reason why JetSec Crypto is so popular is the APIs are straightforward and follow the best practices for cryptography in Android. I personally would trust that the JetSec team knew what they were doing and as such, EncryptedSharedPreferences is a very attractive option if I ever find myself needing to secure data locally. This won’t change with deprecation and I’d always prefer (and recommend) to use this over rolling my own solution. That’s never a good idea…</p><p>Finally, you might also just have no choice and <em>need </em>to use EncryptedSharedPreferences 🥲 What do I mean? Well, there are a number of industries (FinTech, Banking, Healthcare, etc) that have regulations that all businesses <strong>must</strong> abide by. Depending on your location or the markets your apps are available in, you may well be bound by laws or regulations that dictate any data stored locally <strong>must</strong> be encrypted to some degree. If you are wondering if this applies to you, then you should probably speak to your legal department as I’m not a lawyer, I’m just a lowly developer 😅</p><h4>The future 🔮</h4><p>Unfortunately, I don’t have a crystal ball so I can’t guarantee what comes next. However, it’s been clear from the last handful of major Android releases that security continues to be at the forefront of Google’s mind and providing developers with the tooling and resources to implement secure best practices is not likely something that will disappear any time soon.</p><p>I still have my fingers crossed that the JetSec team releases some guidance of their own shortly, but until then we’ll need to wait patiently to see if something completely brand-new comes along and whether we learn for certain whether JetSec is truly dead and buried.</p><h4>Conclusion</h4><p>Ultimately, as the custodian of your own applications, it is <em>your</em> decision to make whether EncryptedSharedPreferences and JetSec Crypto is the right choice for you and it’s my hope this post will help you make a better-informed decision!</p><p>In any case, JetSec Crypto was a great little library that we learned a lot from ✨ I look forward to seeing what comes next in the Android Security world!</p><p>As always, I’ll be the first to let you know when we find out more…</p><h4>Thanks 🌟</h4><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to contact me with any feedback at </em><a href="https://linktr.ee/sp4ghetticode"><em>@Sp4ghettiCode</em></a><em> and don’t forget to clap, like, share, star etc — It really helps!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=91ce3c20ae8d" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/securing-the-future-navigating-the-deprecation-of-encrypted-shared-preferences-91ce3c20ae8d">Securing the Future: Navigating the deprecation of Encrypted Shared Preferences</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The elephant in the room: How to update Gradle in your Android project correctly]]></title>
            <link>https://sp4ghetticode.medium.com/the-elephant-in-the-room-how-to-update-gradle-in-your-android-project-correctly-09154fe3d47b?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/09154fe3d47b</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[gradle]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[build-tool]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Mon, 27 May 2024 20:23:45 GMT</pubDate>
            <atom:updated>2024-05-28T13:14:47.137Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="A black and white image of an African elephant’s head" src="https://cdn-images-1.medium.com/max/1024/1*TNmRyIEJ_B7FvoMzR42DRQ.jpeg" /><figcaption>Image credit: <a href="https://unsplash.com/photos/elephant-during-daytime-FNVYos3W0AY">James Hammond</a></figcaption></figure><h4>A quick introduction 🤗</h4><p>I don’t want to alarm you, but if you’ve ever updated the Gradle version in your Android project, you’ve <em>probably</em> done it incorrectly at least once 🥲</p><p><strong>How do I know this?</strong> Well, first and foremost I was also guilty of this for a long time but since repenting and learning the ‘correct way’, I have seen it occur in many large open-source projects too (and of course, authored <a href="https://github.com/duckduckgo/Android/pull/4277">fixes</a> to address it).</p><p>But don’t just take my word for it, here’s a poll I conducted on X (or ‘Twitter’ for those living under a rock)</p><iframe src="https://cdn.embedly.com/widgets/media.html?type=text%2Fhtml&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;schema=twitter&amp;url=http%3A//x.com/Sp4ghettiCode/status/1780620090666320022&amp;image=" width="500" height="281" frameborder="0" scrolling="no"><a href="https://medium.com/media/1f79570f4b0806cf6c67e08c7ec3d251/href">https://medium.com/media/1f79570f4b0806cf6c67e08c7ec3d251/href</a></iframe><p>What’s the problem you may ask? In this post, I hope to answer that question and ensure you update Gradle correctly every time going forward!</p><h4>How to not update Gradle 🔥</h4><p>Let’s consider a real-world scenario. You’ve noticed Gradle has <a href="https://gradle.org/releases/">just released</a> a new version (which at the time of writing is version 8.7). Your app’s project is behind that version, and you want to update it.</p><p>Most developers, my past self included, would probably open gradle-wrapper.properties and just simply change the distributionUrl property as follows:</p><pre>diff --git a/src/some-project/gradle/wrapper/gradle-wrapper.properties b/src/some-project/gradle/wrapper/gradle-wrapper.properties<br>index a3dc3ba8fe3..d4b79aa7c54 100644<br>--- a/src/some-project/gradle/wrapper/gradle-wrapper.properties<br>+++ b/src/some-project/gradle/wrapper/gradle-wrapper.properties<br>@@ -1,6 +1,6 @@<br> distributionBase=GRADLE_USER_HOME<br> distributionPath=wrapper/dists<br>-distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip<br>+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip<br> networkTimeout=10000<br> validateDistributionUrl=true<br> zipStoreBase=GRADLE_USER_HOME</pre><p><em>Alternatively</em>, you could also use the wrapper task directly by using a command similar to ./gradlew wrapper --gradle-version=8.7 which will effectively just update the gradle-wrapper.properties for you. Nice.</p><p>Job done right? Well no, not really, and hopefully a handful of observant readers have already spotted the issue.</p><h4>How to (properly) update Gradle ✨</h4><p>To ensure you migrate to the new version correctly, you need to run the gradlew wrapper command up to <strong>two times</strong>,<strong> </strong>depending on the update method you previously chose above.</p><p>While editing your gradle-wrapper.propertiesfile will ensure your wrapper will correctly pull the new version’s distribution the next time Gradle is run, it will, unfortunately, leave your wrapper files themselves (i.e. the gradle-wrapper.jar and gradlew scripts) untouched and <em>out-of-date</em> 😬 Yikes!</p><p>The same applies to calling wrapper directly, the first pass will download the new distribution, but won’t touch your gradle-wrapper.jar and gradlew files unless you run it <em>a second time</em>. 🥲</p><p>Why is this? Simply, the wrapper can only write the wrapper files for its <em>own version</em>, so if you haven’t previously pulled the distribution, it requires another call once it is downloaded to create/update the relevant wrapper files for the new version.</p><p>Confused? So was I. However, the <a href="https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:upgrading_wrapper">Gradle documentation</a> <em>does</em> mention this explicitly:</p><blockquote>If you want all the wrapper files to be completely up-to-date, you will need to run the wrapper task a second time.</blockquote><p>D’oh.</p><h4>Why bother?</h4><p>Ok, this is something you might have missed, but <em>why</em> should we go to the effort of doing this?</p><p>Indeed, using an outdated Gradle wrapper won’t stop your project from building, but to ensure you get the very best from Gradle you’d probably want to make sure you’re using the latest and greatest wrapper. This ensures you reap the benefits of doing so, including bug fixes, security updates, performance improvements etc.</p><p>For the sake of an extra call to ./gradlew wrapper it seems pretty worth it to me!</p><h4>But wait, there’s more… 😱</h4><p>If you’ve read my posts before, you’ll know I tend to talk a lot about <a href="https://www.spght.dev/archive/">mobile security</a> and may have previously seen me present <a href="https://www.youtube.com/watch?v=loIWpxsMNkg">how to secure Gradle</a> (now also available as a <a href="https://www.spght.dev/articles/23-07-2023/gradle-security">blog post</a>). Therefore, it would be quite rude of me not to shoe-horn a little sprinkling into this!</p><p>By adding a gradle-distribution-sha256-sum field to the ./gradlew wrappercall with a SHA256 checksum, whenever the distribution is downloaded, the checksum of that file will be compared with the string in the supplied property and the build will fail should they differ. As these distribution <a href="https://gradle.org/release-checksums/">checksums are known</a> for each Gradle version, any unauthorized changes to the Gradle distribution you downloaded will be caught and you will have just saved yourself from a supply-chain attack!</p><p>If you wanted to upgrade to Gradle 8.7, you could call the following:</p><pre>./gradlew wrapper --gradle-version=8.7 --distribution-type=bin --gradle-distribution-sha256-sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d</pre><p>🚨 If you do, make sure you run this <strong>twice</strong>. Once to update the distribution and expected SHA-256 and <em>again</em> to update the wrapper files themselves</p><p>For more on this, make sure you check out my talk!</p><h4>TL;DR</h4><p>If you’re lazy (like me) and skipped to the end, we can summarise the above as follows!</p><ul><li>If you update Gradle via editing your gradle-wrapper.properties file, make sure you always run gradlew wrapper after</li><li>If you normally update Gradle via the gradlew wrapper directly, make sure you run it <em>twice</em>! You also get bonus points from your fellow developers for using the gradle-distribution-sha256-sum field 💞</li></ul><p>Finally, you can also check your wrapper is the expected version by running ./gradlew wrapper --version(Thanks to <a href="https://medium.com/@xoangon?source=responses-----09154fe3d47b----0----------------------------">Xoangon</a> for pointing this out)</p><p>Of course, if you want to learn <em>more</em> about the Gradle wrapper, check out the <a href="http://wrapper --gradle-version=8.7 --distribution-type=bin --gradle-distribution-sha256-sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d">documentation</a> ✨</p><h4>Thanks 🌟</h4><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to contact me with any feedback at </em><a href="https://linktr.ee/sp4ghetticode"><em>@Sp4ghettiCode</em></a><em> and don’t forget to clap, like, share, star etc</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=09154fe3d47b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What’s the buzz about the 2024 OWASP Mobile Top 10 changes?]]></title>
            <link>https://proandroiddev.com/whats-the-buzz-about-the-2024-owasp-mobile-top-10-changes-83c93f765bd3?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/83c93f765bd3</guid>
            <category><![CDATA[mobile-security]]></category>
            <category><![CDATA[owasp-top-10]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[owasp]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Mon, 26 Feb 2024 15:17:08 GMT</pubDate>
            <atom:updated>2024-02-26T15:17:08.907Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5uQQl3sDBjr_JXKGgkxYNg.jpeg" /><figcaption>Photo credit: <a href="https://unsplash.com/photos/brown-insect-5nH0Hh78Nh4">Max Muselmann</a></figcaption></figure><h3>Introduction</h3><p>First and foremost, a very happy 2024 to you 🎉 I <em>know</em> it’s February already, but given this is my first post of the year I hope you can forgive me for being slightly late.</p><p>That aside, the good news is this year has already kicked off with some exciting news in the mobile security space. In this post, we’ll discuss the changes that have been made to the OWASP Mobile Top 10 for 2024 and see what this means for <strong>you</strong>, the security-conscious developer!</p><p>For those that are already familiar with my OWASP Mobile Top 10 talks or posts, you can totally skip ahead to the more juicy “Top of the OWASP” section and find out what all the excitement is about. However, if you aren’t familiar or would just like a quick refresher, stick around as I recap <em>what</em> OWASP is and why the recent changes they made are a <strong>big deal</strong> in mobile security circles.</p><h3>What the heck is OWASP? 🐝</h3><p>If you are new to mobile security, my blog posts, or have just been living under a rock for some time, you might not be aware of OWASP and the excellent work they do.</p><p>Founded in 2001, the <a href="https://owasp.org/">Open Worldwide Application Security Project (OWASP) Foundation</a> is a non-profit that provides documentation, tooling, educational resources and many other community-based services to advance and educate people in software security practises. They are widely acknowledged to be the leading application security community in our field and have many dedicated volunteers within their various projects, including those that touch upon mobile security.</p><p>Part of the guidance OWASP provides is their ‘Top 10’ threat lists. These are lists of OWASP’s perceived top 10 threats to the security of particular areas and an incredibly useful resource for any developer ¹.</p><p>I have previously put out plenty of content surrounding their past guidance, so if you’d like to learn more, please check my <a href="https://www.spght.dev/talks/">talks page</a> and my previous <a href="https://www.spght.dev/categories/#OWASP">OWASP-related blogs</a> for far greater details and more relevant links.</p><p>If you are a more hands-on learner, there’s also a <a href="https://github.com/ed-george/owasp-top-five">companion app</a> to my OWASP talks that demonstrates some of the topics outlined.</p><p>Regardless, 2024 sees the most significant modifications to the Mobile Top 10 in nearly a decade, so without further ado let’s see what has changed 👀</p><h3>“Top of the OWASP” ✨</h3><p>After a long consultation period and several revisions, the newly released <a href="https://owasp.org/www-project-mobile-top-10/">OWASP Mobile Top Ten 2024</a> is the third and latest major revision of the Mobile Top Ten list since its initial release in 2014.</p><p>The 2024 release now supersedes the 2016 release and brings some noticeable changes that better reflect the present mobile security landscape, including four brand-new threat categories and a complete re-ordering of threats.</p><p>This is all well and good, but what has <em>actually</em> changed and what does it all mean? 😅 Well, in true Billboard chart style (or for me as a Brit, <a href="https://en.wikipedia.org/wiki/Top_of_the_Pops">Top of the Pops</a>), let’s very briefly discuss each threat in reverse order starting at number 10!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/384/1*9ESds38QHiOyqz_CkOXM7A.gif" /><figcaption><a href="https://www.youtube.com/watch?v=xWu0OmahYmc">I can hear the theme song…</a></figcaption></figure><h4>#10: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m10-insufficient-cryptography.html">Insufficient Cryptography</a> ⬇️</h4><p>Moving down from 2016’s 5th spot, Insufficient Cryptography is the threat posed to mobile apps by poor adoption of modern cryptography best practices. This could be through implementing algorithms that are deemed insecure (SHA-1, MD5, etc), not using secure data transport (HTTPS) or perhaps even by not adding delicious salt to your keys ² 🧂.</p><p>When utilising cryptography, ensure you follow the best practices for your particular needs such as using algorithms like <a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a> with <em>at least</em> 128-bit block size or <a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)">RSA</a> with<em> at least</em> 2048 bits. If in doubt, defer to a professional or utilise trusted tools such as Google’s <a href="https://developers.google.com/tink">tink</a> library.</p><p>Stay tuned to my blog for a post on this in the future (I hope) ³.</p><h4>#9: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m9-insecure-data-storage.html">Insecure Data Storage</a> ⬇️</h4><p>Another big mover from 2016’s list is Insecure Data Storage which moves from the second spot, right down to 9th. Ouch 😣</p><p>Your apps may be vulnerable to Insecure Data Storage if they are printing any data (including network calls ⁴) to logs, storing passwords or tokens, creating temporary files or even just using standard storage techniques such as SQL databases or Shared Preferences.</p><p>I’ve covered Insecure Data Storage in detail before, so be sure to <a href="https://www.spght.dev/articles/04-06-2022/owasp-m2">check out my post on it</a> and ensure your app’s data is stored safely &amp; securely.</p><p>As always, it’s worth reiterating that it is a best practice to avoid storing sensitive data on a device whenever possible!</p><h4>#8: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m8-security-misconfiguration.html">Security Misconfiguration</a> ⬆️</h4><p>On the rise, from the 10th spot is Extraneous Functionality under its new moniker of ‘Security Misconfiguration’.</p><p>If you are aware of the concept of ‘RTFM’ ⁵, then you might be able to figure out what this threat is. It’s often caused by developers using incorrect settings in production builds, requesting elevated access or permissions when it’s not required or maybe exposing functionality that was originally intended to be internal to the application.</p><p>Documentation can often be your friend. Don’t neglect to read it. 🥲 Grab a coffee and get stuck in!</p><h4>#7: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m7-insufficient-binary-protection.html">Insufficient Binary Protections</a> ⬆️</h4><p>In a similar vein to famous bands like Cream, Audioslave or Atoms for Peace, by forming a proverbial “supergroup”, 2016’s 8th and 9th spots (Code Tampering &amp; Reverse Engineering) have now combined and moved up the chart to 7th. 😎</p><p>Binary Protection focuses on ensuring your app’s binaries (i.e. your .apk/.aar for Android or .ipa for iOS) do not leak information or can be repackaged. If you are not obfuscating your app correctly, or utilising integrity checks, you may find attackers can reverse engineer or potentially redistribute your apps with malicious code injected.</p><p>I highly recommend my good friends at <a href="https://www.guardsquare.com/">Guardsquare</a> and their excellent tools (e.g. <a href="https://www.guardsquare.com/dexguard">DexGuard</a> and <a href="https://playground.proguard.com/">Proguard Playground</a>) to help keep your app safe from these particular threats. Alternatively investing time into learning more about R8 and the Google Play Integrity API may also benefit you!</p><h4>#6: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m6-inadequate-privacy-controls.html">Inadequate Privacy Controls</a> 🆕</h4><p>A brand new entry at number 6 is ‘Inadequate Privacy Controls’.</p><p>If your app handles a user’s personally identifiable information, i.e. data like full names, precise location, financial details, sexual orientation, etc, which in the wrong hands could be used to impersonate/harass them or possibly commit fraud, then this may apply to you! 🥸</p><p>Ensure your app is <em>never</em> storing or logging PII locally and you only ever request/transfer the <em>minimal </em>amount of information from the user to perform your app’s functionality. This will drastically reduce the chance of PII potentially being exposed through weaknesses in your storage or data transfer.</p><p>For example, should a cinema booking app <em>require</em> your sexual orientation or your <strong>precise</strong> location to book tickets? Probably not right! It would be far better to instead request a coarse location to find nearby cinemas and allow the user the option of supplying further personal details to serve recommendations, while also allowing them to opt out at a later date.</p><h4>#5: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m5-insecure-communication.html">Insecure Communication</a> ⬇️</h4><p>Another mover! 2016’s number 3 Insecure Communication falls two places to 5th.</p><p>These are the threats associated with the transfer or receiving of data. Most applications will be doing that via the internet, but your apps may utilise other communication methods such as NFC or Bluetooth. When there’s data communication, you can bet your last dollar there are risks associated with that!</p><p>I won’t go into more detail here, as I have <a href="https://www.spght.dev/articles/12-08-2022/owasp-m3">previously blogged</a> about Insecure Communication, so be sure to check that out.</p><h4>#4: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m4-insufficient-input-output-validation.html">Insufficient Input/Output Validation</a> 🆕</h4><p>A brand new entry for number 4 sees us visit the topic of user input and outputs.</p><p>It’s incredibly important to ensure both your mobile app and APIs are correctly sanitizing user input when it’s communicated or when it is used as an output 🛁 Failure to do so can potentially lead to threats such as SQL injection or Cross Site Scripting (XSS) which may be used to expose sensitive user data or in more extreme circumstances compromise a device. Make sure you are ensuring you are getting the values and format you expect and discard anything that doesn’t meet that criteria.</p><p>Do you remember the <a href="https://www.youtube.com/watch?v=hJLMSllzoLA">‘Effective Power’</a> or the <a href="https://www.youtube.com/watch?v=jC4NNUYIIdM">‘Black Spot’</a> messages that circulated on WhatsApp? These were issues caused by specifically crafted inputs that when outputted in WhatsApp messages were designed as a ‘Denial of Service’ of sorts. — Could sanitisation have saved the day here? Quite possibly!</p><p>In short, by being cautious of I/O, you can sleep easy knowing ‘Little Bobby Tables’ won’t be causing you any issues ⁶.</p><h4>#3: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m3-insecure-authentication-authorization.html">Insecure Authentication/Authorization</a> ⬆️</h4><p>A combo of the previous 4th and 6th places sees insecurities surrounding authentication and authorization make the new 3rd spot.</p><p>To avoid any confusion given the similarity in naming, authentication is the act of verifying the user is <em>who they say they are</em> while authorization is the act of verifying the user <em>has the role(s) or credentials</em> to access a particular resource.</p><p>In both cases, it’s recommended that checks for authentication and authorization are always made server-side to avoid vulnerabilities introduced through binary modification or other means.</p><p>If you are communicating with APIs that require authorization, ensure you are using revocable tokens that are tied to the device so tokens can be revoked by users if their device is lost/stolen. Ensure tokens are refreshed periodically and your backend team are correctly authenticating when authorizing access to restricted resources!</p><p>Again, for more info on Insecure Authentication, you can <a href="https://www.spght.dev/articles/31-08-2023/owasp-m4">check out my previous blog</a> on the subject 🤠 Another will follow in due course for Insecure Authorization.</p><h4>#2: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m2-inadequate-supply-chain-security.html">Inadequate Supply Chain Security</a> 🆕</h4><p>A new entry for the 2nd spot sees the focus shift onto the tools and processes we use to build our apps.</p><p>A ‘supply-chain attack’ is an attack on the tooling you use, to introduce vulnerabilities, insecurities or malicious code into the tooling without being detected. It <em>could</em> be done internally within your organization by a rouge employee, or perhaps externally by a malicious actor who has gained privileged access to a system or tooling.</p><p>To protect against it, a thorough code review process should be part of your regular workflow and regular audits of access control to your supply chain should be performed. You should monitor (or limit) your app’s dependencies and ensure they are also regularly reviewed to avoid introducing vulnerabilities.</p><p>If you haven’t checked it out already, I have both previously <a href="https://www.spght.dev/articles/23-07-2023/gradle-security">blogged</a> and <a href="https://www.droidcon.com/2023/07/31/how-to-stop-the-gradle-snatchers-securing-your-builds-from-baddies/">talked</a> on the subject of supply chain attacks and how to mitigate them when working with Gradle.</p><h4>#1: <a href="https://owasp.org/www-project-mobile-top-10/2023-risks/m1-improper-credential-usage.html">Improper Credential Usage</a> 🆕</h4><p>Drumroll please 🥁 The biggest threat to mobile security, as determined by OWASP is… <strong>Improper Credential Usage</strong></p><p>This is a catch-all category for cases where there is improper security surrounding credentials, applying to the user’s credentials, API keys and everything in between!</p><p>In an alarming 2021 report, an estimated 1 in 200 apps were estimated to be leaking AWS credentials through hardcoded API keys</p><blockquote>Researchers from CloudSek, a cybersecurity vendor based in India, said that a study of some 8,000 apps found that around 0.5%, or one in every 200 mobile apps, contained hardcoded private keys for the APIs that the apps use to communicate with AWS services</blockquote><blockquote>Source: <a href="https://www.techtarget.com/searchsecurity/news/252500361/Popular-mobile-apps-leaking-AWS-keys-exposing-user-data#:~:text=Researchers%20from%20CloudSek%2C%20a%20cybersecurity,to%20communicate%20with%20AWS%20services.">TechTarget</a> &amp; <a href="https://www.cloudsek.com/whitepapers-reports/mobile-apps-exposing-aws-keys-affect-100m-users-data">CloudSek</a></blockquote><p>An exposed API key or hard-coded credential <em>could </em>have devastating outcomes. The leaking of these sorts of credentials has previously caught out major companies such as Uber, Verizon, Accenture and many more, allowing for data breaches where customer data including PII and payment details have been exposed 😅 In general, <em>any</em> sensitive data that needs to be stored locally should always be encrypted and the keys used for encryption should be securely stored within a hardware-backed keystore.</p><p>This all sounds scary, but avoiding falling foul of improper credential handling yourself is fairly straightforward. Do not store user credentials such as passwords on the device (ever!), ensure you routinely rotate any third-party API keys and ensure you always transmit credentials securely via HTTPS. Simples!</p><h3>In Conclusion… 🐝</h3><p>In conclusion, while there’s been some significant movement between 2016’s and 2024’s list, as a security-conscious developer you should be <em>always</em> monitoring your applications for potential threats regardless of their position. The Top 10 might have changed, unfortunately, the reality that mobile security is not overly well understood by many developers has not. By learning more and sharing this knowledge, you can make a difference in changing that!</p><p>If there’s to be one takeaway from this post, please make sure you and your teammates are clued up on the potential threats to mobile applications (through great resources like the MASVS or by reading my blogs!) and consider integrating tools such as <a href="http://appsweep.guardsquare.com">AppSweep</a>, <a href="https://github.com/MobSF/Mobile-Security-Framework-MobSF">MobSF</a>, <a href="https://snyk.io/">Snyk</a> or <a href="https://www.sonarsource.com/products/sonarqube/">SonarQube</a> into your build pipelines to continuously check your code/binaries for these issues.</p><p>Well done for making it to the end! I hope you have a fantastic and secure 2024 🥰 🔐</p><h3>Thanks 🌟</h3><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to tweet me with any feedback at </em><a href="https://twitter.com/sp4ghetticode"><em>@Sp4ghettiCode</em></a><em> and don’t forget to clap, like, tweet, share, star etc</em></p><h4>Further Reading</h4><ul><li><a href="https://github.com/ed-george/owasp-top-five">owasp-top-five Companion App</a> (2016 edition)</li><li><a href="https://owasp.org/www-project-mobile-top-10/">OWASP Mobile Top Ten 2024</a></li><li>Mobile Application Security Verification Standard: <a href="https://mas.owasp.org/MASVS/">MASVS</a></li><li>Mobile Application Security Testing Guide: <a href="https://mas.owasp.org/MASTG/">MASTG</a></li></ul><h4>Footnotes</h4><p>[1]: If you <em>are</em> indeed a security-focused mobile developer, you should certainly pay particular attention to the updated <a href="https://mas.owasp.org/MASVS/">MASVS</a> and <a href="https://mas.owasp.org/MASTG/">MASTG</a> to apply and test your mobile app’s security model.</p><p>[2]: Nothing to do with sodium chloride. A <a href="https://en.wikipedia.org/wiki/Salt_(cryptography)">salt</a> in this context is randomised data that should be concatenated to plaintext before being hashed to ensure different hash values are generated, even if the entered plaintext is the same multiple times!</p><p>[3]: Annoyingly, I had the Insufficient Cryptography post mostly written before the 2024 Top 10 was finalized when it was in the 5th spot, not the 10th. (Whose idea was a 10-part blog series anyway!?)</p><p>[4]: <em>Please</em> stop logging your network calls in production. It’s 2024. 🥲</p><p>[5]: The ‘F’ is for <em>fricking </em>right 😅</p><p>[6]: <a href="https://xkcd.com/327/">https://xkcd.com/327/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=83c93f765bd3" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/whats-the-buzz-about-the-2024-owasp-mobile-top-10-changes-83c93f765bd3">What’s the buzz about the 2024 OWASP Mobile Top 10 changes?</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Here’s what we got up to this month in Tech Develops…]]></title>
            <link>https://medium.com/asos-techblog/heres-what-we-got-up-to-this-month-in-tech-develops-0f8a9f3adf81?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/0f8a9f3adf81</guid>
            <category><![CDATA[people]]></category>
            <category><![CDATA[culture]]></category>
            <category><![CDATA[self-improvement]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Thu, 19 Oct 2023 16:35:47 GMT</pubDate>
            <atom:updated>2023-10-19T16:43:00.022Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Y15fNrBQsANgpXlC" /><figcaption>Photo by <a href="https://unsplash.com/@marvelous?utm_source=medium&amp;utm_medium=referral">Marvin Meyer</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><em>This month, the tech team have been hard at work improving their skills and getting their hands dirty through our ‘Tech Develops’ initiative. In this post, </em><a href="https://medium.com/u/1e7c83978135"><em>Ed Holloway-George</em></a><em> highlights some examples of what the team has been doing in their own words!</em></p><p>Working at ASOS certainly has its benefits. In one of our <a href="https://medium.com/asos-techblog/perks-of-working-asos-3917ebdd03f">recent blog posts</a> by <a href="https://medium.com/u/9c78232bd527">Leah Wolstenholme</a>, we showcased some of the perks that <em>any</em> ASOS employee can expect when they join. However, on top of these, there are also some unique perks for our tech team members!</p><p>“Tech Develops” is our monthly self-learning day for the tech team. Whether it’s joining teammates to create something innovative to present back to the team, or using the time to learn something completely new, Tech Develops is a time when the tech team down-tools, clears their diaries and focuses on developing their skills in a way of their own choosing.</p><p>This month was slightly different in that Tech Develops, which <em>usually</em> happens on the last Friday of every month, was moved to coincide with ASOS Develops over a two-day period (For more on ASOS Develops, see Leah’s previous <a href="https://medium.com/asos-techblog/perks-of-working-asos-3917ebdd03f">post</a>!).</p><p>With double the fun this time around, here are some highlights of what some of our teams got up to!</p><h3>Native Apps</h3><p>The Native Apps team at ASOS consists of engineers working on our Android and iOS mobile applications. When they aren’t arguing about which platform is better <em>(Editors note: It’s Android by the way </em>😉<em>)</em>, they spend their Tech Develops looking into all sorts of tech to make our apps and processes better.</p><p><strong>Joshua Cotterell</strong> recently joined ASOS’ Android team for the second time, after taking a brief break of a few months to travel around Asia. For his Tech Develops, he created a web-based tool to help modify internal JSON config files.</p><blockquote>For Tech Develops, I decided to build a JSON editor website. I wanted a quicker way to edit JSON, rather than using Find &amp; Replace in a text editor.</blockquote><blockquote>To tackle this problem, I decided to load all text/number values into text/number fields, all bool values into switches, and display the keys as headers with the text size determined by the depth. I also created a simple filtering system using a search bar, so when you enter some text into the search bar, the JSON is filtered to display only the JSON that matches the search term.</blockquote><blockquote>I originally wrote this in JavaScript, but have since rewritten the app using Flutter — not only to learn a cross-platform framework, but because it allows direct persisting of any changes to the opened file, whereas a web solution only allows the changes to be saved as a new file.</blockquote><blockquote>Two days was a great amount of time to get stuck into a problem and really flush out a small working prototype. As with most POCs, testing and refactoring were left out of the building process as I wanted to focus on the features and the UI. Overall, I was happy with the project and found it to be the perfect learning experience for the two-day tech develops here at ASOS.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*ZapM61RLyjLxIULzef_ykg.gif" /><figcaption>Joshua’s JSON editor in action ✨</figcaption></figure><h3>Notifications</h3><p>It’s certainly frustrating to miss out on a new drop or not know when your latest ASOS order is on the way, but thanks to the smart cookies in the Notifications tech team this is a problem of the past!</p><p><a href="https://medium.com/u/8e66acaab06d">Joe Conway</a> is a Lead Engineer within the Notifications team and this month used Tech Develops to explore the increasingly more relevant topic of AI.</p><blockquote>For this month’s Tech Develops, I decided to immerse myself in the world of generative AI, an area I find fascinating. 2023 has been awash with AI related developments and news, a fair proportion of which has centred around the ability that LLMs like OpenAI’s ChatGPT have to write code.</blockquote><blockquote>Alongside the rise of LLMs, there has been a rise in systems to orchestrate the LLMs into groups of interoperable agents. These systems allow different agents to be defined and converse with one another to reach a final goal. One such system is Autogen, from the labs of Microsoft Research.</blockquote><blockquote>I decided to run an experiment to expose the kinds of results that could be achieved and get a feel for the technology. As with many things, it started with a Pip install of the autogen library and a prompt <em>😊</em></blockquote><blockquote>I followed one of the more simplistic examples from the Autogen documentation and created an example involving an <strong>AssistantAgent</strong> and a <strong>UserProxyAgent</strong>.</blockquote><blockquote>The assistant would represent our friendly engineer, the user proxy would run the output from the assistant and delegate back to me in case of any further queries. My initial prompt was as follows (Note: The JSON ‘searchresponse’ input contained the raw search response from the ASOS Search API when searching for “red dress”).</blockquote><blockquote><strong>“Write a program to find the first product image in the list of products in the searchresponse.json file that contains the text ‘PETITE’, use the ‘imageUrl’ field to download the image, use easyocr for the ocr reader.”</strong></blockquote><blockquote>The resulting conversation resulted in a back and forth between the two agents The assistant began:</blockquote><blockquote><strong><em>“Sure, I can help with that. Here’s the plan:</em></strong></blockquote><blockquote><strong><em>1. Read the JSON file and parse it.<br>2. Iterate over the list of products and find the first product that contains the text ‘PETITE’.<br>3. Extract the ‘imageUrl’ field from the product.<br>4. Download the image from the URL.<br>5. Use easyocr to read the text from the image.”</em></strong></blockquote><blockquote>The user agent would follow on to execute the script and respond with any errors, this back and forth continued for a couple of iterations, until the model stumbled on one of the requirements. My intention was for the code to read the text content from the images themselves, and not the step that the assistant outlined in step 2. The assistant asked for help. <br> <br><strong>“Please provide a new keyword or a new JSON file if available. If not, we may need to terminate the task here.”</strong></blockquote><blockquote>The user agent (in this instance, me) responded</blockquote><blockquote><strong>“Do not search for text in the json file, search for images that contain the text as part of the image itself”</strong></blockquote><blockquote>The agent and user proxy continued to write code, test the code, iterate (sound familiar?) before finally the user agent (Python interpreter and LLM combined!) responded with the code below</blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/97d5c2857659121d4266203982e83695/href">https://medium.com/media/97d5c2857659121d4266203982e83695/href</a></iframe><blockquote>It even printed the final image to the same directory!</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*AiAc5UPKInBxXCKLKtVp3g.png" /><figcaption>The final image 🔥</figcaption></figure><h3>Commercial Tech</h3><p><strong>Kishor Achtani </strong>is a Platform Lead for our Commercial Integrations team, a critical area of the Commercial Technology platform. This month, Kishor’s Tech Develops was far from ordinary!</p><blockquote>This Tech Develops I managed to muster some courage and made my second attempt to learn a foreign language by learning some Italian. My first attempt was German when I was teen and I was kicked out of the class within 15 mins <em>😂</em></blockquote><blockquote>However, this time I managed to survive for 60 mins and learnt some basics of this wonderful language. Now I can confidently walk in to any Italian restaurant and say “Ciao, come stai, tavlo per 2.” or perhaps if I am stranded in middle of nowhere in Naples with no access to internet “Mi Scusi, Ciao, dove la stazione piu vicina <em>🚈</em>”</blockquote><blockquote>The second half of Tech Develops was much more fun and thrilling than the first, as a colleague and I attended a <a href="https://miro.com">MIRO</a> innovational event located at Level 39 of the iconic Gherkin building in London!</blockquote><blockquote>Not only did we receive a hearty welcome, we also witnessed some mesmerizing views and got to munch on some lip smacking food. <em>🥞☕</em></blockquote><blockquote>We learnt how a culture of psychological safety is a vital part of successful innovation. We also heard about a ton of new features (Talk Tracks + Miro AI Assists + Integration with DevOps etc).</blockquote><blockquote>We were feeling as proud as a peacock when ASOS featured in one of their slides during the keynote session.<em>🦚</em></blockquote><blockquote>The evening concluded with a champagne networking reception, where we got an opportunity to learn from likeminded leaders from the world’s most interesting brands over champagne and canapes.<em>🥂</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*cl8peScXv6F5ad1ghB2tkA.jpeg" /><figcaption>‘Buon appetito’ from Kishor @ the Miro event!</figcaption></figure><h4>That’s all for now!</h4><p>What would <em>you </em>bring to Tech Develops? Why not check out our <a href="https://www.asoscareers.com/our-teams/technology-data">open positions</a> within the Tech team and come find out?</p><p><em>Ed is a Lead Android Developer at ASOS and a member of the Tech Blog team.<br>In his spare time, you can find him </em><a href="https://spght.dev/talks"><em>talking about mobile security</em></a><em> at conferences or </em><a href="https://twitter.com/sp4ghetticode"><em>posting pictures of his dog</em></a><em>!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0f8a9f3adf81" width="1" height="1" alt=""><hr><p><a href="https://medium.com/asos-techblog/heres-what-we-got-up-to-this-month-in-tech-develops-0f8a9f3adf81">Here’s what we got up to this month in Tech Develops…</a> was originally published in <a href="https://medium.com/asos-techblog">ASOS Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unpacking Android Security: Part 4 — Insecure Authentication]]></title>
            <link>https://proandroiddev.com/unpacking-android-security-part-4-insecure-authentication-330fcc019ef5?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/330fcc019ef5</guid>
            <category><![CDATA[mobile-security]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[owasp]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Tue, 12 Sep 2023 01:57:28 GMT</pubDate>
            <atom:updated>2023-09-14T14:25:33.457Z</atom:updated>
            <content:encoded><![CDATA[<h3>Unpacking Android Security: Part 4 — Insecure Authentication</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lM5YfvmHQcreGuBYLWqD9A.jpeg" /><figcaption><strong><em>Photo Credit: </em></strong><a href="https://unsplash.com/photos/qKtxuJOQpl0"><strong><em>Felipe Furtado</em></strong></a></figcaption></figure><p>👋 Hi and welcome to the fourth post in this series where we deep-dive into Android Security (<a href="https://medium.com/proandroiddev/unpicking-android-security-part-1-improper-platform-usage-ac677a9443b2">Part 1</a>, <a href="https://medium.com/proandroiddev/unpacking-android-security-part-2-insecure-data-storage-71f35107052a">2</a> and <a href="https://medium.com/proandroiddev/unpacking-android-security-part-3-insecure-communication-d5e833166040">3</a>). This series focuses on the Top 10 Mobile security threats as determined by The Open Web Application Security Project (OWASP) Foundation, the leading application security community in our field. Before checking this post, please consider checking out the previous one &#39;Insecure Communication&#39; which is available on my site, and on Medium.</p><p>⚠️ Please note that this series is for educational purposes <strong>only</strong>. Remember to only test on apps where you have permission to do so and most of all, <a href="https://en.wikipedia.org/wiki/Don%27t_be_evil">don&#39;t be evil</a>.</p><p>Finally, if you enjoy this series or have any feedback, <a href="https://twitter.com/sp4ghetticode">please drop me a message</a>. Thanks!</p><h3>Introduction</h3><p>In this helping of my series on Android Security, we shall take a look into the #4 threat to mobile application security as determined by OWASP, &quot;Insecure Authentication&quot;.</p><p>But what does authentication involve? Well, put simply, authentication is the process of verifying a user&#39;s &quot;identity&quot; is what they claim it to be. Once verified, this identity is then often used to authorize the user to access a service, data or other restricted resource.¹</p><p>Authentication is achieved by using <em>at least</em> one of three basic authentication factors: ²</p><h4>💭 Something you KNOW</h4><ul><li>Such as a password, passphrase, user ID, etc ³</li></ul><h4>🎁 Something you HAVE</h4><ul><li>An authorization token, a physical crypto-key, an authentication code, etc</li></ul><h4>👀 Something you ARE</h4><ul><li>Via your own biometrics. i.e. fingerprint(s) or forms of visual recognition such as facial/retinal recognition</li></ul><p>In theory, the more of these factors that are used, the stronger the authentication <em>is</em> and the harder it becomes to pretend to be someone you aren&#39;t. This is, in fact, the guiding principle behind <em>multi-factor-authentication</em> (MFA) and hopefully, something you are familiar with and using already when it comes to your own authentication practises! ⁴</p><p>That said, these individual authentication factors aren&#39;t foolproof and still require care to be taken by the developer in order to ensure the user is protected and your app is secure. So let&#39;s do just that!</p><h3>What&#39;s the passw*rd?</h3><p>Something that certainly isn&#39;t unique to Android apps is users making poor decisions when it comes to password security. Given when data breaches occur the most common choices are usually password, 12345, qwerty or similar variations, we can assume that when given the option users may opt for incredibly simplistic and insecure passwords.</p><p>However, as developers, we have a duty to ensure that when users create passwords they are as secure as possible by enforcing &#39;password policies&#39; which will (hopefully) encourage users to create not only strong passwords, but also <em>unique</em> ones.</p><p><strong>&quot;Ok, but what makes a good password policy?&quot;</strong> I quite <em>clearly</em> heard you say. 🤗 I am so glad you asked, here are some tips on how to come up with one.</p><p><strong>Set a minimum length</strong></p><p>Firstly, ensure your policy has a minimum length of characters that is required. It should be obvious that a longer password is generally more secure than a shorter one, but choosing character limits that add security and also allows users to generate passwords they will find memorable can be difficult. A good minimum number for this task, and also recommended by the <a href="https://www.nist.gov/">National Institute of Standards and Technology</a> (NIST), is <strong>8 characters</strong>.</p><p>Ideally, you should also consider the maximum length of any passwords to be <em>at least</em> 64 characters to facilitate and encourage totally unique passwords or phrases. Visually reinforcing longer passwords within your app&#39;s UX is also a great approach to ensure users make better choices.</p><p><strong>Reconsider the use of &#39;complexity requirements&#39;</strong></p><p>When you read password policy you probably instinctively thought of rules that enforce a mix of letters, numbers, and special characters, as this fairly common place. The theoretical aim of rules of that nature is to make it more difficult for attackers to simply guess or use brute force to crack a password. However, guidance on this has shifted in recent years due to concerns that such complexity requirements actually lead users to create <em>more insecure</em> passwords ⁵ 🤯. In this case, perhaps less is more! Giving your users increased flexibility may encourage longer, harder to crack passwords, which is better for everyone.</p><p><strong>No hints allowed!</strong></p><p>You may occasionally come across applications that ask you to supply a memorable phrase as a hint for future password recovery. This is certainly something you should avoid as it gives extra information to a potential attacker as users routinely choose hints which severely compromise their passwords 😅 The next point highlights exactly why.</p><p><strong>Knowledge is porridge </strong>⁶</p><blockquote>What was your first pet’s name?<br>Who was your favourite teacher? <br>Where were you born?</blockquote><p>Be aware that security questions <em>might</em> occasionally seem like an added layer of safety, but in extreme cases can be (and have been) obtained by social engineering. Social engineering plays upon our human-emotions and as humans are fallible, much like software, even basic social engineering could give malicious actors enough information to work towards compromising a user&#39;s identity. Depending on your visibility online, you might well have already been leaking some of this information yourself without realising. ⁷ Social Engineering has caused numerous high profile security breaches in the last decade and is an attack vector that is seeing an increase in popularity.</p><p><strong>Best practises change over time</strong></p><p>This guide is just that, a <em>guide</em>. Please make sure you consult your own cyber-security team (or other professionals) to determine if your current policy is up to scratch. Guidance on passwords has continuously shifted for decades, and will likely continue to do so for many more to come!</p><p>But wait, there&#39;s more. Once the password is created there are some further considerations to take on board:</p><ol><li><strong>Password expiration:</strong> Setting a limit on how long a password can be used before it needs to be changed. This helps to limit the window of time during which an attacker can use a cracked password.</li><li><strong>History:</strong> Preventing users from reusing passwords that they have used in the past. This helps to prevent attackers from using passwords that have been compromised in previous breaches.</li><li><strong>Use of password manager:</strong> Encourage users to use a password manager that can store their password securely.</li><li><strong>Remember Me:</strong> If you provide some form of &#39;remember me&#39; functionality during sign-in, <em>never</em> store the user&#39;s password locally on the device. Instead, utilise a long-life authentication token that can easily be revoked if needed.</li></ol><p>With these tips - you can do your very best to help users make a well-informed and secure password. You can hopefully sleep easy knowing you have done your part, and as long as the users do theirs, their passwords are secure!</p><p>Clearly, passwords continue to present a very real security problem for apps, but I am pleased to say the future is beginning to look to be somewhat brighter...</p><h3>Passkeys</h3><p>When I originally wrote my very first draft of this blog post, I pretty much wrapped it up here. However, as a consequence of tinkering and toying with this post for a while, Google has now <em>already</em> begun the push to a post-password world in the form of &#39;passkeys&#39;. Doesn&#39;t technology move fast! 😅</p><p>In fact, Google, Apple <em>and</em> Microsoft have <a href="https://fidoalliance.org/apple-google-and-microsoft-commit-to-expanded-support-for-fido-standard-to-accelerate-availability-of-passwordless-sign-ins/">all committed</a> to providing a common password-less solution through the adoption of the FIDO (Fast IDentity Online) Alliance&#39;s <strong>passkey</strong> standard. So this isn&#39;t something to be sleeping on 👀</p><h3>Pass-whats?</h3><p>But what even <em>is</em> a passkey? Well, a passkey is a unique cryptographic key pair used to identify a user and their associated account for a given service. When a new passkey is created, the private key is saved on the <em>issuing device</em> with the public key being sent to be securely stored by the service.</p><p>This may sound <em>just</em> like bog-standard public key cryptography, and guess what? <em>It is!</em> Albeit, with the additional requirement of requiring authentication via the issuing device. If we think back to the list of authentication factors, this new flow requires something you <strong>have</strong> (i.e. the issuing device) and something you <strong>are</strong> (i.e. biometrics) or <strong>know</strong> (i.e. device PIN).</p><p>The good news is, from a user&#39;s perspective, there&#39;s very little that changes from a standard password flow. When a user is prompted to sign-in via passkey, the user approves the sign-in with the same authentication factor that the user has to unlock the device, such as their biometrics, password or PIN. Should a passkey exist for the user, then this authentication is enough for the user to continue - no further action required. If the device has yet to issue a passkey for that user and account, one is created and the sync process between the issuing device and service is also initiated to ensure the user can continue to use the device.</p><h3>Passkeys in Android</h3><p>Over the last few months, Google released a bundle of new online content (see: Further Reading) to aid Android developers in providing passkey support.</p><p>The first thing to note is passkeys are <strong>only supported on devices that run Android 9 (API level 28) or higher</strong>, meaning older OS versions will need to fall back to an existing password flow. Sadly we haven&#39;t eliminated passwords completely, but this is progress!</p><p>Under the hood, using the androidx.credentials:credentials suite of libraries, we can utilise the CredentialManager class to aid us in the generation of credential requests and the handling of the various response types. I won&#39;t discuss the full technical implementation here, but rest assured the official docs have you covered 😎</p><p>If this sounds like something you&#39;d like to learn more about, I would highly recommend reading the original <a href="https://android-developers.googleblog.com/2022/10/bringing-passkeys-to-android-and-chrome.html?m=1">Bringing Passkeys to Android &amp; Chrome</a> announcement blog post and watching the <a href="https://www.youtube.com/watch?v=36peNZUlgzU">associated YouTube video</a> before attempting to implement this yourself using the <a href="https://developer.android.com/training/sign-in/passkeys">Sign in your user with Credential Manager</a> development guide.</p><p>In any case, you may also wish to check out the <a href="https://github.com/android/identity-samples/tree/main/CredentialManager">sample app</a> provided by the Google identity team to give an idea of the best practices surrounding passkey implementation.</p><p>Hopefully, in a few year&#39;s time, we&#39;ll have totally ditched the dodgy passwords and have made our apps much more secure in the process!</p><h3>Next up 🚀</h3><p>In the upcoming posts within this series, we shall explore more of the OWASP Top 10 for Mobile. Next up is #5 <a href="https://owasp.org/www-project-mobile-top-10/2016-risks/m5-insufficient-cryptography">Insufficient Cryptography</a></p><h3>Thanks 🌟</h3><p><em>Thanks as always for reading! I hope you found this post interesting, Please feel free to tweet me with any feedback at </em><a href="https://twitter.com/sp4ghetticode"><em>@Sp4ghettiCode</em></a><em> and don&#39;t forget to clap, like, tweet, share, star etc</em></p><h4>Further Reading</h4><ul><li><a href="https://github.com/ed-george/owasp-top-five">owasp-top-five Companion App</a></li><li><a href="https://owasp.org/www-project-mobile-top-10/2016-risks/m4-insecure-authentication">M4: Insecure Authentication : OWASP Foundation</a></li><li><a href="https://securityqueens.co.uk/mobster4-insecure-authentication/">Security Queens: Mobster4 - Insecure Authentication</a></li><li><a href="https://developer.android.com/topic/security/best-practices">Android - Security Best Practices</a></li><li><a href="https://pages.nist.gov/800-63-3/sp800-63b.html#sec5">NIST Special Publication 800-63B - Digital Identity Guidelines</a></li><li><a href="https://youtu.be/36peNZUlgzU">How to reduce reliance on passwords in Android apps with passkey support</a></li><li><a href="https://developer.android.com/training/sign-in/passkeys">Sign in your user with Credential Manager</a></li></ul><h4>Footnotes</h4><p>[<strong>1</strong>] Spoiler alert, we will revisit authorization in a future blog! You can swot up in advance by checking out <a href="https://owasp.org/www-project-mobile-top-10/2016-risks/m6-insecure-authorization">OWASP - M6: Insecure Authorization</a></p><p>[<strong>2</strong>] You <em>could</em> also use &#39;location&#39; and &#39;behaviour&#39; as separate authentication factors. However, to keep it simple I have limited it to the most common 3 factors.</p><p>[<strong>3</strong>] Assuming that you, unlike me, can remember your passwords! In any case, I highly recommend a decent password manager such as <a href="1password.com">1Password</a></p><p>[<strong>4</strong>] Please use MFA whenever it&#39;s available. It usually takes no time at all to set up!</p><p>[<strong>5</strong>] For example, JohnDoe@1992 could be cracked a lot easier than android is my favourite mobile os</p><p>[<strong>6</strong>] <a href="https://www.youtube.com/watch?v=cbLm--0Iudo">One of my favourite &#39;Thick of It&#39; quotes</a> (NSFW)</p><p>[<strong>7</strong>] I&#39;ve never (to my knowledge) posted my dog&#39;s name on the internet - <em>just in case</em>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=330fcc019ef5" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/unpacking-android-security-part-4-insecure-authentication-330fcc019ef5">Unpacking Android Security: Part 4 — Insecure Authentication</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android Security: Securing your Gradle builds from baddies]]></title>
            <link>https://proandroiddev.com/android-security-securing-your-gradle-builds-from-baddies-1dc30e1acf30?source=rss-1e7c83978135------2</link>
            <guid isPermaLink="false">https://medium.com/p/1dc30e1acf30</guid>
            <category><![CDATA[security]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[gradle]]></category>
            <category><![CDATA[mobile-security]]></category>
            <dc:creator><![CDATA[Ed Holloway-George]]></dc:creator>
            <pubDate>Mon, 24 Jul 2023 20:51:06 GMT</pubDate>
            <atom:updated>2023-07-24T20:51:06.791Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-0oNHvWU9jLb0pr-fLFTng.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/pt-br/@chuttersnap?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">CHUTTERSNAP</a> on <a href="https://unsplash.com/photos/fN603qcEA7g?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>This is the accompanying blog post for my recent Droidcon Berlin 2023 talk “How to stop the Gradle Snatchers: Securing your builds from baddies” — you can find the slides, video and other resources for this talk at my site <a href="https://spght.dev/talks">spght.dev/talks</a></p><p>If you are an Android developer like me, you will likely be somewhat familiar with the ‘elephant in the room’ when it comes to our builds, Gradle. For over 10 years, it has been the go-to build tool for the Android ecosystem replacing ant, and helping developers move forward into a more configurable and pleasant developer experience¹.</p><p>However, like any tool we use in our developer utility belt to build our apps, it is susceptible to security risks that can (and do) pose a threat to our codebases, apps and users.</p><p>While my talk and this post approach the topic from an Android development angle, the tips and tricks shared can be applied to <strong><em>any</em></strong> Gradle project. In this post, we will explore some simple steps we can take to ensure Gradle doesn’t fall foul to a supply-chain attack.</p><h4>A supply-what?</h4><p>A supply-chain attack is loosely defined as an attack on the tooling you use with the intention to introduce vulnerabilities, insecurities or malicious code into the tooling without being detected. It <em>could</em> be done internally within an organization by a rouge employee, or perhaps externally by a malicious actor who has gained privileged access to a system or tooling.</p><p>These types of attacks, while rare in the mobile industry, <em>do happen</em> and Gradle has been proven to be a popular choice of tooling to attack in the past.</p><p>Let’s look at three distinct areas where we can make improvements to secure our Gradle projects: <strong>Dependencies</strong>, <strong>Gradle Wrapper</strong> and <strong>Gradle Distribution</strong>.</p><h3>Dependencies</h3><p>It should come as no surprise that most Gradle projects contain external dependencies. Unless you have an extremely large development team, a lot of time or perhaps some incredibly strict security requirements of your own, it’s highly unlikely you will re-write particular code each time you begin a project. Third-party networking libraries, logging or other utilities are common dependencies to add at the start of most Android projects, but once we have added them to our build.gradle and we leave it to Gradle to import them from external repositories, <strong>how do we know these dependencies are legitimate</strong><em> </em><strong>😧?</strong></p><p>In 2018, a supply-chain attack was observed via a number of compromised dependencies hosted on the now-defunct Maven repository, JCenter. In Márton Braun’s excellent blog post <a href="https://web.archive.org/web/20181214053140/http://blog.autsoft.hu/a-confusing-dependency/">‘A Confusing Dependency’</a>, he describes how a malicious actor was able to upload artifacts to JCenter that shadowed popular libraries found in other repositories such as Jitpack. These libraries shared package names and common code with their shadowed counterparts but also contained maliciously injected code to run on a user’s device when these libraries were used by unsuspecting developers. From the developer’s standpoint, there would be <em>little to no obvious difference</em> when using a legitimate or malicious library, however, the security of their users would be <em>severely</em> compromised. The full story itself is best described by Márton, but fortunately JCenter is no-more and we have some tools to protect us from these attacks going forwards.</p><h4>Dependency Verification</h4><p>When working with dependencies, we have two tools available to <em>verify</em> the dependency is legitimate and what we expect. Firstly, we have the ability to check the <strong>integrity</strong> of the dependency (i.e. has the dependency been modified in any way when compared to the <em>trusted</em> version) and also the <strong>origin</strong> of the dependency, also known as the provenance (i.e. is the dependency being provided by the legitimate trusted author).</p><p><strong>Integrity</strong> is checked via a checksum verification process. A checksum is a value that can be generated for a given file, via a specific algorithm, that does not change if a file is an exact copy of an original. For example, using the <a href="https://gchq.github.io/CyberChef/#recipe=SHA2(&#39;256&#39;,64,160)&amp;input=SGVsbG8gV29ybGQK">SHA-256 algorithm</a>, a simple file containing just the string Hello World would always resolve to d2a84f4b8b650… (You get the idea!). This same concept applies to Gradle dependency artifacts, as if we know the expected checksum, we can verify the integrity of the dependency we download.</p><p>To enable these checks via Gradle is as simple as running the following command</p><pre>./gradlew --write-verification-metadata sha256 someTaskName</pre><p>Running this task² will create a verification-metadata.xml file within your $PROJECT_ROOT/gradle folder that may look similar to the following:</p><pre>&lt;verification-metadata&gt;<br>   &lt;configuration&gt;<br>      &lt;verify-metadata&gt;true&lt;/verify-metadata&gt;<br>      &lt;verify-signatures&gt;false&lt;/verify-signatures&gt;<br>   &lt;/configuration&gt;<br>   &lt;components&gt;<br>      &lt;!-- All your dependencies here! --&gt;<br>      &lt;component group=&quot;com.jakewharton.timber&quot; name=&quot;timber&quot; version=&quot;5.0.1&quot;&gt;<br>         &lt;artifact name=&quot;timber-5.0.1.aar&quot;&gt;<br>            &lt;sha256 value=&quot;ffedddfcc8eff42a1604c8577fcfa4b4ffd9f252122c52ea36cfe7967f512f71&quot; /&gt;<br>         &lt;/artifact&gt;<br>      &lt;/component&gt;<br>   &lt;/components&gt;<br>&lt;/verification-metadata&gt;</pre><p>This metadata file will contain checksums for your dependencies and their artifacts. Any subsequent fetches of these files will be compared with the provided checksum values and should any mismatch occur, a build error will occur — allowing you to catch any suspicious differences quickly.</p><p>In addition to this, an HTML report is also generated within the$PROJECT_ROOT/build/reports/dependency-verification folder of your project. This report gives further information surrounding any issues including links to relevant documentation and details on the warnings or errors present.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3q7RAUpTkqkMLilDb1ndlA.png" /><figcaption>An example of an HTML report generated when a checksum fails verification</figcaption></figure><p>But where are these checksum values actually coming from?</p><p>When a dependency is added to a Maven repo, such as Maven Central, the artifacts are uploaded with checksum files with .md5, .sha1, .sha256 or .sha512 file suffixes after the corresponding file’s original name (e.g mylib.aar.sha256). These files contain the hash value for the artifact using the given algorithm and are downloaded from the Maven repo as part of the verification meta-data process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/605/1*_rbgN-mB33I0DAE12pvX5w.png" /><figcaption>An example of how the com.jakewharton.timber:timber:5.0.1 dependency looks within the Maven Central repo</figcaption></figure><p>Once this verification is enabled, when you add or update a dependency you’ll need to ensure <em>the correct data </em>for each relevant artifact is added to the metadata file — otherwise your builds will fail and you might get an earful from anyone else working on your project(s)! 😅 If your builds fail without any update to your dependencies, you must investigate as this would be the first indication of a supply-chain attack!</p><p><strong>The provenance</strong>, or origin of a dependency is verified via the signature that was used to sign the artifacts. This signature is generated by a public-private key pair used by the library’s author when uploading the library to a Maven Repo.</p><p>To allow for this check to occur in your Gradle builds, amend the previous Gradle task to the following</p><pre>./gradlew --write-verification-metadata sha256,pgp someTaskName</pre><p>When this is enabled, you’ll see a number of trusted-key elements added to your metadata file representing trusted public keys for given dependencies.</p><pre>&lt;verification-metadata&gt;<br>   &lt;configuration&gt;<br>      &lt;verify-metadata&gt;true&lt;/verify-metadata&gt;<br>      &lt;verify-signatures&gt;true&lt;/verify-signatures&gt;<br>   &lt;/configuration&gt;<br>   &lt;trusted-keys&gt;   <br>     &lt;trusted-key id=“47bf5922…” group=&quot;com.jakewharton.timber&quot; name=“timber&quot; version=&quot;5.0.1&quot;/&gt;<br>   &lt;/trusted-keys&gt;<br>&lt;/verification-metadata&gt;</pre><p>These trusted public keys are stored locally and tested against the .asc PGP signature files that are also present within the Maven repo for the given dependency. When the dependency is fetched from the repo, these files and associated keys are used to authenticate a particular artifact&#39;s author.</p><p>⚠️ <strong>PLEASE NOTE:</strong> While the setup of this checksum/signature verification is quite straightforward, for it to provide total security it requires that you begin the process with <strong>complete trust </strong>in the pre-existing dependencies you have imported. Failure to first pre-verify <em>each</em> dependency’s checksum against a value you consider trusted renders this process useless. This process also applies to situations where you update the dependency — so while this is a far from frictionless experience, if done properly you can <em>guarantee</em> the integrity of your dependencies.</p><p>The <a href="https://docs.gradle.org/current/userguide/dependency_verification.html">Gradle documentation</a> for dependency verification goes into great detail on these two methods. It is an excellent place to find out much more information about how to secure your dependencies and a must-read for any security-conscious developer! 😎</p><h4>Repository Filtering</h4><p>Another approach to using dependencies in a more secure way is to use <a href="https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:repository-content-filtering">repository filtering</a>. This is the process of creating allow/deny rules for specific repositories surrounding the dependencies they are allowed to fetch. The APIs available for this give developers plenty of scope for creating simple or more complex rules and is something that can be implemented relatively easily through modifications to your existing repositories block.</p><p>In the example below, we allow <em>all</em> dependencies with the group com.example and the specific dependency com.example:foo to be fetched from JitPack, while excluding all dependencies from dev.spght.*³</p><pre>repositories {<br>    maven {<br>        url &quot;https://jitpack.io&quot;<br>        content {<br>            // Fetch dependencies<br>            includeGroup &quot;com.example&quot;<br>            includeModule(&quot;com.example&quot;, &quot;foo&quot;)<br>            // Exclude dependencies             <br>            excludeGroupByRegex(&quot;dev\\.spght\\..*&quot;)<br>        }<br>    }<br>}</pre><p>By defining your rules correctly (i.e. in a mutually exclusive way), you can completely guarantee dependencies are downloaded from the source you wish them to be.</p><p>However, it should be noted that while this <em>might </em>add some degree of trust, this approach <strong>does not verify the dependencies themselves are legitimate</strong> like the checksum or signature checks discussed previously. So certainly consider using repository filtering in combination with other methods. 🙏</p><h4>Gradle Wrapper Verification</h4><p>The Gradle Wrapper is a tool we use often with little thought. For most of us, the gradlew script in our projects is commonly the entry point we use to run specific tasks relating to our projects, such as running tests, building artifacts and everything in between. We might give it no attention, but behind the scenes, the wrapper has an important role in ensuring the “correct version” of Gradle is downloaded and executed for your project.</p><p>Part of this process is running the gradle-wrapper.jar , a Java executable that is likely checked into your version control. As this file is commonly executed, it is certainly a potential security risk should it be maliciously modified.</p><p>In fact, in late 2022 a <a href="https://blog.gradle.org/wrapper-attack-report">supply chain attack on the wrapper</a> .jar file was first observed in the wild within the codebase of an incredibly popular Minecraft Server. A malicious Minecraft plugin, in conjunction with the wrapper JAR executable, was responsible for accessing user data and granting particular users admin/root-level access to the game as well as the underlying tech stack used to serve it.</p><p>On the back of this, Gradle has released a <a href="https://github.com/marketplace/actions/gradle-wrapper-validation">GitHub Action</a> that can be used as part of your build pipeline to verify that the Wrapper’s JAR is legitimate. It uses the <a href="https://gradle.org/release-checksums/">known wrapper checksums</a> to ensure the wrapper has not been tampered with and also is smart enough to check files named gradle-wrapper.jar with <a href="https://en.wikipedia.org/wiki/Homoglyph">homoglyph</a> variants (i.e. where an attacker uses a Unicode character that looks similar to an ASCII one in order to deceive developers into using the wrong file).</p><p>However, should you not be using GitHub for CI and require a solution you can run both locally and remotely, I also created a simple <a href="https://gist.github.com/ed-george/3751d09ccdfd33cfe48d8987d9f68510">script</a> to verify the Wrapper’s JAR</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/54d350dc3fd596b298c5fd319e3cadcd/href">https://medium.com/media/54d350dc3fd596b298c5fd319e3cadcd/href</a></iframe><p>Sadly no official solution exists for verifying the gradlew script, but a <a href="https://github.com/gradle/wrapper-validation-action/issues/16">GitHub issue</a> exists as a feature request. It may be worth keeping an eye on… 👀</p><h4>Gradle Distribution Verification</h4><p>Finally, it is also possible to verify the actual Gradle distribution that the wrapper downloads. You may have seen the distributionUrl property within your $PROJ_ROOT/gradle/wrapper/gradle-wrapper.properties file, which contains the URL of the distribution of Gradle to fetch. However, how can we guarantee that what is downloaded is legitimate?</p><p>By adding a distributionSha256Sum property to this file with a SHA256 checksum, when the distribution is downloaded the checksum of that file will be compared with the string in the supplied property. These distribution <a href="https://gradle.org/release-checksums/">checksums are known</a> and therefore can be added to your project easily.</p><p>It is also possible to add the distributionSha256Sum property dynamically when updating your Gradle wrapper by using the gradle-distribution-sha256-sum flag</p><pre>./gradlew wrapper --gradle-version=7.5 \<br>       --gradle-distribution-sha256-sum=cb87f222c…</pre><p>Should you download something that doesn’t match the distributionSha256Sum checksum, your builds will fail and you can begin to investigate. You never know, this might just save you one day!</p><h3>Final Thoughts 💭</h3><p>Phew, that’s it. Thanks for sticking to the end 😅</p><p>In conclusion, while a supply-chain attack on your Gradle tooling might <em>not</em> be as common as other forms of attacks, it is still a viable attack vector that has been proven to occur many times over.</p><p>The mechanisms Gradle supplies to thwart such attacks are more than simple enough to integrate into any project relatively quickly. Fingers crossed this post helps you make a more informed choice and perhaps look into adding one or more of these to your project.</p><p>For more information, check out <a href="https://spght.dev/talks">spght.dev/talks</a> and catch my talk “How to stop the Gradle Snatchers: Securing your builds from baddies” at Droidcon</p><p>Stay safe out there! 💪</p><h3>Thanks 🌟</h3><p><em>Thanks as always for reading! I hope you found this post interesting, please feel free to contact me with any feedback at </em><a href="https://linktr.ee/sp4ghetticode"><em>@Sp4ghettiCode</em></a><em> and don’t forget to clap, like, share, star etc</em></p><p>[1]: If you remember the time before Gradle, you will hopefully be in agreement. In my talk, I refer to this time as ‘the dark ages’.</p><p>[2]: In this example, someTaskName is an optional param that, if provided, should be the name of a Gradle task that exposes the dependencies you wish to verify. Gradle’s documentation recommends using the help task, but depending on your own configuration, there may be better tasks to run instead.</p><p>[3]: Who could trust someone with a domain that silly?! 😅</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1dc30e1acf30" width="1" height="1" alt=""><hr><p><a href="https://proandroiddev.com/android-security-securing-your-gradle-builds-from-baddies-1dc30e1acf30">Android Security: Securing your Gradle builds from baddies</a> was originally published in <a href="https://proandroiddev.com">ProAndroidDev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>