wicg / webusb Goto Github PK
View Code? Open in Web Editor NEWConnecting hardware to the web.
Home Page: https://wicg.github.io/webusb/
License: Other
Connecting hardware to the web.
Home Page: https://wicg.github.io/webusb/
License: Other
This project must be immediately stopped, because it opens a critical security hole.
Web browser NEVER should have access to physical devices !
Subject says it all.
This would allow people to pass in ArrayBuffers if desired.
float for usbVersion; octet for deviceClass etc.; ...
If there's no intention for people to do arithmetic on these, I'd definitely suggest strings.
Floats are especially problematic since e.g. usbVersion: 3.1
actually means usbVersion: 3.10000000000000008882
.
In explainer.md, navigate to the second paragraph of the "What is it not?" section. Observe the first sentence.
Now:
Instead USB devices will be associated with a web origin and can only be connected to from a page from the same origin.
Proposed Changes:
After:
Instead, USB devices will be associated with a web origin and can only be connected to a page from the same origin.
I originally made the changes myself and was going to create a pull request, but, as I understand it, I would have to be accepted in the CG before I can contribute. Perhaps creating an issue is still beneficial.
Have you considered what happens with USB-Serial devices like FTDI and Prolific? If FTDI decided to allow access publicly, they would effectively claim ownership of any device that used their chips (or was connected by a cable containing their chips), regardless of whether it was theirs or not? Given their history of bricking counterfeit devices, that's a bit scary.
It works the other way too - many older Arduino boards would be unusable because they use FTDI chips and so have their VID and PID, and FTDI wouldn't want to risk putting another company's URL into allowed origins. It'd be really nice to have some 'advanced' way to override it, perhaps by having the option to specify which 'Public URLs' contained the descriptors for legacy devices.
Also many devices now have a USB DFU bootloader burnt into the device. I'm not saying it should be a 'single click' to enable it (that'd be a security disaster) but it'd be nice for people who knew what they were doing to be able to work around it (if only with chrome://flags/
)
I develop Espruino (an Open Source JavaScript interpreter for microcontrollers) and most users have been dependent on the Chrome Serial API via a Chrome app for years - while it works fine now, driver support is always a nightmare and there's no support on Android.
I'm using Web Bluetooth in a new product specifically because of the promise of communication directly from a website. Adding Web USB too would be amazing.
Given the driver issue, I was lazy and have my devices the PID and VID that ST used for the USB CDC examples for the microcontrollers I was using, as they provided a set of drivers that 'just worked' - obviously that would now cause my users problems (unless I can update the firmware to serve up descriptors).
Example security considerations:
Example privacy consideration:
Example mitigation:
...but then the spec needs to describe the requirements for the knowledge and consent ceremony.
Yep, that pretty much sums it up.
Should just be a sequence<USBDevice>
; no need for the wrapper thingy
https://reillyeon.github.io/webusb/#device-requirements has a bunch of MUST statements that apply to devices. If a device violates one of these, how does the UA need to respond, especially if the violation is in a field that's read lazily? Does the UA need to immediately disconnect? Does it just ignore that field?
With WebUSB, and other Such Libraries being Developed, what if we Added "Scheme" Data too the Meta Tags in the HTML Itself? Much like the Allowed Policies, that other Applications Do. Verifying, that the Site is Requesting This, This, and This. Example.
<meta headset="OculusDK2">
<meta name="controller" content="LeapMotion" version="*">
I am Testing something similar too that for Direct Interaction with the Website, towards VR-Web Compliance.
It would be nice with a quick overview of the current implementation like the Web Bluetooth API does:
https://github.com/WebBluetoothCG/web-bluetooth/blob/gh-pages/implementation-status.md
to get a quick overview, instead of having to closely follow https://code.google.com/p/chromium/issues/detail?id=492204
"that have barring on this specification" -> "that have bearing on this specification"
I am quite new to WebUSB, but it seems that it can support in what I would like to implement.
Is it possible that a PHP-based web-application would be able to read data from a pen drive?
The idea is to have an encryption key stored on a pen drive. when the web-application detects the presence of the drive it should decrypt certain data in the database and show it to the user.
However, it is a little hard to understand how one should go about this? Can you provide an example, or point me in the right direction?
When handling multiple otherwise identical USB devices, it is useful to try to keep track of which device is which. USB doesn't reliably provide this information, since the serial number is optional (and often duplicated).
If topology information is provided (it can be obfuscated if necessary), then clients can compute a reasonable heuristic based on a combination of serial number, topology, and product+vendor id.
Windows provides a heuristic with its Container ID mechanism: https://msdn.microsoft.com/en-us/library/windows/hardware/ff546243(v=vs.85).aspx
It is very important to have the option to do a local whitelist for development (at least until a well functioning online db/repo is up... could we use a file/subrepo here on github?). Otherwise, it will only be explored by arduino makers and not by larger industry with legacy devices on the market. Remember that for most existing devices out there, it's not a simple task to change the USB communication (headers) for shipped units and even units in the pipeline for some time to come.
Most W3C style specs these days have a "participation" section at the top (eg. UIEvents), consider adding one here to make it easier for people to see how to participate in the discussion,
Could we extends the filter to filter by serialNumber
value too (in requestDevice
and getDevices
)?
Use case: I want to expose in the usb.requestDevice
window only a list of devices (i.e. mass storages, smartcard readers, ...) that were previously added in the settings section of my web application.
Service Workers have something like this:
6 Security Considerations
Service workers should be implemented to be HTTPS-only. The reasons for SSL-only support include:
Better to protect end users from man-in-the-middle attacks
Do good by encouraging HTTPS adoption
Existing "playground" services (e.g. github.io) now work with HTTPS
HTTPS is coming across much more of the web quickly
Devtools can loosen the restriction for development (file://, localhost, etc.)
Thinking about #50 I got the following idea:
In the end, what you want to do is let a webapp communicate with a USB-connected device running a cooperating firmware. You might be able to achieve this by doing the following:
This requires a bit of code on the firmware side of things, but that's mostly a barebones stripped-down IP/DHCP/TCP/HTTP stack. The advantage of this would be that it is fully compatible with existing systems, since USB network drivers (hopefully) are already installed on any system and browsers are already good at talking to "network" devices.
This solution would IMO be cleaner than what is currently proposed as it does not require new client-side code and the attack surface is clearly limited on the embedded HTTP thingamabob which could conceivably be secured. There still remains a lot of potential for ownage, but I guess that's what you get for plugging the internet into your things.
If the former is just for getting an individual index of the allowed origins, I find it weird that the name is so different. Why not just GET_ALLOWED_ORIGIN or GET_ALLOWED_ORIGIN_AT
From spec ISSUE 1
"""New devices (or firmware updates) may include a list of acceptable origins that the user agent can query, similar to the CORS mechanism for HTTP requests. Device vendors may enable existing devices by registering them in an open directory which maps device IDs to acceptable origins."""
How do we make sure the list is not supplied by the attacker?
Will it be possible to use the driver from node.js?
I guess calling open on something opened might not be too bad, and it is kind of required by other methods like reset. Having to handle this with promises is ugly but doable, even with ES2017 async/await.
async function doStuff() {
try {
await open();
} catch() {
... ignore invalid state
}
try {
await reset();
...
}
}
Maybe it should be possible to query the state or have open not tread this as an error (option?)
Feedback from one of our USB subsystem maintainers:
With devices like Edison, Beaglebone, RasPI and the like, we have a full Linux machine with a USB peripheral controller inside. Given they also come with sources and sdk, anybody in the world can make these hacker platforms look like anything they want.
Say e.g. st.com wants to access their STM32 discovery boards over the web using WebUSB, so they'll look for devices which have st.com as allowed URLs and discovery boards will ship with a bootloader containing
that support. Now, the only thing they have to check that they are, indeed, talking to an stm32 discovery board, are the USB descriptors themselves.
What prevents anybody from getting an Edison and copying these descriptors to force st.com to talk to their boards?
Now, with that out of the way, how can force st.com to crash & burn by returning oddling formed packets or descriptors larger/smaller then they should be, or
returning much more data than asked and so on.
Instead of saying
A URL descriptor referenced by the response must be interpreted as an origin (as defined by [RFC6454]) and so content beyond the scheme/host/port triple must be ignored.
Wouldn't it make more sense to refer to https://tools.ietf.org/html/rfc6454#page-10
Maybe it could additionally define it in ABNF like here: https://fetch.spec.whatwg.org/#origin-header
In some cases it is OK for an interface to not have a WebIDL-defined constructor. Those are the cases when an object is meant to only be created by the UA. (In which case, it has a constructor, but one that is not callable by normal JS code.)
Are all of the objects in the spec such cases? Is there a way to design the architecture better so that there are fewer magically-created objects, and more normal-constructible-from-JS objects?
please stop
Would it be possible to include friendly names ( https://wicg.github.io/webusb/#dom-usbdevice-productname ) as part of the search/trigger filters? (could be a regex)
This would allow much better fine grained evaluation and allow different types of products/versions inside the same VID,PID combo.
The spec contains a getDevices method on USBDeviceEnumeration, but I can't see how to access a USBDeviceEnumeration. Is it supposed to be a property of navigator or something?
We have an attribute on USBInterface to get the current alternate setting. There's probably no perfect way for us to cache this information to make it available synchronously, so we should always query the device instead. Should change to an async interface:
Promise<octet> getAlternateSetting();
Some USB standards (e.g. DFU, CDC-ACM) define class-specific descriptors that are included in the set of descriptors returned with the configuration descriptor. These descriptors are not necessarily accessible via GET_DESCRIPTOR requests.
Currently, the only way to access these descriptors via WebUSB is to retrieve the configuration descriptor set and manually parse all of the descriptors, standard and class-specific alike.
One way to simplify this would be to stash non-standard descriptors into a buffer while parsing the set of descriptors. For example, LibUSB stores a copy of any unknown descriptors and associates them with the closest configuration / interface / endpoint descriptor.
This would allow the user to parse just the class-specific descriptors without needing to repeat the entire descriptor parsing process.
It makes sense for a service worker to be able to react to a device being plugged in. It also makes sense for a service worker to be able to provide driver-like functionality for a device to other origins through navigator.connect. This issue is a reminder to figure out how this should work.
I'm trying to figure out what the long-term plan for web access to exotic input devices should be. Would it make sense for WebUSB to someday be extended to support HID devices somehow? Eg. consider a USB mouse or stylus with some extra non-standard capability (eg. extra buttons, wheel, z-axis, etc.). How would a device vendor build such a device such that it still behaves just like a normal mouse/stylus while also making the additional input data available to a web app such that it can be used in concert with the standard data? Synchronization of event streams might be challenging here.
Said another way, what's the open web equivalent of the Chrome.hid API?
Any thoughts? I'm happy to brainstorm further if/when you feel the time is right.
It would be better (hear easier) in my opinion if setConfiguration
would succeed even if the active configuration is already the one we're trying to set.
For now, here's what we have to write...
device.getConfiguration()
.then(config => {
if (config.configurationValue == 1) {
return Promise.resolve();
} else {
return Promise.reject();
}
})
.catch(error => device.setConfiguration(1))
.then(() => { ... })
How about instead?
device.setConfiguration(1)
.then(() => { ... })
Currently if I try device.setConfiguration(1)
while active configuratuion configurationValue
is 1, I get a "DOMException: Unable to set device configutation" error.
And my about:device-log
page says "Failed to set configuration 1: Resource busy".
I think the NFC implementation on android could be a good source of inspiration.
http://developer.android.com/guide/topics/connectivity/nfc/nfc.html
Because you are doing something pretty similar.
The way NDEF messages are defined.
https://w3c.github.io/web-nfc/#dfn-ndef-record
Intent filter (way to integrate NFC and an application specific to a website/protocol)
< intent-filter>
< action android:name="android.nfc.action.NDEF_DISCOVERED"/>
< category android:name="android.intent.category.DEFAULT"/>
< data
android:host="nfc.nuage.ch"
android:scheme="https"/>
< /intent-filter>
The landing page and allowed-origin descriptors take up a reasonably large amount of firmware space on small devices. It would help if the spec required the host to prepend https:// to origins that do not specify a protocol. E.g., example.com
becomes https://example.com
.
What compelling applications would WebUSB make possible that are not possible now?
Subject says it all
The TAG started to discuss (briefly) the specification at our London face-to-face, as part of the request for TAG review (w3ctag/design-reviews#108).
One issue that came up is that the specification currently uses the model where the USB device vendor decides what origins can communicate with the USB device. Some people were wondering the alternative model where the decisions are made by the user rather than the device vendor, or perhaps a model that allows both mechanisms.
We're certainly not ready to say that one model or the other was better. However, it would be interesting to hear (maybe in the explainer or the spec draft?) about whether you considered a user-mediated model, and if so, what led you to make the choices that you did.
https://url.spec.whatwg.org/#concept-url-origin makes it clear that origin is a tuple of (scheme, host, port) but URL Descriptor contains only "scheme", and "url".
As URL normally contains scheme, and this is actually an origin, why not make it:
Offset Field Size Value Description
0 bLength 1 Number Size of this descriptor.
1 bDescriptorType 1 Constant WEBUSB_ORIGIN.
2 bScheme 1 Number Origin scheme prefix.
3 Host Variable String UTF-8 encoded Origin host.
4 bPort 1 Number Origin port.
Granting a capability to a non-secure origin is effectively granting it to every origin, in the presence of a network attacker. And we assume network attackers are present.
Example
ISSUE 1
What configuration is the device in after it resets?
http://wicg.github.io/webusb/#events
It has a constructor in Chromium:
https://chromium.googlesource.com/chromium/src/+/2fe96ea775a73ad5dcc05105f57be096d302baa2/third_party/WebKit/Source/modules/webusb/USBConnectionEvent.idl
But unless device
is made nullable, some tweaks are needed to ensure that it's never null, a non-optional dict with a required member:
[Constructor(DOMString type, USBConnectionEventInit eventInitDict)]
interface USBConnectionEventB : Event {
[SameObject] readonly attribute USBDevice device;
};
dictionary USBConnectionEventInit : EventInit {
required USBDevice device;
};
Interrupt and bulk transfers are joined together and just called "transfers", control and isochromous are separate in functions and result types.
Some result types carry the exact same data (USBIsochronousInTransferPacket and USBInTransferResult, for instance).
interface USBInTransferResult {
readonly attribute DataView data;
readonly attribute USBTransferStatus status;
};
interface USBOutTransferResult {
readonly attribute unsigned long bytesWritten;
readonly attribute USBTransferStatus status;
};
interface USBIsochronousInTransferPacket {
readonly attribute DataView data;
readonly attribute USBTransferStatus status;
};
interface USBIsochronousInTransferResult {
readonly attribute DataView data;
readonly attribute FrozenArray<USBIsochronousInTransferPacket> packets;
};
interface USBIsochronousOutTransferPacket {
readonly attribute unsigned long bytesWritten;
readonly attribute USBTransferStatus status;
};
interface USBIsochronousOutTransferResult {
readonly attribute FrozenArray<USBIsochronousOutTransferPacket> packets;
};
Why not simplify this:
interface USBOutTransferResult {
readonly attribute TransferType type; // "isochronous", "interrupt", "bulk", "control"
readonly attribute FrozenArray<USBOutTransferPacketResult> packets;
}
interface USBInTransferResult {
readonly attribute TransferType type; // "isochronous", "interrupt", "bulk", "control"
readonly attribute FrozenArray<USBInTransferPacketResult> packets;
};
interface USBOutTransferPacketResult {
readonly attribute unsigned long bytesWritten;
readonly attribute USBTransferStatus status;
};
interface USBInTransferPacketResult {
readonly attribute DataView data;
readonly attribute USBTransferStatus status;
};
Yes this means that you would need to do result.packets[0].bytesWritten
for instance for a bulk transfer, but I don't think that should be much of an issue. It might be possible to have a shorthand like result.packet
as well.
As the endpoint type is fixed (unless reconfigured), I also think we can safely merge transferIn(octet endpointNumber, unsigned long length);
and Promise<USBIsochronousInTransferResult> isochronousTransferIn(octet endpointNumber, sequence<unsigned long> packetLengths);
to
Promise<USBInTransferResult> transferIn(octet endpointNumber, sequence<unsigned long> packetLengths);
A sequence with size more than 1 for non-isochronous transfers makes no sense and can just result in a failed promise, with an appropriate error.
I still like having controlTransferIn separate as it is really a special endpoint, but for that reason, it make sense to rename transferIn(..)
to dataTransferIn
Feedback from one of our USB maintainers:
There's a privacy concern which, while mentioned in the spec, doesn't seem to be fully considered either. Say someone gives me an STM32 discovery board which acts as a keylogger but I don't know about it. From all I can tell st.com is in the list of allowed URLs and st.com
will happily talk to it; however the domain mrhanky-keylogger.com is also in the list of allowed URLs because whoever gave me this stm32 discovery board hacked it.
Whatever keys stm32 discovery hacked managed to log will be periodically sent over to mrhanky-keylogger.com.
Callers should be able to cancel transfers, at least with a timeout argument if not a more general solution. Two ways I could see cancellation happening:
1. Introduce a new interface for return
interface PendingTransfer {
readonly attribute Promise<ArrayBuffer> promise;
void cancel();
};
All transfer calls would return this instead of a Promise<ArrayBuffer>
. This seems undesirable to me because then usage looks like:
device.controlTransferIn(foo, bar, ...).promise.then(() => ...)
Pretty ugly.
2. Introduce a new Waiter interface that can be passed to transfer calls
interface TransferWaiter {
void cancel();
};
The pattern then looks like this:
let waiter = new TransferWaiter;
device.controlTransferIn(foo, bar, ..., waiter).then(...).catch(...);
setTimeout(function() { waiter.cancel(); }, 100);
This would address the more general cancellation concern without a need to introduce an explicit timeout argument. Still not a common pattern, but it seems reasonable to me.
Note: "waiter" may be a misnomer.
Instead, per https://www.w3.org/Bugs/Public/show_bug.cgi?id=23682, use FrozenArray<T>
for attributes, or sequence<T>
elsewhere.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.