Skip to content

Commit

Permalink
For mozilla-mobile#9338 - Introduce SafeUrl to strip unwanted uri sch…
Browse files Browse the repository at this point in the history
…emes

Interested clients can overwrite "mozac_url_schemes_blocklist" with a custom
list of uri schemes that will be recursively removed from the front of the uri.
  • Loading branch information
Mugurell committed Jan 6, 2021
1 parent 5f2b7d4 commit 123ab64
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.support.utils

import android.content.Context

/**
* Collection of methods used for ensuring the validity and security of URLs.
*/
object SafeUrl {
fun stripUnsafeUrlSchemes(context: Context, unsafeText: CharSequence?): String? {
val urlSchemesBlocklist = context.resources.getStringArray(R.array.mozac_url_schemes_blocklist)
var safeUrl = unsafeText.toString()
if (safeUrl.isEmpty()) {
return safeUrl
}

@Suppress("ControlFlowWithEmptyBody", "EmptyWhileBlock")
while (urlSchemesBlocklist.find {
if (safeUrl.startsWith(it, true)) {
safeUrl = safeUrl.replaceFirst(Regex(it, RegexOption.IGNORE_CASE), "")
true
} else {
false
}
} != null) {
}

return safeUrl
}
}
10 changes: 10 additions & 0 deletions components/support/utils/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
<!--
List of url schemes which will be dropped from clipboard urls when pasting due to potential security issues.
-->
<string-array name="mozac_url_schemes_blocklist" />
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.support.utils

import android.content.Context
import android.content.res.Resources
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.support.test.mock
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.doReturn

@RunWith(AndroidJUnit4::class)
class SafeUrlTest {
@Test
fun `WHEN schemes blocklist is empty THEN stripUnsafeUrlSchemes should return the initial String`() {
val resources = mock<Resources>()
val context = mock<Context>()
doReturn(resources).`when`(context).resources
doReturn(emptyArray<String>()).`when`(resources).getStringArray(R.array.mozac_url_schemes_blocklist)

val result = SafeUrl.stripUnsafeUrlSchemes(context, "unsafeText")

assertEquals("unsafeText", result)
}

@Test
fun `WHEN schemes blocklist contains items not found in the argument THEN stripUnsafeUrlSchemes should return the initial String`() {
val resources = mock<Resources>()
val context = mock<Context>()
doReturn(resources).`when`(context).resources
doReturn(arrayOf("alien")).`when`(resources).getStringArray(R.array.mozac_url_schemes_blocklist)

val result = SafeUrl.stripUnsafeUrlSchemes(context, "thisIsAnOkText")

assertEquals("thisIsAnOkText", result)
}

@Test
fun `WHEN schemes blocklist contains items found in the argument THEN stripUnsafeUrlSchemes should recursively remove them from the front`() {
val resources = mock<Resources>()
val context = mock<Context>()
doReturn(resources).`when`(context).resources
doReturn(arrayOf("one", "two")).`when`(resources).getStringArray(R.array.mozac_url_schemes_blocklist)

val result = SafeUrl.stripUnsafeUrlSchemes(context, "two" + "one" + "one" + "two" + "safeText")
assertEquals("safeText", result)

val result2 = SafeUrl.stripUnsafeUrlSchemes(context, "one" + "two" + "one" + "two" + "safeText" + "one")
assertEquals("safeText" + "one", result2)
}
}
3 changes: 3 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ permalink: /changelog/
* [Gecko](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Gecko.kt)
* [Configuration](https://github.com/mozilla-mobile/android-components/blob/master/.config.yml)

* **support-utils**:
* 🌟 Added SafeUrl#stripUnsafeUrlSchemes that can cleanup unwanted uri schemes. Interested clients can specify what these are by overwriting "mozac_url_schemes_blocklist".

* **feature-prompts**:
* 🚒 Bug fixed [issue #9229](https://github.com/mozilla-mobile/android-components/issues/9229) - Dismiss SelectLoginPrompt from the current tab when opening a new one ensuring the new one can show it's own. When returning to the previous tab users should focus a login field to see the SelectLoginPrompt again.

Expand Down

0 comments on commit 123ab64

Please sign in to comment.