-
Notifications
You must be signed in to change notification settings - Fork 34
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
Security concern when importing executable modules as non-executable data #40
Comments
they should define a custom section. |
Great point! One thing to note is that, until core wasm gets single-level imports, this problem doesn't yet arise since wasm has no way to access the default exports of a module (only named exports) and JSON modules only have a default export (no named exports) (iiuc, skimming the JSON module proposal right now ;). Once wasm does get single-level imports, there is an interesting question of defaults. Since, unlike JS, wasm imports are annotated with types, we could theoretically say that, when the imported type is a value, the default assertion is non-executable and thus an executable import requires the extra opt-in. What would be nice about this is that it would allow a host-agnostic interface-typed wasm module to not have to do anything ESM-specific when all it wants is to import some raw data from the host. A hole in this reasoning is if the ESM loader one day allowed importing parts of a JSON module via named exports (the named export just projecting a field in the root object). This isn't unthinkable (afaics), so a different line in the sand we could draw (instead of default-export vs. named-export) is core type vs. interface type: we could say that an import of a pure interface-typed value had a default assertion of non-executable. This line may actually be the better one since core wasm doesn't actually have imports of values, only imports of constant-valued globals (which are a subtly-different entity). Adapter modules would actually import interface-typed values (no "global"). Either way; it seems like we have some time before a precedent gets established. |
Yes, the JSON proposal only has an "export default," for now. But even then, why wouldn't you be able to import it? I'm thinking that we would end up with something along the lines of: (import "./data.json" "default" (global $JSON externref)) ;; can be more specific, of course Unless I misunderstood this proposal, is that the syntax being suggested? So, how would it not already be possible? Now I'm honestly not sure what to think about that other proposal you had linked, I might end up suggesting that we get infinite level nesting, but that's unrelated to this. |
Web Assembly has the capabilities to import dependencies, and execute calls within the environment. These are the same capabilities that JS has. One could get into fine details that the JS module has eg global access, and that the Wasm start function doesn't have full capabilities. But I think at a base-level the user assumptions are the same that the modules are both executing and importing. Replacing a JSON module with a Wasm module is handled by the security provided by the import assertions on the JSON module. Hence it is not a security escalation swapping in JS for Wasm like it is swapping in JS for JSON. Now of course we can have import assertions for Wasm. I'm just pointing out that the same justifying security reasoning doesn't necessarily apply to Wasm. |
Well... yes, and no. It doesn't have global access by default, but it can very well be given that much power, which would make Wasm much closer to being equal to JS. WebAssembly.instantiateStreaming( fetch("..."), globalThis ); With Okay, now, back on topic:
Neither of these are security escalations at all. Swapping executable code for other executable code isn't necessarily more or less safe, and depends on the actual code being executed. The problem arises when you try to simply read data but actually evaluate code. For example, in a native binary, say, you attempt to read a file, but somehow instead you execute the file. These are very different things, that have very different results and side effects. The problem is that you are offered this new, non-deterministic, way to import pure data with the potential to execute arbitrary executable code, but a deterministic alternative that does only what you want it to, and it exists in the browser already:
Can you please elaborate more on this point in particular? It wasn't clear as to how everything else you had said specifically tied into this. |
@00ff0000red apologies I got my direction mixed up when skimming this last night :) I agree the point stands, my diatribe was more about any Wasm assertion not really being a security property, despite the assertion system being about security.
Is the suggestion here that the esm integration disallow importing the "default" export by name when interfacing with JS, such that the single-level exports can be a completely disjoint space? I wasn't aware of this - is that in the proposal here already? |
It is not (and shouldn't be). |
Maybe I'm missing a detail of ESM-integration, but I don't think any valid string can be assigned to refer to the default export since that would mask named exports that happened to have that same string. That's why we need something "out of band", like single-level imports. |
@lukewagner actually, the default export is just |
Oh whoops, sorry! (What happens with tc39/#2154/#2155?) |
@lukewagner not much, since |
So, now that that has been clarified, does this refute your earlier claim:
thus making this problem a feasible reality if/once both proposals are complete and have passed? |
@00ff0000red I suppose so. Even before interface types, in theory someone could attempt to import a JSON module via immutable |
Unless you were intentionally referring to it, that was precisely what I had suggested near the beginning, and by importing |
With regards to the original issue, I suppose the question is if data imports in Web Assembly with strictly limited execution is a useful property. Perhaps for remote data fetching such as JSON use cases while restricting execution? But I'd be concered in such a use case about the privacy implications of hard coding URLs into Wasm binaries as opposed to an imperative injection, personally. The Wasm binary being different from JS here because it naturally forms a tooling boundary between native developers and js developers. |
Closing this issue in favor of issue #42. If anyone believes that the issue doesn't properly cover the problem(s) raised in this issue, feel free to re-open it, or leave a message for me to re-open it for further discussion. |
ECMAScript proposals that directly affect ESM, thus indirectly affect this Wasm proposal for reference:
If this proposal, and both, the ECMAScript JSON and module type assertions proposal all succeed, then Wasm will deal with the same problem that ECMAScript would have with JSON/non-executable modules.
As the JSON import proposal seems very general, simply allowing parsing and importing of JSON files via URLs, coupled with the Wasm interface type proposal, Wasm could very well be capable of importing structs, arrays, and everything necessary to define the shape of an entire JSON module.
Thus, I believe, that this proposal should attempt to define a way for Wasm to do those same host import assertions, even if the ECMAScript assertion proposal were to fail, unless the ECMAScript JSON proposal doesn't become a part of the spec.
If this is pushed out to implementors and the ESM assertion proposal is accepted and implemented first, then Wasm will not be at equal footing with ECMAScript.
At a minimum, a set of bytes should be reserved or defined for this capability.
The text was updated successfully, but these errors were encountered: