New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest a permission UI flow #3

Open
zolkis opened this Issue Mar 13, 2015 · 37 comments

Comments

Projects
None yet
7 participants
@zolkis
Contributor

zolkis commented Mar 13, 2015

From @jyasskin on February 7, 2015 2:59

The NFC spec, or surrounding documentation, should suggest one or more UI flows that UAs might find acceptable, along with some explanation of the security concerns leading to those options.

For example, maybe setPushMessage() is allowed with no UI but only takes effect during times that the calling document is in the foreground. This would be safe because the user is likely to have a clear understanding that tapping two NFC objects is likely to let their foreground applications communicate.

Maybe watch() is also allowed with no UI. Then, when a matching tag or peer is tapped, the UA shows a chooser between the sites that have made matching watch() calls. When the user picks a site, that site opens and gets to communicate with the tag or peer. It would be important not to skip the chooser when only one site is watching, since the chooser is the permission UI. Please also evaluate whether it's possible to have a "remember this choice" checkbox in the chooser, given the data that's available to the UA.

Maybe write() requires a yes/no prompt because it can destroy data. Or, maybe it can run without a prompt when its document is in the foreground because the user understands that foreground apps on touching NFC devices can communicate.

I'm not sure whether it's important to hide a document's "foreground" status from JS running in that document.

@egmorant, the PM of the Chrome security UI group.

Copied from original issue: w3c/nfc#63

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 18, 2015

What is the purpose of having the API ask for UI permission?

Generally speaking, it doesn't seem like communicating through the NFC chip is that different from communicating through TCP/IP packets.

For TCP/IP packets we don't ask the user for permission before allowing a webpage to send or receive data. The only thing that we do do is to make sure that the party that we communicate with is prepared to communicate with untrusted web content.

That's why we have strict limitations on what types of HTTP requests you can send to 3rd party servers. Only if the servers opt in through the use of CORS do we allow arbitrary HTTP requests to be sent.

Similarly with WebSockets we only allow talking to WebSocket servers if the server explicitly opts in to talking to the initiating website.

But once that opt-in exists, we don't have any user prompts asking the user if it's ok if website X can connect to website Y.

That same opt-in is what #2 provides for NFC.

So why do we have a user prompt for NFC?

The only argument that I can see for having a prompt is that NFC can potentially expose information about the users location. For example if I set up a tag at a given intersection in San Francisco with a unique identifier and then create a website which listens to NFC events, then I will know that the user is at that location in San Francisco if I get an NFC event which contains my unique identifier.

This is equally true for writing since rather than reading the id of the tag, I could write something that identifies the user to the tag. Then I can go to the tag to see who was at the given intersection at what time.

This is obviously also true for P2P.

However I would argue that in the vast majority of cases a user won't accidentally hold up their NFC enabled device to an NFC tag without expecting that the currently foreground content will be able to access that tag.

One option is to do something similar to what we do for fullscreen. I.e. rather than having a prompt, simply inform the user in an unobtrusive manner. If we can make that unobtrusive enough I think it's fine to leave it as an UA decision what the UI would look like. For example enable an icon in the status bar of a phone indicating that the current webpage is attempting to do NFC communication.

So in summary, I think the spec should:

  • Explain the privacy aspect.
  • Not require that implementations prompt the user.
  • Suggest that some form of unobtrusive notification might be wanted if the implementation wants.
  • Explain that this notification would apply equally to all of reading/writing/p2p

Obviously we shouldn't forbid any prompts or other privacy/security measures that implementations want to add. Just like no spec forbids that for TCP/IP communication.

sicking commented Aug 18, 2015

What is the purpose of having the API ask for UI permission?

Generally speaking, it doesn't seem like communicating through the NFC chip is that different from communicating through TCP/IP packets.

For TCP/IP packets we don't ask the user for permission before allowing a webpage to send or receive data. The only thing that we do do is to make sure that the party that we communicate with is prepared to communicate with untrusted web content.

That's why we have strict limitations on what types of HTTP requests you can send to 3rd party servers. Only if the servers opt in through the use of CORS do we allow arbitrary HTTP requests to be sent.

Similarly with WebSockets we only allow talking to WebSocket servers if the server explicitly opts in to talking to the initiating website.

But once that opt-in exists, we don't have any user prompts asking the user if it's ok if website X can connect to website Y.

That same opt-in is what #2 provides for NFC.

So why do we have a user prompt for NFC?

The only argument that I can see for having a prompt is that NFC can potentially expose information about the users location. For example if I set up a tag at a given intersection in San Francisco with a unique identifier and then create a website which listens to NFC events, then I will know that the user is at that location in San Francisco if I get an NFC event which contains my unique identifier.

This is equally true for writing since rather than reading the id of the tag, I could write something that identifies the user to the tag. Then I can go to the tag to see who was at the given intersection at what time.

This is obviously also true for P2P.

However I would argue that in the vast majority of cases a user won't accidentally hold up their NFC enabled device to an NFC tag without expecting that the currently foreground content will be able to access that tag.

One option is to do something similar to what we do for fullscreen. I.e. rather than having a prompt, simply inform the user in an unobtrusive manner. If we can make that unobtrusive enough I think it's fine to leave it as an UA decision what the UI would look like. For example enable an icon in the status bar of a phone indicating that the current webpage is attempting to do NFC communication.

So in summary, I think the spec should:

  • Explain the privacy aspect.
  • Not require that implementations prompt the user.
  • Suggest that some form of unobtrusive notification might be wanted if the implementation wants.
  • Explain that this notification would apply equally to all of reading/writing/p2p

Obviously we shouldn't forbid any prompts or other privacy/security measures that implementations want to add. Just like no spec forbids that for TCP/IP communication.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 18, 2015

Contributor

So in summary, I think the spec should:

  • Explain the privacy aspect.
  • Not require that implementations prompt the user.
  • Suggest that some form of unobtrusive notification might be wanted if the implementation wants.
  • Explain that this notification would apply equally to all of reading/writing/p2p

Sounds fine with me.

Contributor

zolkis commented Aug 18, 2015

So in summary, I think the spec should:

  • Explain the privacy aspect.
  • Not require that implementations prompt the user.
  • Suggest that some form of unobtrusive notification might be wanted if the implementation wants.
  • Explain that this notification would apply equally to all of reading/writing/p2p

Sounds fine with me.

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 19, 2015

Contributor

Pretty good points. I am on board with this

Contributor

kenchris commented Aug 19, 2015

Pretty good points. I am on board with this

@anssiko

This comment has been minimized.

Show comment
Hide comment
@anssiko

anssiko Aug 19, 2015

Collaborator

So it sounds like the prose around the term obtain permission should be rephrased. The term itself could be renamed too, but I don't have better suggestions for the name at this time. However, here's a suggested rewording for the prose to start:

The term obtain permission for a certain operation indicates that the user agent has either obtained expressed permission, asks for forgiveness, or ensures a prearranged trust relationship exists.

I'm not sure whether there is a better term for the "ask for forgiveness" approach. IIRC this term was first coined by Robert O'Callahan et al. in the Why does the HTML fullscreen API ask for approval after entering fullscreen, rather than before? blog post.

Then, we should explain what the term ask for forgiveness means. Here's my first stab along the lines of @sicking's suggestion, borrowing some language from the Fullscreen API spec too:

The term ask for forgiveness refers to some form of unobtrusive notification that informs the user of an operation while it is running. User agents SHOULD provide the user with means to ignore similar future operations from the same origin and advertise this to the user.

If this resonates with people I can craft a PR to get the spec updated.

Collaborator

anssiko commented Aug 19, 2015

So it sounds like the prose around the term obtain permission should be rephrased. The term itself could be renamed too, but I don't have better suggestions for the name at this time. However, here's a suggested rewording for the prose to start:

The term obtain permission for a certain operation indicates that the user agent has either obtained expressed permission, asks for forgiveness, or ensures a prearranged trust relationship exists.

I'm not sure whether there is a better term for the "ask for forgiveness" approach. IIRC this term was first coined by Robert O'Callahan et al. in the Why does the HTML fullscreen API ask for approval after entering fullscreen, rather than before? blog post.

Then, we should explain what the term ask for forgiveness means. Here's my first stab along the lines of @sicking's suggestion, borrowing some language from the Fullscreen API spec too:

The term ask for forgiveness refers to some form of unobtrusive notification that informs the user of an operation while it is running. User agents SHOULD provide the user with means to ignore similar future operations from the same origin and advertise this to the user.

If this resonates with people I can craft a PR to get the spec updated.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 19, 2015

Contributor

Thanks @anssiko . Wait with the PR some time, we are doing a major revamp of the spec right now.

Contributor

zolkis commented Aug 19, 2015

Thanks @anssiko . Wait with the PR some time, we are doing a major revamp of the spec right now.

@jyasskin

This comment has been minimized.

Show comment
Hide comment
@jyasskin

jyasskin Aug 19, 2015

@ngparker, can you comment on @sicking's suggestion from Chrome Security's perspective?

jyasskin commented Aug 19, 2015

@ngparker, can you comment on @sicking's suggestion from Chrome Security's perspective?

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 19, 2015

Contributor

While here, I should ask what is the preferred policy for reading non-web tags or peer content:

  1. UA silently rejects them, i.e. only reads web-tags
  2. UA asks the user, or checks a preference
  3. UA reads and exposes the content normally, but without exposing the origin/path of the message since it's not there.

We had a long discussion with Alex on this, and we concluded there is no actual danger in exposing tags to web pages. The problem is when writing to them. So it comes to what is the preferred policy for writing / pushing tags:

  1. UA asks the user, or checks a preference
  2. no questions asked, the User needs to tap in order to write/push, so we can assume s/he knows what s/he wants.

In the end, we challenge even the idea of having web-specific tags. Including an extra special record in NDEF messages (or indicating in any other way that the content is web-specific) does not solve any security problems, but it may add new ones because of false sense of security. Everything is forgeable/changeable using native clients, so a web site cannot be sure that a web tag really has the origin it claims to have.

In turn, implementations can make sure that at least web sites cannot write other than web tag content, and at least web pages cannot alter the origin written with the content [*]. Then, native and web clients know that the content originates from a web site, so extra caution may be needed (unless it has been tampered with, but the result of that is more thorough checks, so this should be ok).

So web-specific tags can be seen as a convenience, by storing the origin/path of the website (browsing context) which has written the content. This opens up extra content handling options. But any policies based on assumptions about the origin of the data are broken from start.

[*] Note that the most recent, yet unpublished version saves the origin and path of the writer, together with the message, and discontinues the former notion of "scope".

Contributor

zolkis commented Aug 19, 2015

While here, I should ask what is the preferred policy for reading non-web tags or peer content:

  1. UA silently rejects them, i.e. only reads web-tags
  2. UA asks the user, or checks a preference
  3. UA reads and exposes the content normally, but without exposing the origin/path of the message since it's not there.

We had a long discussion with Alex on this, and we concluded there is no actual danger in exposing tags to web pages. The problem is when writing to them. So it comes to what is the preferred policy for writing / pushing tags:

  1. UA asks the user, or checks a preference
  2. no questions asked, the User needs to tap in order to write/push, so we can assume s/he knows what s/he wants.

In the end, we challenge even the idea of having web-specific tags. Including an extra special record in NDEF messages (or indicating in any other way that the content is web-specific) does not solve any security problems, but it may add new ones because of false sense of security. Everything is forgeable/changeable using native clients, so a web site cannot be sure that a web tag really has the origin it claims to have.

In turn, implementations can make sure that at least web sites cannot write other than web tag content, and at least web pages cannot alter the origin written with the content [*]. Then, native and web clients know that the content originates from a web site, so extra caution may be needed (unless it has been tampered with, but the result of that is more thorough checks, so this should be ok).

So web-specific tags can be seen as a convenience, by storing the origin/path of the website (browsing context) which has written the content. This opens up extra content handling options. But any policies based on assumptions about the origin of the data are broken from start.

[*] Note that the most recent, yet unpublished version saves the origin and path of the writer, together with the message, and discontinues the former notion of "scope".

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 19, 2015

Contributor

I would vote for 1 or 3. I actually think that 3 is fine (with prompt, more info in next comment).

We also need to read empty tags by default (ie. without calling watch). Question is how should one call watch() to be able to read non web-tags?

Contributor

kenchris commented Aug 19, 2015

I would vote for 1 or 3. I actually think that 3 is fine (with prompt, more info in next comment).

We also need to read empty tags by default (ie. without calling watch). Question is how should one call watch() to be able to read non web-tags?

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 19, 2015

Contributor

So yeah, you can use a native app to fake the origin/path (you cannot from a web app). I guess that there is a change that users might do that to bypass buying subscriptions etc from web sites - ie try to cheat the site, but the site can add tokens etc to the tag for avoid such cases. In that way it is not really a security issue.

I guess the problem is if a person walks up to a bar and there is a place to tap the nfc reader and it says to enter the site and tap the nfc tag. Now the nfc tag is fake and it tricks the user into getting the site to read a fake tag. I am not really sure that is a big problem either (we are trying to protect the user from random sites reading his data, not the sites).

What the origin/path makes sure, is that random sites don't read info not made for them, so it protects the user for giving random sites access to data (unless the user manually goes and modifies the origin/path - but then the user knows what he is doing). I do think that is a pretty good protection of the user and his/her data. If you tap a tag by mistake, at least only the site intended to read it, will read it (without prompts).

Non web-tags are not safe in that sense, so we probably shouldn't allow random sites to get access to that info, without at least some consent from the user, ie. a prompt when the site watches for non web-tags.

Contributor

kenchris commented Aug 19, 2015

So yeah, you can use a native app to fake the origin/path (you cannot from a web app). I guess that there is a change that users might do that to bypass buying subscriptions etc from web sites - ie try to cheat the site, but the site can add tokens etc to the tag for avoid such cases. In that way it is not really a security issue.

I guess the problem is if a person walks up to a bar and there is a place to tap the nfc reader and it says to enter the site and tap the nfc tag. Now the nfc tag is fake and it tricks the user into getting the site to read a fake tag. I am not really sure that is a big problem either (we are trying to protect the user from random sites reading his data, not the sites).

What the origin/path makes sure, is that random sites don't read info not made for them, so it protects the user for giving random sites access to data (unless the user manually goes and modifies the origin/path - but then the user knows what he is doing). I do think that is a pretty good protection of the user and his/her data. If you tap a tag by mistake, at least only the site intended to read it, will read it (without prompts).

Non web-tags are not safe in that sense, so we probably shouldn't allow random sites to get access to that info, without at least some consent from the user, ie. a prompt when the site watches for non web-tags.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 19, 2015

Contributor

What the origin/path makes sure, is that random sites don't read info not made for them

We currently don't support this with origin/path. We don't have any means to say which sites are permitted to read the content (with or without permission dialogs).

Currently any random site can read any web tag. We used to have the white and black lists, but security discussions revealed that they make little sense, again because of false sense of security.

Contributor

zolkis commented Aug 19, 2015

What the origin/path makes sure, is that random sites don't read info not made for them

We currently don't support this with origin/path. We don't have any means to say which sites are permitted to read the content (with or without permission dialogs).

Currently any random site can read any web tag. We used to have the white and black lists, but security discussions revealed that they make little sense, again because of false sense of security.

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 19, 2015

Contributor

Actually thinking about it. My passport has some RFID tech (but it could have been NFC) so it often lays on the table after travelling and it is not uncommon that I lay my phone on top of it.

I don't want random sites to be able to read that info and share it to the cloud. This even means that if reading non web-nfc tags, I don't want to give the site permission to read any non web-nfc tag at any time, so if I allow that, it should be per read, and disappear when the document becomes unfocused (like my phone screen turns off)

Contributor

kenchris commented Aug 19, 2015

Actually thinking about it. My passport has some RFID tech (but it could have been NFC) so it often lays on the table after travelling and it is not uncommon that I lay my phone on top of it.

I don't want random sites to be able to read that info and share it to the cloud. This even means that if reading non web-nfc tags, I don't want to give the site permission to read any non web-nfc tag at any time, so if I allow that, it should be per read, and disappear when the document becomes unfocused (like my phone screen turns off)

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 19, 2015

Contributor

no @zolkis, that is the point, only same origin should be able to read web-nfc tags without prompts when calling watch()

Contributor

kenchris commented Aug 19, 2015

no @zolkis, that is the point, only same origin should be able to read web-nfc tags without prompts when calling watch()

@jyasskin

This comment has been minimized.

Show comment
Hide comment
@jyasskin

jyasskin Aug 19, 2015

For web-page/same-origin-web-tag pairings, +1 on inferring permission from the foregroundness and the tap. I don't think asking for forgiveness is appropriate here: unlike fullscreen, any damage is done as soon as the message is transferred. We should just treat same-origin communication as ok.

For web-page/cross-origin-web-tag pairings, we can say "Do you want to let https://origin1.com/ read this tag from https://origin2.com/?", and we can give a "remember this choice" checkbox for that origin pairing. We can even give the user a multi-way choice, between letting the current page read the tag, opening the tag's URL, and ignoring the tag. That makes a pretty good dialog. This would happen on tapping the tag, not on watching the cross-origin url.

For non-web tags, we don't have an origin to ask the user about. We could ask about the mime type, but folks are less used to being asked about mime types, so it'll be hard without a database of human-readable names for them.

Does NFC give you the technical ability to identify that you're seeing a particular physical tag for the second time (ignoring malicious native apps)? If so, we could "remember this choice" about that exact pairing, so the user can pair their metro card with a particular site.

(Note that there shouldn't be any normative requirements about this in the spec. The spec should include a place to get the user's consent, and say what happens if the user doesn't give consent, but otherwise leave it up to the UA. This issue is just about informatively outlining some options for UAs.)

jyasskin commented Aug 19, 2015

For web-page/same-origin-web-tag pairings, +1 on inferring permission from the foregroundness and the tap. I don't think asking for forgiveness is appropriate here: unlike fullscreen, any damage is done as soon as the message is transferred. We should just treat same-origin communication as ok.

For web-page/cross-origin-web-tag pairings, we can say "Do you want to let https://origin1.com/ read this tag from https://origin2.com/?", and we can give a "remember this choice" checkbox for that origin pairing. We can even give the user a multi-way choice, between letting the current page read the tag, opening the tag's URL, and ignoring the tag. That makes a pretty good dialog. This would happen on tapping the tag, not on watching the cross-origin url.

For non-web tags, we don't have an origin to ask the user about. We could ask about the mime type, but folks are less used to being asked about mime types, so it'll be hard without a database of human-readable names for them.

Does NFC give you the technical ability to identify that you're seeing a particular physical tag for the second time (ignoring malicious native apps)? If so, we could "remember this choice" about that exact pairing, so the user can pair their metro card with a particular site.

(Note that there shouldn't be any normative requirements about this in the spec. The spec should include a place to get the user's consent, and say what happens if the user doesn't give consent, but otherwise leave it up to the UA. This issue is just about informatively outlining some options for UAs.)

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 19, 2015

Contributor

@kenchris
So you propose a new policy (in addition to the above which concern non-web tags) which says that even for web tags, UA must obtain permission to read them, unless the reading page has the same origin that has written the content. That means you can only read the tags you created, and no one else's (without permission). In general case, you basically ask that the UA needs permission for reading even web tags (when setting up the watch()).

The problem is with NFC we cannot implement sessions, and we cannot "pair" with a given device or tag so that we can remember user choices about them. Therefore every tap will require permission if we want to implement the policy you are asking for.

Contributor

zolkis commented Aug 19, 2015

@kenchris
So you propose a new policy (in addition to the above which concern non-web tags) which says that even for web tags, UA must obtain permission to read them, unless the reading page has the same origin that has written the content. That means you can only read the tags you created, and no one else's (without permission). In general case, you basically ask that the UA needs permission for reading even web tags (when setting up the watch()).

The problem is with NFC we cannot implement sessions, and we cannot "pair" with a given device or tag so that we can remember user choices about them. Therefore every tap will require permission if we want to implement the policy you are asking for.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 19, 2015

Contributor

@jyasskin
See the points above. AFAIK you can't "pair" with NFC, unlike with Bluetooth.
The only thing we can do is building a white list of origin pairs in the UA as you have suggested.
Do we have means by which the user can review/reset that white list?

Contributor

zolkis commented Aug 19, 2015

@jyasskin
See the points above. AFAIK you can't "pair" with NFC, unlike with Bluetooth.
The only thing we can do is building a white list of origin pairs in the UA as you have suggested.
Do we have means by which the user can review/reset that white list?

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 19, 2015

Contributor

There seems to be an insolvable conflict between the desire to remove prompts (@sicking) and protecting user data (@kenchris).

We seem to suggest a security dialog per calls to the watch() function which specify different filters. Because it is not (re)published yet, for context I share the planned signature.

partial interface NFCAdapter {
   Promise<long> watch(NFCWatchOptions options);
    void unwatch(long id);
}

dictionary NFCWatchOptions {
    USVString url;  // can contain wildcards; it could also be a pattern?
}

So when a page requests and obtains an adapter object, no permissions are asked yet.
The page can subscribe to onmessage events, and no permissions are asked.
But here we need a policy:

  1. the page will get none of the events until it calls the watch() function, where it must specify the URL [pattern] to be matched. There may be multiple calls to watch(), each with a different URL [pattern].
  2. the page may get messages without calling watch(), but when calling watch() with a specific URL [pattern], subsequently it will get only those which match.

Based on previous comments, it seems that we can rule out 2, since we do require permissions before reading. So I assume the policy is 1.

For each distinct call to watch(), a permission should be obtained by the UA. This can be done via persistent user preferences, or prompting the user (up to the UA). Using these dialogs, the UA can build a white list as suggested by @jyasskin here.

In practice, webpages will probably want to watch everything, or the alternative is to call watch() many, many times. Similarly, building the white list across numerous calls of watch() is tedious. I wonder what user experience will it give - to me it seems close enough to getting a prompt at each tap.

Contributor

zolkis commented Aug 19, 2015

There seems to be an insolvable conflict between the desire to remove prompts (@sicking) and protecting user data (@kenchris).

We seem to suggest a security dialog per calls to the watch() function which specify different filters. Because it is not (re)published yet, for context I share the planned signature.

partial interface NFCAdapter {
   Promise<long> watch(NFCWatchOptions options);
    void unwatch(long id);
}

dictionary NFCWatchOptions {
    USVString url;  // can contain wildcards; it could also be a pattern?
}

So when a page requests and obtains an adapter object, no permissions are asked yet.
The page can subscribe to onmessage events, and no permissions are asked.
But here we need a policy:

  1. the page will get none of the events until it calls the watch() function, where it must specify the URL [pattern] to be matched. There may be multiple calls to watch(), each with a different URL [pattern].
  2. the page may get messages without calling watch(), but when calling watch() with a specific URL [pattern], subsequently it will get only those which match.

Based on previous comments, it seems that we can rule out 2, since we do require permissions before reading. So I assume the policy is 1.

For each distinct call to watch(), a permission should be obtained by the UA. This can be done via persistent user preferences, or prompting the user (up to the UA). Using these dialogs, the UA can build a white list as suggested by @jyasskin here.

In practice, webpages will probably want to watch everything, or the alternative is to call watch() many, many times. Similarly, building the white list across numerous calls of watch() is tedious. I wonder what user experience will it give - to me it seems close enough to getting a prompt at each tap.

@jyasskin

This comment has been minimized.

Show comment
Hide comment
@jyasskin

jyasskin Aug 19, 2015

@sicking focused on same-origin messages in his comment, which I think everyone agrees don't need prompts. (Pending @ngparker confirming that Chrome Security isn't worried.) We don't need to support cross-origin messages at all in the first version of the Web NFC API, if they're contentious.

Policy (1) looks good.

Even for cross-origin or non-web tags, I don't think it's "For each distinct call to watch(), a permission should be obtained by the UA." "For each distinct call" is wrong because I might watch() 2 paths within an origin. It's permission to the origin that matters, not permission for each watch() call. "A permission should be obtained" misleadingly implies a prompt, which would be wrong if I'm watch()ing my own origin.

I'm also pretty sure webpages won't want to watch everything. Lots of tags will just have data formats they don't understand, and a major use of watch() should be to filter out events they'd just have to drop anyway.

jyasskin commented Aug 19, 2015

@sicking focused on same-origin messages in his comment, which I think everyone agrees don't need prompts. (Pending @ngparker confirming that Chrome Security isn't worried.) We don't need to support cross-origin messages at all in the first version of the Web NFC API, if they're contentious.

Policy (1) looks good.

Even for cross-origin or non-web tags, I don't think it's "For each distinct call to watch(), a permission should be obtained by the UA." "For each distinct call" is wrong because I might watch() 2 paths within an origin. It's permission to the origin that matters, not permission for each watch() call. "A permission should be obtained" misleadingly implies a prompt, which would be wrong if I'm watch()ing my own origin.

I'm also pretty sure webpages won't want to watch everything. Lots of tags will just have data formats they don't understand, and a major use of watch() should be to filter out events they'd just have to drop anyway.

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 19, 2015

The passport scenario is indeed an interesting one.

Do you feel that it's different if the thing reading your passport is a native app, running in the background, which you have installed?

Would you think twice about putting your phone on your passport if the phone was telling you that the current foreground webpage had enabled NFC?

sicking commented Aug 19, 2015

The passport scenario is indeed an interesting one.

Do you feel that it's different if the thing reading your passport is a native app, running in the background, which you have installed?

Would you think twice about putting your phone on your passport if the phone was telling you that the current foreground webpage had enabled NFC?

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 19, 2015

I don't think a prompt like "Do you want to let https://origin1.com/ read this tag from https://origin2.com/?" makes any more sense than "Do you want to let https://origin1.com/ make network connections to https://origin2.com/?". I.e. I don't think users can meaningfully make a decision about if that's safe or not.

I.e. if we feel that it's not safe enough that we can enable that by default, then I don't think we should enable it at all.

sicking commented Aug 19, 2015

I don't think a prompt like "Do you want to let https://origin1.com/ read this tag from https://origin2.com/?" makes any more sense than "Do you want to let https://origin1.com/ make network connections to https://origin2.com/?". I.e. I don't think users can meaningfully make a decision about if that's safe or not.

I.e. if we feel that it's not safe enough that we can enable that by default, then I don't think we should enable it at all.

@ngparker

This comment has been minimized.

Show comment
Hide comment
@ngparker

ngparker Aug 19, 2015

I think reading same-origin tags with an "ask forgiveness" rather than "ask permission" model is a reasonably small privacy cost for a gain in usability.

e.g. Suppose www.popularsocialnetwork.com pays restaurants to embed tags in their tables. People who are commonly on that site all the time put their phone on the table, and leak their location. If this happened once and the user was notified and could disable further tag reading, the harm would be limited.

I think different-origin should require a permissions since it has potential to leak a lot more info.

ngparker commented Aug 19, 2015

I think reading same-origin tags with an "ask forgiveness" rather than "ask permission" model is a reasonably small privacy cost for a gain in usability.

e.g. Suppose www.popularsocialnetwork.com pays restaurants to embed tags in their tables. People who are commonly on that site all the time put their phone on the table, and leak their location. If this happened once and the user was notified and could disable further tag reading, the harm would be limited.

I think different-origin should require a permissions since it has potential to leak a lot more info.

@ngparker

This comment has been minimized.

Show comment
Hide comment
@ngparker

ngparker Aug 20, 2015

Re making sense of cross-origin prompt text: I agree that asking about a pair is not helpful. It could be allow-all, i.e. "Do you want to let https://origin1.com read tags from any domain?" That's only slightly easier to understand. Otherwise, I'd go with not allowing cross-origin at all.

ngparker commented Aug 20, 2015

Re making sense of cross-origin prompt text: I agree that asking about a pair is not helpful. It could be allow-all, i.e. "Do you want to let https://origin1.com read tags from any domain?" That's only slightly easier to understand. Otherwise, I'd go with not allowing cross-origin at all.

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 20, 2015

In the end, we challenge even the idea of having web-specific tags. Including an extra special record in NDEF messages (or indicating in any other way that the content is web-specific) does not solve any security problems, but it may add new ones because of false sense of security. Everything is forgeable/changeable using native clients, so a web site cannot be sure that a web tag really has the origin it claims to have.

There are two basic assumptions in play here:

  1. Users do not install native applications that they don't trust.
  2. Users do visit websites that they don't trust.

Note that browsers are native apps, so based on 1 above, users only install browser implementations that they trust.

So while it is entirely possible for a native app to pretend to be any website, the assumption here is that they user trust that app. I.e. the app will still act in the users best interest. When apps are created that trick users about their intentions and don't act in the users interest, we call these apps malware and remove them from app stores.

The web security model is based on the assumption that websites will try to do evil things. We deal with this by limiting the harm that websites can do when you go to them.

If we think no harm can come to allowing any and all websites get read/write access to any and all NFC tags/peers that the user tags then I agree that we don't need a way to expose NFC tags/peers as "web compatible".

I.e. if we think that all writable NFC tags out there can be arbitrarily overwritten with arbitrary data without any loss of significant information to anyone, and we think that all NFC P2P software won't take any irreversable actions without first asking the user through other means, then I think that we wouldn't need any "web compatible" flag.

But it seems like a tall order to me. This has not been true for internet connected servers for example. Lots of servers protect themselves by being behind a firewall. They rely on that even though the user might be browsing harmful websites while inside the firewall, that the web security model protect these website from causing harm to the servers behind the firewall.

I would imagine that NFC tags make the same assumption. That they assume that users that can physically get to the NFC tag will only run trusted apps. If these tags can be written to by untrusted websites that the user visit when tagging the tag then that breaks that assumption.

sicking commented Aug 20, 2015

In the end, we challenge even the idea of having web-specific tags. Including an extra special record in NDEF messages (or indicating in any other way that the content is web-specific) does not solve any security problems, but it may add new ones because of false sense of security. Everything is forgeable/changeable using native clients, so a web site cannot be sure that a web tag really has the origin it claims to have.

There are two basic assumptions in play here:

  1. Users do not install native applications that they don't trust.
  2. Users do visit websites that they don't trust.

Note that browsers are native apps, so based on 1 above, users only install browser implementations that they trust.

So while it is entirely possible for a native app to pretend to be any website, the assumption here is that they user trust that app. I.e. the app will still act in the users best interest. When apps are created that trick users about their intentions and don't act in the users interest, we call these apps malware and remove them from app stores.

The web security model is based on the assumption that websites will try to do evil things. We deal with this by limiting the harm that websites can do when you go to them.

If we think no harm can come to allowing any and all websites get read/write access to any and all NFC tags/peers that the user tags then I agree that we don't need a way to expose NFC tags/peers as "web compatible".

I.e. if we think that all writable NFC tags out there can be arbitrarily overwritten with arbitrary data without any loss of significant information to anyone, and we think that all NFC P2P software won't take any irreversable actions without first asking the user through other means, then I think that we wouldn't need any "web compatible" flag.

But it seems like a tall order to me. This has not been true for internet connected servers for example. Lots of servers protect themselves by being behind a firewall. They rely on that even though the user might be browsing harmful websites while inside the firewall, that the web security model protect these website from causing harm to the servers behind the firewall.

I would imagine that NFC tags make the same assumption. That they assume that users that can physically get to the NFC tag will only run trusted apps. If these tags can be written to by untrusted websites that the user visit when tagging the tag then that breaks that assumption.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 20, 2015

Contributor

Otherwise, I'd go with not allowing cross-origin at all.

That would mean web pages can only read content (coming from peers or tags) which was written by them. I think that is too much limitation. We kind of deprive users from using (most of) NFC because we don't want to disturb them :). Yet this still leaves a lot of use cases possible.

IMO the spec itself should be concerned with stating the need for obtaining permissions rather than specifying prompting policies which may be platform dependent.

On the other hand, the spec actually states that the browser security mechanisms are used, i.e. NFC content is handled the same way as any other content (vs cross-origin access).

Contributor

zolkis commented Aug 20, 2015

Otherwise, I'd go with not allowing cross-origin at all.

That would mean web pages can only read content (coming from peers or tags) which was written by them. I think that is too much limitation. We kind of deprive users from using (most of) NFC because we don't want to disturb them :). Yet this still leaves a lot of use cases possible.

IMO the spec itself should be concerned with stating the need for obtaining permissions rather than specifying prompting policies which may be platform dependent.

On the other hand, the spec actually states that the browser security mechanisms are used, i.e. NFC content is handled the same way as any other content (vs cross-origin access).

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 20, 2015

IMO the spec itself should be concerned with stating the need for obtaining permissions rather than specifying prompting policies which may be platform dependent.

I don't think asking the user to make decisions about what's safe and what's not safe is useful. What information will the user use to base that decision on? I.e. how will the user know if allowing access to a given tag is safe or not?

I guess that's the short version of my longer response above. If we think that permission of some form needs to be granted by anyone, then I think it needs to be the tag that grants the permission. Not the user.

On the other hand, the spec actually states that the browser security mechanisms are used, i.e. NFC content is handled the same way as any other content (vs cross-origin access).

For cross-origin access of network content we require that the website explicitly say that it either can be read by a given website, or that it can be read by all websites.

I.e. for website X to be able to read from website Y, website Y must either explicitly white-list X, or say that any website can read the contents.

sicking commented Aug 20, 2015

IMO the spec itself should be concerned with stating the need for obtaining permissions rather than specifying prompting policies which may be platform dependent.

I don't think asking the user to make decisions about what's safe and what's not safe is useful. What information will the user use to base that decision on? I.e. how will the user know if allowing access to a given tag is safe or not?

I guess that's the short version of my longer response above. If we think that permission of some form needs to be granted by anyone, then I think it needs to be the tag that grants the permission. Not the user.

On the other hand, the spec actually states that the browser security mechanisms are used, i.e. NFC content is handled the same way as any other content (vs cross-origin access).

For cross-origin access of network content we require that the website explicitly say that it either can be read by a given website, or that it can be read by all websites.

I.e. for website X to be able to read from website Y, website Y must either explicitly white-list X, or say that any website can read the contents.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 20, 2015

Contributor

In our case (NFC) we may include white lists/patterns or black lists/pattern in the (meta)content, but it's easily forgeable by native clients. You said earlier that's OK since we are only concerned about preventing web pages from forging these, which we can achieve.

Summarizing the discussion, can we say that

  1. same origin read/write access doesn't need prompting
  2. empty tags (TNF=0) can be written without prompt
  3. cross-origin access (reading from different origin and writing to different origin) is determined by a white list/pattern which is written to the content [*] and no prompt is used.
  4. if origin information is missing, we apply a restrictive policy, i.e. access is denied (reads are not exposed and write is denied). A permissive policy would leak the passport information in the example @kenchris gave.

[*] for this we have 2 alternate designs, one is using a special Web NFC record and another one using the ID field of each record. This will be outlined later, but first let's agree on what we do.

Contributor

zolkis commented Aug 20, 2015

In our case (NFC) we may include white lists/patterns or black lists/pattern in the (meta)content, but it's easily forgeable by native clients. You said earlier that's OK since we are only concerned about preventing web pages from forging these, which we can achieve.

Summarizing the discussion, can we say that

  1. same origin read/write access doesn't need prompting
  2. empty tags (TNF=0) can be written without prompt
  3. cross-origin access (reading from different origin and writing to different origin) is determined by a white list/pattern which is written to the content [*] and no prompt is used.
  4. if origin information is missing, we apply a restrictive policy, i.e. access is denied (reads are not exposed and write is denied). A permissive policy would leak the passport information in the example @kenchris gave.

[*] for this we have 2 alternate designs, one is using a special Web NFC record and another one using the ID field of each record. This will be outlined later, but first let's agree on what we do.

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 20, 2015

I don't understand what 3 above means. What is the purpose of having separate origin information from white-list information?

Why don't we simply let tags contain a list which indicates "origins X, Y and Z can read/write this tag"? We should also allow the tag to indicate "any origin can read/write this tag".

sicking commented Aug 20, 2015

I don't understand what 3 above means. What is the purpose of having separate origin information from white-list information?

Why don't we simply let tags contain a list which indicates "origins X, Y and Z can read/write this tag"? We should also allow the tag to indicate "any origin can read/write this tag".

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 20, 2015

Contributor

Writing something to an NFC tag is not much more secure than writing it down on a piece of paper.

My wife now writes a recipe on a piece of paper. When it is laying around in the house, everyone can read it (same origin - no prompts really necessary).

Now someone (Peter) visits and sees that paper and asks if he may have a look (prompt - not same origin). I the user, can decide to show it or not. (I got told that Peter would like to look (request) and I explicitly handed the recipe to him (tapped the tag))

It is pretty much up to me. Now my wife may have said to me that I should not show it to anyone, but that power is really up to me, the user.

I don't like white lists much, they are going to get outdated quickly. (Think if my wife had to write down on the paper who could read it - she could not include everyone and would get it wrong) So one option would be to mark the tag as "not for sharing" and somehow let the user decide to obey that or share anyway. Or we would somehow need to get the external site to ask permission from the original site.

I guess a whitelist could be stored online, but I don't think it will scale... I might find a small site which I trust and which can do something smart with the data that I wrote to the NFC tag from www.superawesomegame.com (they can only read, not modify - so they might be able to tell me exciting info about my character in the game)

And ultimately I think the user is the one who should be in control, just like I could take the recipe and mail to to Super Awesome Cakes, Ltd.

Also if a site really wants to protect the data, they can encrypt it and give the encryption key to sites they trust. I mean such a security system could be implemented on top.

Contributor

kenchris commented Aug 20, 2015

Writing something to an NFC tag is not much more secure than writing it down on a piece of paper.

My wife now writes a recipe on a piece of paper. When it is laying around in the house, everyone can read it (same origin - no prompts really necessary).

Now someone (Peter) visits and sees that paper and asks if he may have a look (prompt - not same origin). I the user, can decide to show it or not. (I got told that Peter would like to look (request) and I explicitly handed the recipe to him (tapped the tag))

It is pretty much up to me. Now my wife may have said to me that I should not show it to anyone, but that power is really up to me, the user.

I don't like white lists much, they are going to get outdated quickly. (Think if my wife had to write down on the paper who could read it - she could not include everyone and would get it wrong) So one option would be to mark the tag as "not for sharing" and somehow let the user decide to obey that or share anyway. Or we would somehow need to get the external site to ask permission from the original site.

I guess a whitelist could be stored online, but I don't think it will scale... I might find a small site which I trust and which can do something smart with the data that I wrote to the NFC tag from www.superawesomegame.com (they can only read, not modify - so they might be able to tell me exciting info about my character in the game)

And ultimately I think the user is the one who should be in control, just like I could take the recipe and mail to to Super Awesome Cakes, Ltd.

Also if a site really wants to protect the data, they can encrypt it and give the encryption key to sites they trust. I mean such a security system could be implemented on top.

@alexshalamov

This comment has been minimized.

Show comment
Hide comment
@alexshalamov

alexshalamov Aug 20, 2015

@kenchris @sicking, Passport case is not valid one, usually MifareClassic, MifareDESfire or IsoDep compatible tags are used. Those tags have authentication methods for accessing protected blocks on a tag. Web NFC API is operating on NDEF level.

alexshalamov commented Aug 20, 2015

@kenchris @sicking, Passport case is not valid one, usually MifareClassic, MifareDESfire or IsoDep compatible tags are used. Those tags have authentication methods for accessing protected blocks on a tag. Web NFC API is operating on NDEF level.

@kenchris

This comment has been minimized.

Show comment
Hide comment
@kenchris

kenchris Aug 20, 2015

Contributor

@alexshalamov as I said it was a thought example. It could have been using NFC. Also in the future we might support more than just NDEF.

Contributor

kenchris commented Aug 20, 2015

@alexshalamov as I said it was a thought example. It could have been using NFC. Also in the future we might support more than just NDEF.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 20, 2015

Contributor

@sicking

Why don't we simply let tags contain a list which indicates "origins X, Y and Z can read/write this tag"? We should also allow the tag to indicate "any origin can read/write this tag".

That is what I meant about a white list. In addition, when a tag is written, the origin of the writing page is also saved anyway. This, and (currently) the presence of the Web NFC record indicates that the tag is a web tag.

If you meant that instead of pattern matching we should use a list of exact origins + an "all origins" wildcard, then I am taking the point, but would deserve some more explanation :).

Now @alexshalamov has proposed this and I think it's a good idea.

  • We could implement "being a web tag" without a special Web NFC record, by using the NDEF id field to store the writing origin (contained in max 253 byes which fits the NDEF Id field). That would even allow mixing web content with multiple origins and legacy content in a single tag, and even work with the platforms which currently expose only one record per message (Windows and neard/Linux).
  • The writing page could indicate it permits access to all origins, and the UA could serialize that as <origin> + "/*" and still safely fit in the Id field. This means that if you want to say which exact origins to be able to read your data, you write a web NFC record, but if you want either the same-origin policy applied, or no policy (everyone can access), then the NDEF Id field would be enough.

The consequences are the following:

  • Empty tags can be read and written (as before).
  • By default, writes are partitioned per origin. Every origin can write a tag, but that means only adding record(s) with its origin (plus the * flag eventually) recorded, without affecting other records on the tag. When writing, all the records with the given origin are replaced, but no records of other origins are affected. If that is not possible, the write fails.
  • When writing a tag with an explicit list of target origins, UA's need to write a Web NFC record which contains that list and the writing origin. Otherwise a Web NFC record is not mandatory (only to write the origin into the Id field).
  • When reading NFC content (message), and if there is a Web NFC record, that dictates the read policy for the whole message: origin and white list.
  • If there is no Web NFC record, then the same-origin policy is applied for all reads: you only get the records you created or which have any origin + the * flag.
  • This also means that legacy records are not exposed by default (since they fail the same-origin check). We can change that policy if you want: we could also say that a missing origin information from the Id field of the record means that everyone can read. And write (but not erase+write). Please provide input on this, both on the read and write policy.
  • We need to make difference between the partitioned writes (above) and complete erase+write operation on a tag. I argue that we could allow that with a new separate method, which would require user permission. It is rare case, but IMO we could enable it for convenience, at the expense of prompting in a corner case.
Contributor

zolkis commented Aug 20, 2015

@sicking

Why don't we simply let tags contain a list which indicates "origins X, Y and Z can read/write this tag"? We should also allow the tag to indicate "any origin can read/write this tag".

That is what I meant about a white list. In addition, when a tag is written, the origin of the writing page is also saved anyway. This, and (currently) the presence of the Web NFC record indicates that the tag is a web tag.

If you meant that instead of pattern matching we should use a list of exact origins + an "all origins" wildcard, then I am taking the point, but would deserve some more explanation :).

Now @alexshalamov has proposed this and I think it's a good idea.

  • We could implement "being a web tag" without a special Web NFC record, by using the NDEF id field to store the writing origin (contained in max 253 byes which fits the NDEF Id field). That would even allow mixing web content with multiple origins and legacy content in a single tag, and even work with the platforms which currently expose only one record per message (Windows and neard/Linux).
  • The writing page could indicate it permits access to all origins, and the UA could serialize that as <origin> + "/*" and still safely fit in the Id field. This means that if you want to say which exact origins to be able to read your data, you write a web NFC record, but if you want either the same-origin policy applied, or no policy (everyone can access), then the NDEF Id field would be enough.

The consequences are the following:

  • Empty tags can be read and written (as before).
  • By default, writes are partitioned per origin. Every origin can write a tag, but that means only adding record(s) with its origin (plus the * flag eventually) recorded, without affecting other records on the tag. When writing, all the records with the given origin are replaced, but no records of other origins are affected. If that is not possible, the write fails.
  • When writing a tag with an explicit list of target origins, UA's need to write a Web NFC record which contains that list and the writing origin. Otherwise a Web NFC record is not mandatory (only to write the origin into the Id field).
  • When reading NFC content (message), and if there is a Web NFC record, that dictates the read policy for the whole message: origin and white list.
  • If there is no Web NFC record, then the same-origin policy is applied for all reads: you only get the records you created or which have any origin + the * flag.
  • This also means that legacy records are not exposed by default (since they fail the same-origin check). We can change that policy if you want: we could also say that a missing origin information from the Id field of the record means that everyone can read. And write (but not erase+write). Please provide input on this, both on the read and write policy.
  • We need to make difference between the partitioned writes (above) and complete erase+write operation on a tag. I argue that we could allow that with a new separate method, which would require user permission. It is rare case, but IMO we could enable it for convenience, at the expense of prompting in a corner case.
@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 20, 2015

Contributor

BTW I would get rid of white lists for now. It would simplify things a lot. Same-origin is enough, plus eventually no-policy (* flag, i.e. everyone can read/write). Plus the rules above.

Contributor

zolkis commented Aug 20, 2015

BTW I would get rid of white lists for now. It would simplify things a lot. Same-origin is enough, plus eventually no-policy (* flag, i.e. everyone can read/write). Plus the rules above.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 20, 2015

Contributor

We need to make a decision for the upcoming version of the spec. I propose what seems to be (close to) the consensus here:

  • No prompts required for same-origin access (eventually ask-forgiveness).
  • User permission required for cross-origin access (including legacy tags); if not obtained for any reason (including that the browser doesn't want to show user prompts), methods will fail.
  • Use Alex' idea for implementation: origin saved in NDEF Id, support partitioned writes, but no white list support in the coming version. Track white list support in an enhancement issue. Remove Web NFC record from the spec (since it's not needed at the moment).
  • No permissions required for partitioned writes (since they are same-origin by definition).
  • Require permission for erase+write (unless same origin).
  • Optionally, use paths along with origins, to support watch() filtering within same-origin.
Contributor

zolkis commented Aug 20, 2015

We need to make a decision for the upcoming version of the spec. I propose what seems to be (close to) the consensus here:

  • No prompts required for same-origin access (eventually ask-forgiveness).
  • User permission required for cross-origin access (including legacy tags); if not obtained for any reason (including that the browser doesn't want to show user prompts), methods will fail.
  • Use Alex' idea for implementation: origin saved in NDEF Id, support partitioned writes, but no white list support in the coming version. Track white list support in an enhancement issue. Remove Web NFC record from the spec (since it's not needed at the moment).
  • No permissions required for partitioned writes (since they are same-origin by definition).
  • Require permission for erase+write (unless same origin).
  • Optionally, use paths along with origins, to support watch() filtering within same-origin.
@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 20, 2015

Since we seem to be getting stuck and going in circles on the details here, let me try to rephrase the mozilla requirements at a higher level.

  • We should only ask the user questions that they can reasonably make an informed decision on and where the consequences of saying "yes" is clear. Things like "do you want to share your location with this website" and "do you want this website to be able to use your camera and microphone" have understandable consequences to users. Things like "do you want to allow this website to write to this NFC tag" or "do you want to allow this website to send an NFC message to this P2P peer" does not have understandable consequences to the user.
  • We need to define when a prompt will be displayed and when it won't. Simply saying "UA policy" is not good enough for two reasons.
    • Websites care a lot about when a prompt is displayed. If one is displayed when they didn't expect it to, they consider that broken behavior.
    • If a UA automatically deny a particular action when the website did expect a prompt to displayed, that effectively means that that functionality is broken to the website.
  • This does mean that we have a problem if two different browsers want to prompt for different things. However for every other web specification created so far we have been able to resolve those differences. So I have confidence that we can resolve that here too.
  • If we can't make a particular NFC read/write/message-exchange safe to all websites everywhere, including evil ones that are trying to hack the user, then we need someone to assert that a given action is safe. This means that either the user has to make that assertion, which does not seem possible to me per the first bullet, or the NFC tag needs to indicate what is safe and what isn't. For network requests we solve this using patterns like CORS and WebSocket which include explicit messages about which website can take what actions against a given server.
  • If we are relying on tags to indicate which actions are safe and which ones are not, then should use a very explicit format. One thing to be very careful of is if there are existing NFC tags out there that use the same format, then those could accidentally look like they are opting in to allowing a particular action even though that was not the intent of the person creating the NFC tag.

My concern with using a URL in the ID field as the way to indicate that an otherwise unsafe action is safe, is that the NDEF spec says that the ID field always includes a URL. But maybe I'm not understanding the thinking here.

sicking commented Aug 20, 2015

Since we seem to be getting stuck and going in circles on the details here, let me try to rephrase the mozilla requirements at a higher level.

  • We should only ask the user questions that they can reasonably make an informed decision on and where the consequences of saying "yes" is clear. Things like "do you want to share your location with this website" and "do you want this website to be able to use your camera and microphone" have understandable consequences to users. Things like "do you want to allow this website to write to this NFC tag" or "do you want to allow this website to send an NFC message to this P2P peer" does not have understandable consequences to the user.
  • We need to define when a prompt will be displayed and when it won't. Simply saying "UA policy" is not good enough for two reasons.
    • Websites care a lot about when a prompt is displayed. If one is displayed when they didn't expect it to, they consider that broken behavior.
    • If a UA automatically deny a particular action when the website did expect a prompt to displayed, that effectively means that that functionality is broken to the website.
  • This does mean that we have a problem if two different browsers want to prompt for different things. However for every other web specification created so far we have been able to resolve those differences. So I have confidence that we can resolve that here too.
  • If we can't make a particular NFC read/write/message-exchange safe to all websites everywhere, including evil ones that are trying to hack the user, then we need someone to assert that a given action is safe. This means that either the user has to make that assertion, which does not seem possible to me per the first bullet, or the NFC tag needs to indicate what is safe and what isn't. For network requests we solve this using patterns like CORS and WebSocket which include explicit messages about which website can take what actions against a given server.
  • If we are relying on tags to indicate which actions are safe and which ones are not, then should use a very explicit format. One thing to be very careful of is if there are existing NFC tags out there that use the same format, then those could accidentally look like they are opting in to allowing a particular action even though that was not the intent of the person creating the NFC tag.

My concern with using a URL in the ID field as the way to indicate that an otherwise unsafe action is safe, is that the NDEF spec says that the ID field always includes a URL. But maybe I'm not understanding the thinking here.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 20, 2015

Contributor

I think you have stated it pretty clearly, and it's the same of what you said earlier.

My concern with using a URL in the ID field as the way to indicate that an otherwise unsafe action is safe, is that the NDEF spec says that the ID field always includes a URL.

That is correct: if present, the ID field very likely contains a URL, and may match valid origins in many cases. Therefore you may say that using only the ID field is not good enough. But even in those cases, that URL was actually meant to identify the data, hence the usage would be similar and appropriate. If any side effects pop up, it would not affect the original native apps, but indeed may give access to the accidental origin match - which anyway is supposed to be linked with the data, so I see no threat other than now the data can be accessed via a browser and a site which was anyway connected to the payload.

If this is not good enough, then it means we must use at least one special record per message, which is web-nfc-specific, and which contains information about what origins can access the payload and how.

That has been designed quite early, and discarded in later versions, so we indeed went in circles.

Now I have questions/issues concerning the mechanisms "on tags to indicate which actions are safe and which ones are not".

  1. If the format is a "white list", should it be an explicit long list of distinct origins which are allowed to access the data, or could it be a list of URL patterns matching origins?
  2. Do you think we need to make a difference between read and write access for the actions (meaning no prompts - otherwise the operations may complete with prompts).
  3. In the actions, do we need to record a preference for allowing showing prompts or not? What is the default?

I would argue that at the moment we should start only with the following options:

  • only pages with the same origin can access the data (by default), or
  • any origin can access the data (the choice needs to be recorded in the tags)
  • otherwise we prompt (or fail).

I have assumed this (and then we don't strictly need any web nfc specific record), but if you want an explicit format for controlling access, please give some explicit examples and suggestions.

Contributor

zolkis commented Aug 20, 2015

I think you have stated it pretty clearly, and it's the same of what you said earlier.

My concern with using a URL in the ID field as the way to indicate that an otherwise unsafe action is safe, is that the NDEF spec says that the ID field always includes a URL.

That is correct: if present, the ID field very likely contains a URL, and may match valid origins in many cases. Therefore you may say that using only the ID field is not good enough. But even in those cases, that URL was actually meant to identify the data, hence the usage would be similar and appropriate. If any side effects pop up, it would not affect the original native apps, but indeed may give access to the accidental origin match - which anyway is supposed to be linked with the data, so I see no threat other than now the data can be accessed via a browser and a site which was anyway connected to the payload.

If this is not good enough, then it means we must use at least one special record per message, which is web-nfc-specific, and which contains information about what origins can access the payload and how.

That has been designed quite early, and discarded in later versions, so we indeed went in circles.

Now I have questions/issues concerning the mechanisms "on tags to indicate which actions are safe and which ones are not".

  1. If the format is a "white list", should it be an explicit long list of distinct origins which are allowed to access the data, or could it be a list of URL patterns matching origins?
  2. Do you think we need to make a difference between read and write access for the actions (meaning no prompts - otherwise the operations may complete with prompts).
  3. In the actions, do we need to record a preference for allowing showing prompts or not? What is the default?

I would argue that at the moment we should start only with the following options:

  • only pages with the same origin can access the data (by default), or
  • any origin can access the data (the choice needs to be recorded in the tags)
  • otherwise we prompt (or fail).

I have assumed this (and then we don't strictly need any web nfc specific record), but if you want an explicit format for controlling access, please give some explicit examples and suggestions.

@sicking

This comment has been minimized.

Show comment
Hide comment
@sicking

sicking Aug 20, 2015

If you feel that using the ID field is safe enough then I'll defer to you. I don't feel like I know the details about how people use NFC well enough to have a strong opinion.

  1. If the format is a "white list", should it be an explicit long list of distinct origins which are allowed to access the data, or could it be a list of URL patterns matching origins?

I think either is fine. The two cases that I think are critical is to indicate a single website, or to indicate "*", i.e. that all websites are granted access.

Another thing to keep in mind is that it is important to be able to say that "https://somewebsite.com" can access the tag, but that "http://somewebsite.com" can't. I.e. it's important to be able to require a secure connection.

I think it would be nice to be able to say that https://*.foo.com should have access, but I don't feel strongly either way here.

2 Do you think we need to make a difference between read and write access for the actions (meaning no prompts - otherwise the operations may complete with prompts).

I don't know of any usecases where separating read and write access is important.

3 In the actions, do we need to record a preference for allowing showing prompts or not? What is the default?

Given the requirements I mentioned above, I don't see how we can allow browsers to prompt anywhere, under any circumstances. But I'm happy to look at a detailed proposal which includes prompting if you can do that while meeting the requirements mentioned above.

Most specifically, I'm curious as to how you are proposing that the prompt would contain enough information that the user can make an informed decision.

sicking commented Aug 20, 2015

If you feel that using the ID field is safe enough then I'll defer to you. I don't feel like I know the details about how people use NFC well enough to have a strong opinion.

  1. If the format is a "white list", should it be an explicit long list of distinct origins which are allowed to access the data, or could it be a list of URL patterns matching origins?

I think either is fine. The two cases that I think are critical is to indicate a single website, or to indicate "*", i.e. that all websites are granted access.

Another thing to keep in mind is that it is important to be able to say that "https://somewebsite.com" can access the tag, but that "http://somewebsite.com" can't. I.e. it's important to be able to require a secure connection.

I think it would be nice to be able to say that https://*.foo.com should have access, but I don't feel strongly either way here.

2 Do you think we need to make a difference between read and write access for the actions (meaning no prompts - otherwise the operations may complete with prompts).

I don't know of any usecases where separating read and write access is important.

3 In the actions, do we need to record a preference for allowing showing prompts or not? What is the default?

Given the requirements I mentioned above, I don't see how we can allow browsers to prompt anywhere, under any circumstances. But I'm happy to look at a detailed proposal which includes prompting if you can do that while meeting the requirements mentioned above.

Most specifically, I'm curious as to how you are proposing that the prompt would contain enough information that the user can make an informed decision.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 21, 2015

Contributor

Another thing to keep in mind is that it is important to be able to say that "https://somewebsite.com" can access the tag, but that "http://somewebsite.com" can't. I.e. it's important to be able to require a secure connection.

Secure connection is mandatory in the spec. It has been a requirement from the start. The question is how to relax same-origin policy with explicit access control.

Most specifically, I'm curious as to how you are proposing that the prompt would contain enough information that the user can make an informed decision.

If I could guarantee that I could make people understand things, I would not be typing here, especially this much :).

Anyway, if prompts are so bad, we go with the same-origin policy.
For relaxing it, we can use access control - we can do it, certainly, but IMO it's not a good solution. If that is the price to move the spec forward, be it.

Do you expect access control be a mandatory feature already in the first version of the implementation, or could we go with same-origin policy and multi-partitioned use of a given physical tag, as described above, and if there is support for multiple records?

Personal note. I think user prompts in corner cases (not main use cases) is less of a problem than the false sense of security that access control recorded into tags would give, even if we trust the app stores deal with malefic apps. Damage done is damage done and it is not the same to blame someone's own sloppiness vs expectations towards an app store.
We cannot prevent adding any site to that access control, and there is no message integrity guarantee unless provided by application level means (encryption and key management).
I understand the unpopularity of prompts, but we are talking about prompting in corner cases vs decline the functionality with no possibilities for changing it.

Contributor

zolkis commented Aug 21, 2015

Another thing to keep in mind is that it is important to be able to say that "https://somewebsite.com" can access the tag, but that "http://somewebsite.com" can't. I.e. it's important to be able to require a secure connection.

Secure connection is mandatory in the spec. It has been a requirement from the start. The question is how to relax same-origin policy with explicit access control.

Most specifically, I'm curious as to how you are proposing that the prompt would contain enough information that the user can make an informed decision.

If I could guarantee that I could make people understand things, I would not be typing here, especially this much :).

