Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Permission host mismatch #13475

Merged
merged 5 commits into from
Mar 27, 2018
Merged

Permission host mismatch #13475

merged 5 commits into from
Mar 27, 2018

Conversation

jumde
Copy link
Contributor

@jumde jumde commented Mar 16, 2018

Fixes: #13471
Depends: brave/muon#540

Test plan

  1. Open https://google.com
  2. Change the address in the URL bar to sms://ggle.com. Verify the external permission message is for sms://ggle.com and not https://google.com
  3. Launch a webserver with test.html:
    <a href="sms://ggle.com">Test</a>
  4. Open http(s):///test.html
  5. Click on the hyperlink, verify the permission is requested for sms://ggle.com and not <webserver>

@codecov-io
Copy link

codecov-io commented Mar 16, 2018

Codecov Report

Merging #13475 into master will decrease coverage by 0.08%.
The diff coverage is 0%.

@@            Coverage Diff             @@
##           master   #13475      +/-   ##
==========================================
- Coverage   56.74%   56.66%   -0.09%     
==========================================
  Files         285      285              
  Lines       28797    28894      +97     
  Branches     4755     4775      +20     
==========================================
+ Hits        16341    16372      +31     
- Misses      12456    12522      +66
Flag Coverage Δ
#unittest 56.66% <0%> (-0.09%) ⬇️
Impacted Files Coverage Δ
app/filtering.js 17.7% <0%> (-0.48%) ⬇️
app/renderer/components/preferences/pluginsTab.js 40.32% <0%> (-8.7%) ⬇️
app/common/lib/ledgerUtil.js 93.38% <0%> (-0.82%) ⬇️
app/browser/tabs.js 23.34% <0%> (-0.45%) ⬇️
js/about/aboutActions.js 8.87% <0%> (-0.22%) ⬇️
js/actions/appActions.js 18.59% <0%> (ø) ⬆️
app/browser/api/ledger.js 61.6% <0%> (+0.03%) ⬆️
app/sessionStore.js 88.4% <0%> (+0.18%) ⬆️
app/common/state/ledgerState.js 84.95% <0%> (+0.22%) ⬆️
... and 1 more

app/filtering.js Outdated
@@ -495,9 +496,10 @@ function registerPermissionHandler (session, partition) {
}
}

let parsedMainFrameUrl = new URL(mainFrameUrl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this use urlParse?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With urlParse:

tps://oogle.com/search?q=s%3A%2F%2Fwww.lcebook.com%2F
{ hash: '',
  hostname: '',
  host: '',
  href: 'tps://oogle.com/search?q=s%3A%2F%2Fwww.lcebook.com%2F',
  path: '//oogle.com/search?q=s%3A%2F%2Fwww.lcebook.com%2F',
  pathname: '//oogle.com/search',
  port: '',
  protocol: 'tps:',
  query: 'q=s%3A%2F%2Fwww.lcebook.com%2F',
  search: '?q=s%3A%2F%2Fwww.lcebook.com%2F',
  origin: '' }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with new URL

URL {
  href: tps://oogle.com/search?q=s%3A%2F%2Fwww.lcebook.com%2F
  protocol: tps:
  hostname: oogle.com
  pathname: /search
  search: ?q=s%3A%2F%2Fwww.lcebook.com%2F
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fails here: <a href="tp://ttt.com">Test Url</a>

@diracdeltas
Copy link
Member

could you please add a test plan with the expected behavior?

@jumde jumde self-assigned this Mar 16, 2018
@jumde jumde requested a review from bsclifton March 16, 2018 18:00
urlParse = require('url').parse
}

let urlParse = require('url').parse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are some security issues with Node's default URL parser - can this behavior be fixed in Muon's url parser?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, working on that.

app/filtering.js Outdated
@@ -511,7 +511,7 @@ function registerPermissionHandler (session, partition) {
{text: locale.translation('deny')},
{text: locale.translation('allow')}
],
frameOrigin: getOrigin(mainFrameUrl),
frameOrigin: getOrigin(origin),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you want mainFrameUrl here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable names need to be updated here.

In brave/muon#540. I updated the origin to be the security origin of the current frame, and the mainFrameUrl to the URL requesting the permission.

@diracdeltas
Copy link
Member

diracdeltas commented Mar 20, 2018

@jumde previously, the openExternal permission (as I understood it), was granted to the main frame origin, not the origin that is being opened. Ex: if you go to brave.com and click the mailto: link at the bottom of the page, the expected behavior is that it prompts you whether to allow brave.com to open external URLs.

If we are going to change it to the behavior specified in your test plan, we need to also:

  1. update the permission message to "Allow URL_TO_BE_OPENED to be opened in an external application?" instead of "Allow MAIN_FRAME_URL to open external applications"?
  2. delete the existing openExternal permission settings, since those are no longer valid with this change

i agree that the behavior in this PR makes more sense than the existing behavior, but i also want to note that the scope of these changes is larger than #13471 (which can be fixed by just changing the displayed URL to be the external URL in the case where a main frame URL doesn't exist or if the request was initiated by directly entering a link in the URL bar).

could you open a new issue for the change in the openExternal permissions model?

@diracdeltas diracdeltas added this to the 0.22.x (Beta Channel) milestone Mar 22, 2018
if (parsed.origin.length !== 0) {
return parsed.origin.replace(/\/+$/, '')
}
return parsed.href.replace(/\/+$/, '')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this change still needed? i don't think this works on arbitrary URLs, ex:

muon.url.parse('sms://bing/kfdk').href.replace(/\/+$/, '')  // returns "sms://bing/kfdk"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove this diff if it's no longer needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still needed, muon.url.parse for muon.url.parse('sms://bing/kfdk') returns NULL origin. The warning message if this change is not present, the warning message will read Allow Brave Browser to open an external application?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jumde what if instead of this change, you just change https://github.com/brave/browser-laptop/pull/13475/files#diff-7b5b041c814805dd8496488bc6a53d3cR469 to parsed.origin != undefined so that the null origin will trigger https://github.com/brave/browser-laptop/pull/13475/files#diff-7b5b041c814805dd8496488bc6a53d3cR479 ?

also please add a test case in the getOrigin unit tests

Copy link
Contributor Author

@jumde jumde Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Host is also null for arbitrary URLs:

Url: hps://nodejs.org/en/download/
{ hash: '',
  hostname: '',
  host: '',
  href: 'hps://nodejs.org/en/download/',
  path: '//nodejs.org/en/download/',
  pathname: '//nodejs.org/en/download/',
  port: '',
  protocol: 'hps:',
  query: '',
  search: '',
  origin: '' }

Copy link
Member

@diracdeltas diracdeltas Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jumde i see. what if instead of changing the behavior of getOrigin, we just change https://github.com/brave/browser-laptop/pull/13475/files#diff-8a9bac13ef6264feb2b6da7c18d86b3cR500 to requestingOrigin || requestingUrl || 'Brave Browser' so it displays correctly?

i am reluctant to change getOrigin since it's used in various places for security checks

app/filtering.js Outdated
}

let response = []

if (origin == null) {
if (requestingUrl == null) {
response = new Array(permissionTypes.length)
Copy link
Member

@bsclifton bsclifton Mar 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks to be the first real change (origin => requestingUrl)- everything else above this line is just renaming, is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

app/filtering.js Outdated
@@ -497,7 +497,7 @@ function registerPermissionHandler (session, partition) {

// Display 'Brave Browser' if the origin is null; ex: when a mailto: link
// is opened in a new tab via right-click
const message = locale.translation('permissionMessage').replace(/{{\s*host\s*}}/, origin || 'Brave Browser').replace(/{{\s*permission\s*}}/, permissions[permission].action)
const message = locale.translation('permissionMessage').replace(/{{\s*host\s*}}/, getOrigin(requestingUrl) || 'Brave Browser').replace(/{{\s*permission\s*}}/, permissions[permission].action)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of where the setPermissionRequestHandler handler gets called from? I see the definition in Muon, but am not sure when the handler is called?

Copy link
Member

@bsclifton bsclifton Mar 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UPDATE: found it-
PlatformNotificationServiceImpl::DisplayNotification

I wanted to find an example of the args passed in

Copy link
Member

@bsclifton bsclifton Mar 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code in Muon...
mainFrameOrigin maps to current_origin
requestingUrl maps to requesting_origin

Super glad you fixed this mismatch issue 😄

bsclifton
bsclifton previously approved these changes Mar 26, 2018
Copy link
Member

@bsclifton bsclifton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look great! 😄 The problem pops out at you once the variables are renamed. Great job 😄 👍

app/filtering.js Outdated
@@ -530,7 +530,7 @@ function registerPermissionHandler (session, partition) {
response[index] = result
if (persist) {
// remember site setting for this host
appActions.changeSiteSetting(origin, permission + 'Permission', result, isPrivate)
appActions.changeSiteSetting(requestingUrl, permission + 'Permission', result, isPrivate)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused why we are getting the permissions for the main frame origin in https://github.com/brave/browser-laptop/pull/13475/files#diff-8a9bac13ef6264feb2b6da7c18d86b3cR452, but here we apply permissions by requestingUrl instead of mainFrameOrigin. seems like these two lines should either both use requestingUrl or both use mainFrameOrigin

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! fixed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see https://github.com/brave/browser-laptop/pull/13475/files#r177257591 - this should apply the change by requesting origin, not full URL

app/filtering.js Outdated
settings = siteSettings.getSiteSettingsForHostPattern(appState.get('siteSettings'), origin)
tempSettings = siteSettings.getSiteSettingsForHostPattern(appState.get('temporarySiteSettings'), origin)
} else if (mainFrameUrl.startsWith('magnet:')) {
settings = siteSettings.getSiteSettingsForHostPattern(appState.get('siteSettings'), mainFrameOrigin)
Copy link
Member

@diracdeltas diracdeltas Mar 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure this and the other getSiteSettingsForHostPattern lines aren't supposed to use getOrigin(requestingUrl) instead of mainFrameOrigin since that's what is actually shown in the message?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jumde jumde force-pushed the permissions_host branch from 87d6877 to 4dbc4fd Compare March 26, 2018 22:41
app/filtering.js Outdated
tempSettings = siteSettings.getSiteSettingsForHostPattern(appState.get('temporarySiteSettings'), origin)
} else if (mainFrameUrl.startsWith('magnet:')) {
settings = siteSettings.getSiteSettingsForHostPattern(appState.get('siteSettings'), requestingUrl)
tempSettings = siteSettings.getSiteSettingsForHostPattern(appState.get('temporarySiteSettings'), requestingUrl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you have to do requestingUrl = getOrigin(requestingUrl) before calling these settings since these were previously saved by origin not full URL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or better yet, define const requestingOrigin = getOrigin(requestingUrl) in the function scope so that it's harder to confuse URL with origin

app/filtering.js Outdated
origin = getOrigin(origin)
settings = siteSettings.getSiteSettingsForURL(appState.get('siteSettings'), origin)
tempSettings = siteSettings.getSiteSettingsForURL(appState.get('temporarySiteSettings'), origin)
requestingUrl = getOrigin(requestingUrl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app/filtering.js Outdated
@@ -497,7 +497,7 @@ function registerPermissionHandler (session, partition) {

// Display 'Brave Browser' if the origin is null; ex: when a mailto: link
// is opened in a new tab via right-click
const message = locale.translation('permissionMessage').replace(/{{\s*host\s*}}/, origin || 'Brave Browser').replace(/{{\s*permission\s*}}/, permissions[permission].action)
const message = locale.translation('permissionMessage').replace(/{{\s*host\s*}}/, getOrigin(requestingUrl) || 'Brave Browser').replace(/{{\s*permission\s*}}/, permissions[permission].action)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app/filtering.js Outdated
if (mainFrameUrl === appUrlUtil.getBraveExtIndexHTML() || isPDFOrigin || isBraveOrigin) {
let requestingOrigin = getOrigin(requestingUrl)

if (requestingOrigin === appUrlUtil.getBraveExtIndexHTML() || isPDFOrigin || isBraveOrigin) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you want requestingUrl in this line i think

@diracdeltas
Copy link
Member

@jumde thanks for making the changes. PR looks good to me now :). i will test it once the muon build is out.

app/filtering.js Outdated
@@ -471,7 +471,7 @@ function registerPermissionHandler (session, partition) {
response.push(false)
} else if (permission === 'fullscreen' &&
// The Torrent Viewer extension is always allowed to show fullscreen media
origin.startsWith('chrome-extension://' + config.torrentExtensionId)) {
mainFrameOrigin.startsWith('chrome-extension://' + config.torrentExtensionId)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this throws an error when you go to http://www.orimi.com/pdf-test.pdf and click the fullscreen button

should be requestingOrigin instead of mainFrameOrigin i think

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually it shouldn't - https://github.com/brave/browser-laptop/pull/13475/files#diff-8a9bac13ef6264feb2b6da7c18d86b3cR440 set the mainFrameOrigin to null deliberately

so i think this just has to check if mainFrameOrigin is null

app/filtering.js Outdated
} else if (mainFrameUrl.startsWith('magnet:')) {
settings = siteSettings.getSiteSettingsForHostPattern(appState.get('siteSettings'), requestingOrigin)
tempSettings = siteSettings.getSiteSettingsForHostPattern(appState.get('temporarySiteSettings'), requestingOrigin)
} else if (requestingOrigin.startsWith('magnet:')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this if block` is actually not necessary anymore since it will show the magnet URL itself

Copy link
Member

@bsclifton bsclifton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test plan works! 👍

Copy link
Member

@diracdeltas diracdeltas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@bsclifton bsclifton merged commit 5694502 into master Mar 27, 2018
@bsclifton
Copy link
Member

I am an idiot and just merged again without squashing 😛

@bsclifton bsclifton deleted the permissions_host branch March 27, 2018 21:28
bsclifton added a commit that referenced this pull request Mar 27, 2018
bsclifton added a commit that referenced this pull request Mar 27, 2018
@bsclifton
Copy link
Member

master 5694502
0.23.x ac2b5fd
0.22.x cd7a878

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants