OWASP Mobile Top 10:2024
A guide to the ten current OWASP Mobile Top 10:2024 categories for Android, iOS, and the services they depend on.
Edition 2024; risk names follow the official OWASP publication.
M1
Improper Credential Usage
Improper Credential Usage means a mobile app embeds, stores, transmits, or uses passwords, API keys, tokens, or sessions unsafely. Hardcoded secrets or passwords in ordinary device storage can be extracted through reverse engineering or a lost device and reused against the backend.
| What can go wrong | Secrets, tokens, API keys, or passwords are embedded, reused, exposed, or handled without an appropriate lifecycle. |
|---|---|
| Business effect | A recovered application package or leaked token can provide ongoing access to a backend or protected function. |
| First control to verify | Keep long-lived secrets out of the client. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
A recovered application package or leaked token can provide ongoing access to a backend or protected function.
Risk-reduction focus
- Keep long-lived secrets out of the client.
- Use scoped, revocable credentials and rotate them.
- Protect credential entry and transmission paths.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M2
Inadequate Supply Chain Security
Inadequate Supply Chain Security means the app, SDKs, dependencies, build system, or package signing lack adequate provenance and integrity control. A changed third-party SDK, compromised pipeline, or leaked signing key can make an installed app do work the team never intended.
| What can go wrong | Mobile SDKs, build plugins, signing systems, and distribution dependencies are not sufficiently governed. |
|---|---|
| Business effect | A compromised SDK or release pipeline can introduce tracking, data exposure, or altered application behavior. |
| First control to verify | Inventory third-party SDKs and their data flows. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
A compromised SDK or release pipeline can introduce tracking, data exposure, or altered application behavior.
Risk-reduction focus
- Inventory third-party SDKs and their data flows.
- Restrict and audit signing and release access.
- Verify package origin, integrity, and update notices.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M3
Insecure Authentication/Authorization
Insecure Authentication/Authorization means the mobile app or backend misidentifies a user or grants actions incorrectly. Incomplete token checks, client-supplied roles, or sessions surviving logout can enable account takeover, cross-user data access, or restricted functions.
| What can go wrong | The app or its backend accepts weak identity proof, session handling, or permission decisions. |
|---|---|
| Business effect | A device user or remote actor can access another account, protected feature, or data set. |
| First control to verify | Authorize requests on the backend, not only in the app. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
A device user or remote actor can access another account, protected feature, or data set.
Risk-reduction focus
- Authorize requests on the backend, not only in the app.
- Use secure sessions and risk-appropriate MFA.
- Test deep links, app components, and backend object access.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M4
Insufficient Input/Output Validation
Insufficient Input/Output Validation means the app trusts deep links, QR values, intents, files, server responses, or rendered output without checking format, source, and bounds. Tampered data can open an unsafe target, alter a workflow, or send data to the wrong destination.
| What can go wrong | Data crossing application, device, backend, browser, or third-party boundaries is trusted without sufficient checks. |
|---|---|
| Business effect | Malicious content can alter an app flow, be rendered unsafely, or drive an unsafe backend operation. |
| First control to verify | Validate all external data at each trust boundary. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
Malicious content can alter an app flow, be rendered unsafely, or drive an unsafe backend operation.
Risk-reduction focus
- Validate all external data at each trust boundary.
- Encode output for its rendering context.
- Use typed contracts and reject unexpected fields.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M5
Insecure Communication
Insecure Communication means app-to-service data is not sufficiently protected against interception or modification. Trusting unverified certificates, using HTTP, incomplete TLS validation, or sending secrets through another unsafe channel can let a nearby network attacker read or alter traffic.
| What can go wrong | Network traffic, certificate handling, or channel selection does not adequately protect data in transit. |
|---|---|
| Business effect | A hostile or compromised network can observe, alter, or redirect sensitive exchanges. |
| First control to verify | Require modern TLS for sensitive connections. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
A hostile or compromised network can observe, alter, or redirect sensitive exchanges.
Risk-reduction focus
- Require modern TLS for sensitive connections.
- Validate certificates and avoid trust-all behavior.
- Limit sensitive data in requests and diagnostics.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M6
Inadequate Privacy Controls
Inadequate Privacy Controls occur when an app collects, uses, discloses, or retains personal data beyond a clear purpose or without understandable control. Unneeded permissions, identifiable analytics, or missing consent management create risks for users, trust, and privacy obligations.
| What can go wrong | The app collects, shares, retains, or exposes personal data beyond the disclosed and necessary purpose. |
|---|---|
| Business effect | Users can lose control of personal information through telemetry, permissions, analytics, or third-party sharing. |
| First control to verify | Map personal-data collection and recipients. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
Users can lose control of personal information through telemetry, permissions, analytics, or third-party sharing.
Risk-reduction focus
- Map personal-data collection and recipients.
- Request only necessary permissions at the right time.
- Apply retention, consent, and deletion controls.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M7
Insufficient Binary Protections
Insufficient Binary Protections mean an app binary is easy to inspect, modify, or repackage so client-side safeguards can be bypassed. Missing tamper detection or device-integrity checks are examples. These controls do not replace server-side enforcement, but they raise attack cost and create detection signals.
| What can go wrong | The distributed app does not sufficiently resist unauthorized modification, repackaging, or analysis for its threat model. |
|---|---|
| Business effect | A modified client can remove controls, expose implementation details, or misrepresent a trusted application to users. |
| First control to verify | Keep trust decisions and secrets server-side. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
A modified client can remove controls, expose implementation details, or misrepresent a trusted application to users.
Risk-reduction focus
- Keep trust decisions and secrets server-side.
- Use platform signing and integrity signals where appropriate.
- Detect tampering proportionately and plan safe responses.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M8
Security Misconfiguration
Mobile Security Misconfiguration is unnecessary exposure through capabilities, components, debug settings, permissions, or network policy. An exported activity, extractable backup, or release debug endpoint can let another app invoke functionality or access data outside the intended UI.
| What can go wrong | Build variants, platform settings, exported components, or backend configuration expose unintended behavior. |
|---|---|
| Business effect | Debug features, exported components, permissive backups, or weak transport settings can be reachable in a release. |
| First control to verify | Review release manifests and platform settings. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
Debug features, exported components, permissive backups, or weak transport settings can be reachable in a release.
Risk-reduction focus
- Review release manifests and platform settings.
- Separate debug and production configuration.
- Automate configuration checks in CI.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M9
Insecure Data Storage
Insecure Data Storage means sensitive data is saved on the device without suitable protection, such as in shared preferences, caches, logs, screenshots, clipboard, or backups. It can leak through rooted or jailbroken devices, backup extraction, malware, or temporary physical access.
| What can go wrong | Sensitive data is stored locally or cached where another application, backup, device user, or forensic process can access it. |
|---|---|
| Business effect | A lost, rooted, shared, or backed-up device can reveal account, business, or personal data. |
| First control to verify | Minimize local sensitive data and cache duration. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
A lost, rooted, shared, or backed-up device can reveal account, business, or personal data.
Risk-reduction focus
- Minimize local sensitive data and cache duration.
- Use platform-protected storage for necessary secrets.
- Review logs, screenshots, backups, and shared storage.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}M10
Insufficient Cryptography
Insufficient Cryptography means an app selects or applies algorithms, keys, random values, or libraries incorrectly even when encryption exists. Guessable keys, unsuitable modes, or readable key storage can let an attacker who obtains data or keys decrypt or forge it.
| What can go wrong | Cryptographic algorithms, modes, random values, keys, or implementations do not protect mobile data as intended. |
|---|---|
| Business effect | Data protected by weak or incorrectly implemented cryptography can be recovered or altered. |
| First control to verify | Use platform and vetted cryptographic APIs. |
Attacker Victim Application Security control

The diagram contrasts the unsafe route with the control that interrupts it. Select the image to inspect it at full size.
Why it matters
Data protected by weak or incorrectly implemented cryptography can be recovered or altered.
Risk-reduction focus
- Use platform and vetted cryptographic APIs.
- Generate and store keys with platform protections.
- Avoid custom cryptography and obsolete algorithms.
Android example in Kotlin
Vulnerable example
import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rawTarget)))
}
}Fixed example
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import androidx.appcompat.app.AppCompatActivity
class RedirectActivity : AppCompatActivity() {
private val allowedHosts = setOf("app.example.com")
fun openRedirect(intent: Intent) {
val rawTarget = intent.data?.getQueryParameter("redirect") ?: return
val target = Uri.parse(rawTarget)
if (target.scheme != "https" || target.host !in allowedHosts) return
CustomTabsIntent.Builder().build().launchUrl(this, target)
}
}iOS example in Swift
Vulnerable example
import UIKit
final class RedirectViewController: UIViewController {
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget) else { return }
UIApplication.shared.open(target)
}
}Fixed example
import SafariServices
import UIKit
final class RedirectViewController: UIViewController {
private let allowedHosts: Set<String> = ["app.example.com"]
func openRedirect(rawTarget: String) {
guard let target = URL(string: rawTarget),
target.scheme == "https",
let host = target.host,
allowedHosts.contains(host) else { return }
let browser = SFSafariViewController(url: target)
present(browser, animated: true)
}
}