Anyway, if prompts are so bad, we go with the same-origin policy.
For relaxing it, we can use access control - we can do it, certainly, but IMO it's not a good solution. If that is the price to move the spec forward, be it.

Do you expect access control be a mandatory feature already in the first version of the implementation, or could we go with same-origin policy and multi-partitioned use of a given physical tag, as described above, and if there is support for multiple records?

Personal note. I think user prompts in corner cases (not main use cases) is less of a problem than the false sense of security that access control recorded into tags would give, even if we trust the app stores deal with malefic apps. Damage done is damage done and it is not the same to blame someone's own sloppiness vs expectations towards an app store.
We cannot prevent adding any site to that access control, and there is no message integrity guarantee unless provided by application level means (encryption and key management).
I understand the unpopularity of prompts, but we are talking about prompting in corner cases vs decline the functionality with no possibilities for changing it.

@zolkis

This comment has been minimized.

Show comment
Hide comment
@zolkis

zolkis Aug 24, 2015

Contributor

@sicking

If you feel that using the ID field is safe enough then I'll defer to you.

The NDEF ID field is safe to use for containing URL's that identify the payload. However, we cannot call that "origin" and we cannot guarantee that the information we find in the NDEF ID field is actually the web origin which has written the data, since it can be altered (not by web pages though, but still can be altered).

Therefore we cannot speak about same origin and cross origin policies with regard to NFC content in the same way as we speak about normal web content, because we cannot speak about "origin" at all for NFC content. At best we have a "label" that is mutable by 3rd parties and which we can use in filters. Therefore any security policies based on that would be broken.

After many circles of discussions about this, NFC seems to be indeed in similar category as Geolocation. We can minimize the number of user prompts, but let's see if we can completely eliminate them, and if we cannot, then we need to come up with meaningful prompts or info banners when needed.

Luckily, since

  • we require https origins from clients, and
  • the client browsing contexts must be visible and in focus, (the device must also be unlocked and the display visible) and
  • the user must do a physical gesture in order to use NFC, both for reading or sending,

we can safely assume that the user does express permission to the identifiable and visible web page (Window connected to the active Document of the current browsing context) to use the NFC API each time it is used.

However, the user may not be aware about what kind of data is sent from the device: it can be any data the given web page can access (including revealing location directly or indirectly, eventually). Also, a malicious web page can use NFC as a transfer medium, but it is much more inconvenient than using other means, so incentive for the attack and hence the threat can be considered small. Anyway we should show non-blocking information about the page accessing NFC (and eventually specifying what source of data from the device), and the user can decide to complete the physical act of tapping of not.

When reading NFC, the threat is indeed more like revealing the user's physical proximity. This one we intended to solve with the same origin policy, so it can only happen if the user willfully navigates to a page with the same origin that can be found in the tag, in which case this can be again considered as intended by the user. However, since origins written on tags may be broken, we cannot safely do this. Therefore we should be able to notify the user in a non-blocking manner that the web page in focus may (in corner cases, since the tag needs to be connected with the active page) indicate the location of the user when reading the tag, so that the user can decide whether to continue or not with the physical gesture of tapping. I agree it is hard to formulate this well, so any suggestions are welcome. However, it is not the job of the spec to do this formulation: the question is whether is this policy good enough.

At the moment these are the most critical vectors that I can see, based on previous discussion.
@ngparker , could you please review and check the validity of the above?

If they hold true, we can simplify both the API and its usage.

And the conclusion is the same that @sicking suggested here a week ago, but unfortunately we got into the same-origin discussion:

So in summary, I think the spec should:

  • Explain the privacy aspect.
  • Not require that implementations prompt the user.
  • Suggest that some form of unobtrusive notification might be wanted if the implementation wants.
  • Explain that this notification would apply equally to all of reading/writing/p2p

But I repeat, we cannot safely implement any ACL's in tags, nor any security policies based on web origins written in the tags. We can call them labels and filters, though, and keep them as convenience, if we want, in this or later versions of the spec - I suggest the latter in order to keep things simpler for the start.

Since it seems that I agree with @sicking in this matter (with the remarks made above), and @kenchris and @anssiko also have expressed agreement earlier in this thread, unless @ngparker objects, we move forward with these assumptions.

Contributor

zolkis commented Aug 24, 2015

@sicking

If you feel that using the ID field is safe enough then I'll defer to you.

The NDEF ID field is safe to use for containing URL's that identify the payload. However, we cannot call that "origin" and we cannot guarantee that the information we find in the NDEF ID field is actually the web origin which has written the data, since it can be altered (not by web pages though, but still can be altered).

Therefore we cannot speak about same origin and cross origin policies with regard to NFC content in the same way as we speak about normal web content, because we cannot speak about "origin" at all for NFC content. At best we have a "label" that is mutable by 3rd parties and which we can use in filters. Therefore any security policies based on that would be broken.

After many circles of discussions about this, NFC seems to be indeed in similar category as Geolocation. We can minimize the number of user prompts, but let's see if we can completely eliminate them, and if we cannot, then we need to come up with meaningful prompts or info banners when needed.

Luckily, since

  • we require https origins from clients, and
  • the client browsing contexts must be visible and in focus, (the device must also be unlocked and the display visible) and
  • the user must do a physical gesture in order to use NFC, both for reading or sending,

we can safely assume that the user does express permission to the identifiable and visible web page (Window connected to the active Document of the current browsing context) to use the NFC API each time it is used.

However, the user may not be aware about what kind of data is sent from the device: it can be any data the given web page can access (including revealing location directly or indirectly, eventually). Also, a malicious web page can use NFC as a transfer medium, but it is much more inconvenient than using other means, so incentive for the attack and hence the threat can be considered small. Anyway we should show non-blocking information about the page accessing NFC (and eventually specifying what source of data from the device), and the user can decide to complete the physical act of tapping of not.

When reading NFC, the threat is indeed more like revealing the user's physical proximity. This one we intended to solve with the same origin policy, so it can only happen if the user willfully navigates to a page with the same origin that can be found in the tag, in which case this can be again considered as intended by the user. However, since origins written on tags may be broken, we cannot safely do this. Therefore we should be able to notify the user in a non-blocking manner that the web page in focus may (in corner cases, since the tag needs to be connected with the active page) indicate the location of the user when reading the tag, so that the user can decide whether to continue or not with the physical gesture of tapping. I agree it is hard to formulate this well, so any suggestions are welcome. However, it is not the job of the spec to do this formulation: the question is whether is this policy good enough.

At the moment these are the most critical vectors that I can see, based on previous discussion.
@ngparker , could you please review and check the validity of the above?

If they hold true, we can simplify both the API and its usage.

And the conclusion is the same that @sicking suggested here a week ago, but unfortunately we got into the same-origin discussion:

So in summary, I think the spec should:

  • Explain the privacy aspect.
  • Not require that implementations prompt the user.
  • Suggest that some form of unobtrusive notification might be wanted if the implementation wants.
  • Explain that this notification would apply equally to all of reading/writing/p2p

But I repeat, we cannot safely implement any ACL's in tags, nor any security policies based on web origins written in the tags. We can call them labels and filters, though, and keep them as convenience, if we want, in this or later versions of the spec - I suggest the latter in order to keep things simpler for the start.

Since it seems that I agree with @sicking in this matter (with the remarks made above), and @kenchris and @anssiko also have expressed agreement earlier in this thread, unless @ngparker objects, we move forward with these assumptions.

zolkis added a commit to zolkis/web-nfc that referenced this issue Sep 5, 2015

Changed data representation. New security policies. Use watches inste…
…ad events. Fixed terminology related issues. Renamed send() to pushMessage(). Add timeout to push options. Issues addressed: w3c#2, w3c#3, w3c#22, w3c#26, w3c#28, w3c#30, w3c#31, w3c#32, w3c#33, w3c#35, w3c#36, w3c#38, w3c#39, w3c#40.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment