Open Bug 1573034 Opened 3 years ago Updated 3 years ago

nativeMessaging returns undefined error when data exceeds a small limit on Windows

Categories

(WebExtensions :: General, defect, P3)

68 Branch
defect

Tracking

(Not tracked)

UNCONFIRMED

People

(Reporter: david, Unassigned, NeedInfo)

Details

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0

Steps to reproduce:

  1. Install the browserpass extension: https://addons.mozilla.org/en-US/firefox/addon/browserpass-ce/
  2. Install the native messaging host on Windows through WSL https://github.com/browserpass/browserpass-native#installation
  3. Add a few passwords to ensure that everything is setup correctly.
  4. Add a large number of passwords > 200 (?) and the extension will stop working.

Actual results:

The native messageing throws an undefined exception described here: https://github.com/browserpass/browserpass-extension/issues/111

In the console, I get the following error:
https://github.com/browserpass/browserpass-extension/issues/111#issuecomment-517935528

Creating a log point, reveals that an undefined error is thrown:
https://github.com/browserpass/browserpass-extension/issues/111#issuecomment-517937646

The undefined error come from chome.runtime.lastError
https://github.com/browserpass/browserpass-extension/issues/111#issuecomment-518013929

This does not happen in Chrome on Windows (using the same messaging host). I can also confirm that this does not happen on Firefox on macOS. It seems to be only a problem with Firefox on Windows. I wasn't able to test not using WSL, but since it works perfectly in Chrome (and it works perfectly if there are a limited number of passwords in Firefox) that doesn't seem to be the problem.

Expected results:

It should continue to work even with a larger amount of data as it does in Chrome on Windows or Firefox on macOS.

Summary: undefined windows native → nativeMessaging returns undefined error when data exceeds a small limit on Windows
Whiteboard: webext?
Flags: needinfo?(rob)

When you open the global browser console (Ctrl-Shift-J), do you see any errors?

Flags: needinfo?(rob) → needinfo?(david)

This is what I get after clearing the console and hitting the browserpass button on the toolbar:

sender.page is undefined MessageChannel.jsm:976
Security Error: Content at moz-extension://7e33ebcc-0484-45fd-94f4-74cb3ee4c323/ may not load data from blob:null/cc85f4c6-cf18-4506-bfad-dbe5d66652e2.
page is undefined MessageChannel.jsm:976
Loading failed for the <script> with source “blob:null/cc85f4c6-cf18-4506-bfad-dbe5d66652e2”. blank:1:1
Promise resolved after context unloaded
polyfill.js:231
<unavailable> popup.dist.js:12019:17

Let me know if there's anything else I can do to help. :)

Flags: needinfo?(david)

That doesn't contain any useful information. I originally thought that the native messaging host is sending too much data: a message should not exceed 1 MB; sendNativeMessage cannot handle larger messages, and connectNative needs to be used instead if an extension wants more data. Your extension/native app example does not appear to have a theoretical maximum on the number of exchanged bytes, so I thought that it might have caused the issue. However, the absence of error messages doesn't support this hypothesis.

Could you try to create a minimal extension to reproduce the problem?

In the linked Github issue, you're claiming that the amount of data on the filesystem is a potential trigger for the issue, with the issue occuring when more files are present. This suggests that the issue might be in the communication from the host to the extension.

First, you need to intercept the communication between the original native message host and the extension.
To do so, you could use the Debugger (at about:debugging) to debug the background page of the Browserpass extension, and call JSON.stringify(request) to generate the string that would be send to the Browserpass native app.

Copy this string and save it to a file.

Then pass this input to the native messaging host, and save the output to another file:

cat yourinput.json | path/to/browserpass-native-host.exe > output.json

Create a new native messaging host that reads the given input and sends the contents of output.json to stdout. Make sure that you're not changing the bytes (i.e. write in binary mode).

Finally, when your dummy native messaging host is ready, create an extension that calls it, via:

var input = <paste yourinput.json's content here>
chrome.runtime.sendNativeMessage("id.of.app", input, function(response) {
  console.log(chrome.runtime.lastError);
  console.log(response);
});

... and see if the issue is reproduced. If it is, try to transform the data until you have a minimal reproduction, preferably safe for sharing.

Here is an example that you can use as a template: https://github.com/mdn/webextensions-examples/tree/master/native-messaging
Documentation: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging

Flags: needinfo?(david)

(In reply to Rob Wu [:robwu] from comment #3)

Then pass this input to the native messaging host, and save the output to another file:

cat yourinput.json | path/to/browserpass-native-host.exe > output.json

So it looks like the native messaging host checks the message length
https://github.com/browserpass/browserpass-extension/issues/111#issuecomment-524558080

which is defined in the docs here:

Each message is serialized using JSON, UTF-8 encoded and is preceded with a 32-bit value containing the message length in native byte order.

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#App_side

How would I add that to the begining of the test input? Thanks!

Flags: needinfo?(david) → needinfo?(rob)

Try this Python script, which reads yourinput.json and outputs the same, with the expected size prefix:

#!/usr/bin/python
import sys
import struct

try:  # Py3
    stdout = sys.stdout.buffer
except AttributeError:  # Py2
    stdout = sys.stdout


if sys.platform == "win32":
    import os
    import msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)


def output_from_file(filepath):
    with open(filepath, "rb") as f:
        raw_message = f.read()
    # Write the data size before the data
    stdout.write(struct.pack('I', len(raw_message)))
    stdout.write(raw_message)
    stdout.flush()


if __name__ == "__main__":
    output_from_file("yourinput.json")
Flags: needinfo?(rob)

The priority flag is not set for this bug.
:jimm, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jmathies)
Flags: needinfo?(jmathies)
Priority: -- → P3

Could you share more information on reproducing? See comment 3, comment 4, comment 5.

Flags: needinfo?(david)
Whiteboard: webext?
Version: Firefox 68 → 68 Branch
You need to log in before you can comment on or make changes to this bug.