Skip to content
This repository was archived by the owner on May 10, 2024. It is now read-only.

Commit a90bb99

Browse files
cubaiccub
authored andcommitted
Fix #6146: Add eTLD+1 check when debouncing (#6147)
1 parent 4d88b90 commit a90bb99

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

Client/WebFilters/DebouncingResourceDownloader.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,18 @@ public class DebouncingResourceDownloader {
360360
///
361361
/// The following conditions must be met to redirect:
362362
/// 1. Must have a `MatcherRule` that satisifes this url
363-
/// 2. Extracted URL not be the same domain as the base URL
364-
/// 3. Extracted URL must be a valid URL (Have valid scheme, have an `eTLD+1` or be an IP address etc.. )
365-
/// 4. Extracted URL must have a `http` or `https` scheme
363+
/// 2. Extracted URL must not have the same origin as that of the base URL
364+
/// 3. Extracted URL must not have the same `eTLD+1` as that of the base URL (#6146)
365+
/// 4. Extracted URL must be a valid URL (Have valid scheme, have an `eTLD+1` or be an IP address etc.. )
366+
/// 5. Extracted URL must have a `http` or `https` scheme
366367
private func redirectURLOnce(from url: URL) throws -> (url: URL, rule: RedirectRule)? {
367368
guard let rule = matchingRedirectRule(for: url) else {
368369
return nil
369370
}
370371

371372
guard let extractedURL = try rule.extractRedirectURL(from: url),
372-
url.host != extractedURL.host,
373+
url.origin != extractedURL.origin,
374+
url.baseDomain != extractedURL.baseDomain,
373375
extractedURL.scheme == "http" || extractedURL.scheme == "https" else {
374376
return nil
375377
}

Tests/ClientTests/Resources/debouncing.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,15 @@
244244
"action": "regex-path",
245245
"param": "^/(.*)/(.*)$"
246246
},
247+
{
248+
"include": [
249+
"http://*.click.example/bounce?url=*"
250+
],
251+
"exclude": [
252+
],
253+
"action": "redirect",
254+
"param": "url"
255+
},
247256
{
248257
"include": [
249258
"*://brave-long-regex.example/*"

Tests/ClientTests/Web Filters/DebouncingResourceDownloaderTests.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ class DebouncingResourceDownloaderTests: XCTestCase {
110110
let redirectChain = downloader.redirectChain(for: startURL)
111111

112112
// Then
113-
XCTAssertEqual(redirectChain.last?.url, finalURL)
113+
// While we used to go to `finalURL`, we now stop at `intermediateURL`
114+
// This changed with the introduction of ticket #6146
115+
XCTAssertEqual(redirectChain.last?.url, intermediateURL)
114116
}
115117

116118
// Test a long redirect chain that bounces through the original URL's domain,
@@ -374,6 +376,36 @@ class DebouncingResourceDownloaderTests: XCTestCase {
374376
)
375377
}
376378

379+
/// Test several restrictions to debouncing
380+
func testDebounceRestrictions() {
381+
// Given
382+
// A constructed url
383+
let baseURL = URL(string: "http://a.click.example/bounce")!
384+
let startURL1 = baseURL.addRedirectParam(URL(string: "http://a.click.example/dest")!)
385+
let startURL2 = baseURL.addRedirectParam(URL(string: "http://b.click.example/dest")!)
386+
let startURL3 = baseURL.addRedirectParam(URL(string: "ftp://example.com/dest")!)
387+
388+
// When
389+
// A redirect is returned
390+
let redirectChain1 = downloader.redirectChain(for: startURL1)
391+
let redirectChain2 = downloader.redirectChain(for: startURL2)
392+
let redirectChain3 = downloader.redirectChain(for: startURL3)
393+
394+
// Then
395+
XCTAssertNil(
396+
redirectChain1.last,
397+
"This should be nil because origin matches"
398+
)
399+
XCTAssertNil(
400+
redirectChain2.last,
401+
"This should be nil because eTLD+1 matches"
402+
)
403+
XCTAssertNil(
404+
redirectChain3.last,
405+
"This should be nil because the scheme is not http or https"
406+
)
407+
}
408+
377409
/// Test regex rule where `prepend_scheme` is not specified and `base64` action is specified
378410
func testRegexRuleWithBase64DecodedURL() {
379411
// Given

0 commit comments

Comments
 (0)