<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alex Lotsu</title>
    <description>The latest articles on Forem by Alex Lotsu (@alex_lotsu).</description>
    <link>https://forem.com/alex_lotsu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1769455%2F4078d5d5-0cf8-4978-bc14-eebfbe4c8356.png</url>
      <title>Forem: Alex Lotsu</title>
      <link>https://forem.com/alex_lotsu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alex_lotsu"/>
    <language>en</language>
    <item>
      <title>How to avoid one of the biggest risks in mobile security as an iOS developer</title>
      <dc:creator>Alex Lotsu</dc:creator>
      <pubDate>Fri, 12 Jul 2024 17:00:00 +0000</pubDate>
      <link>https://forem.com/alex_lotsu/how-to-avoid-one-of-the-biggest-risks-in-mobile-security-as-an-ios-developer-1hd</link>
      <guid>https://forem.com/alex_lotsu/how-to-avoid-one-of-the-biggest-risks-in-mobile-security-as-an-ios-developer-1hd</guid>
      <description>&lt;h2&gt;
  
  
  What is the most significant security concern in your average mobile app?
&lt;/h2&gt;

&lt;p&gt;What could cause GDPR violations, fines and damage company reputation?&lt;/p&gt;

&lt;p&gt;Unintentionally leaking user data. More specifically, this article will focus on how to avoid unintentionally logging sensitive user data.&lt;/p&gt;

&lt;p&gt;Sensitive user data could be anything from users’ addresses, credit card information to health info.&lt;/p&gt;

&lt;p&gt;“But my logging system is only available internally”&lt;/p&gt;

&lt;p&gt;Many studies show 20–80%+ of data breaches are internal (Sources 1, 2), so part of having a robust security strategy is making sure user data is not available to &lt;em&gt;anyone&lt;/em&gt; it doesn’t need to be.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3swmmjzz4sl5kp7xmop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3swmmjzz4sl5kp7xmop.png" alt="Bad actor grabbing user data" width="720" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What can I do as a developer to avoid this and have impact across my codebase?
&lt;/h2&gt;


&lt;h3&gt;
  
  
  Design Smarter — Unified Logging system
&lt;/h3&gt;

&lt;p&gt;Multiple logging frameworks makes it hard to manage sanitisation, processes and ensure every line of code meets the same standards. A unified logging system is ideal as it allows you to have a common approach for logging safely across the system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Filter data in your logging system.
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;NSRegularExpression&lt;/code&gt;, &lt;code&gt;NSDataDetector&lt;/code&gt; and blacklists you can filter out specific values you do not want to log. A breakdown of each method:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NSRegularExpression&lt;/code&gt; — Use Regex to define specific patterns that can be used to filter logs and redact if any matches are found.&lt;/p&gt;

&lt;p&gt;For example, you could create a Regex pattern to check for values that resemble emails and then redact these values before they get logged.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;redactAddresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Define a regex pattern for matching addresses&lt;/span&gt;
   &lt;span class="c1"&gt;// This example pattern looks for a typical street address format (e.g., “123 Main St”)&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;d{1,5}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;w+(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;w+)*&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;s(?:St|Street|Ave|Avenue|Rd|Road|Blvd|Boulevard|Dr|Drive|Ln|Lane|Ct|Court|Pl|Place|Way|Terrace|Terr)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;b"&lt;/span&gt; 

   &lt;span class="c1"&gt;// Create the regular expression object&lt;/span&gt;
   &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kt"&gt;NSRegularExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="kt"&gt;Invalid&lt;/span&gt; &lt;span class="n"&gt;regex&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="c1"&gt;// Define the range of the input text to be searched&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startIndex&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="c1"&gt;// Perform the regex search and replace matches with “[REDACTED]”&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;redactedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;regex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringByReplacingMatches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nv"&gt;range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;withTemplate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;REDACTED&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;redactedText&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Example usage&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;inputText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"John lives at 123 Main St and his office is located at 456 Elm Ave."&lt;/span&gt; 
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;redactedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;redactAddresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redactedText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Output: “John lives at [REDACTED] and his office is located at [REDACTED].”&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro:&lt;/strong&gt; You can define intricate patterns to search for in your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con:&lt;/strong&gt; You have to consider and handle any localisation and formatting of the data yourself. This means if your data is in other languages or could have various formatting you must account for this in your Regex definitions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NSDataDetector&lt;/code&gt; — use it to filter common data types (phone numbers, urls, addresses). This approach requires less work than regex but can fail quite easily if the data doesn’t follow common structures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;redactAddresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Create an NSDataDetector for addresses&lt;/span&gt;
   &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;detector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kt"&gt;NSDataDetector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSTextCheckingResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;CheckingType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rawValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="kt"&gt;Failed&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="kt"&gt;NSDataDetector&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Create a mutable copy of the input text to perform replacements&lt;/span&gt;
   &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;redactedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
  &lt;span class="c1"&gt;// Define the range of the input text to be searched&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NSRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startIndex&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// Find matches and replace them with “[REDACTED]”&lt;/span&gt;
   &lt;span class="n"&gt;detector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enumerateMatches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nv"&gt;range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;matchRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;swiftRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matchRange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;// Replace the matched address with “[REDACTED]”&lt;/span&gt;
         &lt;span class="n"&gt;redactedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redactedText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replacingCharacters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swiftRange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"[REDACTED]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;redactedText&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Example usage&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;inputText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"John lives at 123 Main St and his office is located at 456 Elm Ave."&lt;/span&gt; 
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;redactedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;redactAddresses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inputText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redactedText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Output: “John lives at [REDACTED] and his office is located at [REDACTED].”&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll notice you have the ability to choose from a predefined &lt;code&gt;CheckingType&lt;/code&gt; with &lt;code&gt;NSDataDetector&lt;/code&gt;. Some of the types it can be useful at checking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Address&lt;/li&gt;
&lt;li&gt;Links&lt;/li&gt;
&lt;li&gt;Phone numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro:&lt;/strong&gt; It handles localisation and formatting for the different data types it detects (nicer for international use)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Con:&lt;/strong&gt; Less flexible and sometimes won’t pick up on patterns if it doesn’t follow a well-known structure (e.g it will not detect some addresses from some countries/areas that don’t follow standard address formats)&lt;/p&gt;

&lt;p&gt;I would say this can be a good option to get you started if you are looking to filter the types listed above and under time constraints. Also, it could be used in conjunction with an &lt;code&gt;NSRegularExpression&lt;/code&gt; filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blacklist
&lt;/h3&gt;

&lt;p&gt;Blacklist certain values you want to specifically target. This is great if you have a particular value in mind you want to filter out. However, because it is so specific, it can mean variations of that value are not caught as they would be with &lt;code&gt;NSRegularExpression&lt;/code&gt; or &lt;code&gt;NSDataDetector&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The secret sauce to building a logging system that can adapt in real-time
&lt;/h2&gt;

&lt;p&gt;How can your app handle a logging incident? Do you have to write an update to go out in the next release cycle, meaning you are potentially waiting weeks until it is effective?&lt;/p&gt;

&lt;p&gt;Or do you have to disable an entire feature behind a feature flag to stop logging sensitive data?&lt;/p&gt;

&lt;p&gt;Putting your filters behind feature flags so they can be modified in incident response is a powerful way to build an app that can be updated in real-time to fix data breaches. With the power of building feature flagging into your app, you can use this to your advantage for a more effective incident response process.&lt;/p&gt;

&lt;p&gt;Anytime your logging system alerts you or another team that sensitive data is being logged, you can respond immediately by updating the regex or blacklist values your app uses to filter for a new type.&lt;/p&gt;

&lt;p&gt;For example, if your app is found to be logging username and passwords, you could modify the feature flag to include a regex pattern for username and passwords:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;patternsString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""" ^[A-Z0–9._%+-]+@[A-Z0–9.-]+&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;.[A-Z]{2,}$;^[A-Za-z0–9]{3,16}$;^(?=.*[A-Z])(?=.*[a-z])(?=.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;d)(?=.*[@$!%*?&amp;amp;#])[A-Za-z&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;d@$!%*?&amp;amp;#]{8,}$; """&lt;/span&gt; 
&lt;span class="c1"&gt;// Split the string into an array of patterns&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;patternsArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patternsString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;separator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You can keep your pre-defined regex patterns separate but have a string feature flag value for values you want to append on the fly)&lt;/p&gt;

&lt;p&gt;This means you now have an incident response process for all app users and everyone who works on your app to quickly rectify any logging issues. So the next time you (or a team member) is paged about a production incident in your free time, you can quickly sort it and get back to watching your TV show.&lt;/p&gt;

&lt;h2&gt;
  
  
  Develop smarter with property wrappers
&lt;/h2&gt;

&lt;p&gt;One of the reasons sensitive data can often get logged is due to logging an entire value (like a &lt;code&gt;User Struct&lt;/code&gt;) without realising you are logging all the properties from that &lt;code&gt;Struct&lt;/code&gt;, i.e. name, email address, etc.&lt;/p&gt;

&lt;p&gt;A smart way to avoid this is a method raised here by Oleg Dreyman that uses property wrappers on any values linked to sensitive data. &lt;a href="https://olegdreyman.medium.com/keep-private-information-out-of-your-logs-with-swift-bbd2fbcd9a40" rel="noopener noreferrer"&gt;https://olegdreyman.medium.com/keep-private-information-out-of-your-logs-with-swift-bbd2fbcd9a40&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarise, your property wrapper has overridden definitions of the values typically used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;@propertyWrapper&lt;/span&gt;
&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;LoggingExcluded&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CustomStringConvertible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;CustomDebugStringConvertible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;CustomLeafReflectable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 

 &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;wrappedValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Value&lt;/span&gt; 

 &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;wrappedValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
 &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wrappedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wrappedValue&lt;/span&gt; 
 &lt;span class="p"&gt;}&lt;/span&gt; 

 &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"— redacted — "&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt; 

 &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;debugDescription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;" — redacted — "&lt;/span&gt; 
 &lt;span class="p"&gt;}&lt;/span&gt; 

 &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;customMirror&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Mirror&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;Mirror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;reflecting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;" — redacted — "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
 &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if you go to log a struct like User, that has its sensitive data properties marked with this property wrapper &lt;code&gt;@LoggingExcluded&lt;/code&gt; the User struct logged will show &lt;code&gt;— redacted —&lt;/code&gt; for the sensitive values. Checkout the article for more on this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable Logging alerts in staging
&lt;/h2&gt;

&lt;p&gt;Enabling alerts in your staging environment allows you to receive notifications when sensitive data is logged before it goes out into production. It can be easy to ignore staging alerts but treating them with care can help catch these issues before they impact production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personal recommendation
&lt;/h2&gt;

&lt;p&gt;If there was one takeaway I had to advise you to implement in your application it would be putting your logging filter behind a feature flag so you can easily update it on the fly across all of your app users.&lt;/p&gt;

&lt;p&gt;Implement these techniques to build a smarter, more secure system and have an impact across your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want more security insights in mobile development?
&lt;/h2&gt;

&lt;p&gt;I’m Alex, a software engineer and security champion. I write about mobile security and provide tips you can implement in your apps.&lt;/p&gt;

&lt;p&gt;To stay up to date on future posts and short form content:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/mynetwork/discovery-see-all/?usecase=PEOPLE_FOLLOWS&amp;amp;followMember=alex-lotsu-644a9b18a" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.idwatchdog.com/insider-threats-and-data-breaches" rel="noopener noreferrer"&gt;https://www.idwatchdog.com/insider-threats-and-data-breaches&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.varonis.com/blog/data-breach-statistics#:%7E:text=83%20percent%20of%20data%20breaches,(Verizon)" rel="noopener noreferrer"&gt;https://www.varonis.com/blog/data-breach-statistics#:~:text=83%20percent%20of%20data%20breaches,(Verizon)&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ios</category>
      <category>security</category>
      <category>mobile</category>
      <category>swift</category>
    </item>
  </channel>
</rss>
