Announcing WCGI: WebAssembly and CGI
wasmer.io
wasmer.io
Replace Wasmer with the a JVM-based app server and WASM assemblies with JVM-bytecode. The big difference is the source language doesn't matter as long as it's able to be run/replaced by WASM bytecode.
We're heading in circles in a lot of ways
* Completely tied to an ecosystem, and incompatible with another (you could not run C programs in the JVM)
* Proprietary (vs based on an open standard)
* They couldn't run in the browser seamlessly
That said, GWT was ahead of its time in a lot of ways, but it had warts galore.
I actually enjoyed using them to get around a few browser limitations around the mid-to-late 00s, and they seemed feature/performance competitive with Flash unless what you were doing fit the media authoring model closely. But by then people were skeptical about Java and if you had to do anything to get it installed they wouldn't, and the direction was native web.
That web application is still in use, in production, today.
In a few cases there were JVM exploits that weren't based on that approach, almost always involving reflection or JIT compiler bugs.
The people saying WASM is easier to sandbox than the JVM are sort of half right and half wrong. The hard part of sandboxing is exposing safe APIs to the sandboxed code. WASM solves that by simply not exposing any APIs at all. This essentially punts the sandbox construction to the user and will allow WASM vendors to claim a good security track record, which they will get by not doing very much.
On the other hand, the OpenJDK guys are retreating from providing any sandbox at all and are taking it out of new Java versions. So you'll end up with mandatory exposed APIs that don't even try to be safe.
Neither approach is really all that great if what you want is the ability to run a useful set of normal-ish programs in a safe way. GraalVM has its own sandboxing features which look like a decent compromise, and you can still use process or VM sandboxing on top.
> It’s designed from the ground up to have an extremely simplistic model of execution that prevents common exploits like buffer overflows and such.
So is the JVM and CLR and dozens of prior runtimes for that matter.
WASM for guests is mostly a security regression as all the design focus was on protecting the host. Things in the runtime got thrown under the security bus (such as no ASLR)
> The JVM is not architected the same way, the VM has a bunch of APIs exposed to it and you have to attempt to constrain those down to make a program secure.
You're confusing concepts here. The JVM bytecode runtime has very few APIs and WASM has no inherent requirement on being minimal or capability-based. WASI, which is what's being used here, has neither of those design attributes, for example. It's just regular POSIX apis. No permission system + massive API surface, yet still WASM all the same
#include <stdio.h>
#include <stdlib.h>
int main() {
char *s = "world";
s[0] = 'o';
s[1] = 'w';
s[2] = 'n';
s[3] = 'e';
s[4] = 'd';
printf("Hello, %s\n", s);
}The point of Wasm is - programs can and will malfunction (and some will be malicious), so we have to protect the environment that runs it.
That was definitely not my experience at that time using a linux desktop.
Everything _else_ was able to do this just fine, in particular it's main competition, Adobe flash. That was actually _almost_ a first class experience and I didn't need to track down and install "icedtea" to make it all work. It just worked out of the box.
The JVM promised "write once, run anywhere." You can blame me for that failure, if you like, but it was then and always was a flat lie. You simply choose to ignore this.
Tuning the garbage collector often helps, modern Java has excellent GC options that will make most software just run better. That's often not an option when you're stuck with JRE 8 because of the curse of legacy code, but modern JREs have made significant progress in both memory management and general performance optimizations.
Port the same abstractions to any language and you'll get very similar performance issues. I've seen plenty of NodeJS applications crash because they grew out of the 2GiB memory limit I set up, and those node processes weren't doing anything that I deemed worth more than half a gigabyte of RAM either.
The JVM is somewhat aggressive in claiming RAM as memory usage grows, but that often leads to a performance increase in the comparisons I've done. Setting parameters (-xmx / -xms) can often reduce the amount of memory used significantly at the cost of slower application startups.
Not entirely true, but of course there has never been any official support. http://nestedvm.ibex.org/
You can compile c to wasm and run that.
In the same way one could compile c to java byte code, write a wrapper program to allocate the "heap", disable the gc and execute it in close to the same way it executes in a wasm runtime.
I can't even come up with a metaphor for it. We're choosing to be stuck with shitty antiquated technology because it's easier than making something better. It's depressing. Like a world that never got past the horse and buggy. Large engines powered by steam would require additional investment in refining of steel and making giant cast or forged parts... easier to just stick with the horse.
[1] https://www.youtube.com/watch?v=zlQEQQSqZ9g -> it's an old dream that others have had before.
So, that means that the remake of an OS that we call a browser is likely to be the pinnacle of computing for our lifetimes.
Hopefully after the Great Reboot of 2038, the next generation will learn from our computing mistakes, but since we've never learned from those that came before us, it's highly unlikely. But at least they will have to start from scratch, so there's a chance!
At lunch one day a colleague explained that the size of the space shuttle could be linked to the width of two horses walking on a Roman road :-)
One of my favorite lunch breaks of all time.
I'd be very leery of trusting the specifics too much. E.g. the reference to "Roman war chariots", which are not a thing the Romans ever used.
Snopes entry: https://www.snopes.com/fact-check/railroad-gauge-chariots/
God, I had forgotten about those email FWDs. The old people I know totally abandoned email.
It can be run outside a browser, and is much more performant than using the whole browser. The future is very likely going to consolidate around WASM and WebGPU, regardless of what hardware you're targeting. If you want more performant specs, it will be driven through a public and consensus driven way... there are far too many economies of scale to standardization for it not to be.
The days of building an ecosystem around a closed, proprietary language/protocol/spec are over. The browser was just the first to bridge the gap... now we move on to WASM, and maybe 10 years from now something newer
Largest /s imaginable.
Your comment is pretty far into LARPing territory.
The innovation of "docker containers" as a total solution is more akin to a POSIX standard than the Go language. Containers only became popular because of Docker, not because of containers themselves. Docker is a solution to a dozen different problems. "A container" is really just a chroot in a unique namespace. Again, that's basically just one problem solved. The functional combination of all the features of container orchestration software and interoperability is where the actual value of containers lies. Not in the container, but in the 12 different problems that are now all solved in a universal way by all the different solutions that deal with containers in the same way.
If WASM can evolve an entire ecosystem and standard around all the problems needed to be solved to run software easier, then sure, it could be revolutionary. We'll see if that happens in a way that is easy to use. My bet is it won't happen.
You seem confused… fewer and fewer people are writing software in OS locked apis/contexts. Back in the day it was much closer to 100%
Software development always goes in cycles. "Apps" were great now maybe not so much so...
In the late 80s/early 90s, the CEO of ETA Systems (a supercomputer company) had a vision that by 2000, the world would be split between supercomputers and workstations. I have seen some evidence that people are considerng that once again... The Circle of Dumb is always with us in software land.
Comparing WASM and JVM is like comparing a truck and a bus because they are relatively the same size, move at the same speed etc.
I mean sure you can load people in trucks and cargo into buses - and both have been done with JVM (eg. people built C compilers) and WASM (people are building GCed runtimes on top of it despite lack of GC support from platform).
Almost 30 years later nobody sane is running C on JVM and there were many attempts posted here over the years.
Similarly, many managed compiled languages don't depend on C.
Finally, cybersecurity legislation will speed those efforts.
All angel companies that do no evil.
You mean in a OCI image, a bit like this? - https://docs.docker.com/desktop/wasm/
and then deployed using Kubernetes? - a bit like this - https://learn.microsoft.com/en-us/azure/aks/use-wasi-node-po...
No wonder they are ditching it in favor of OCI...
"Picture running Wordpress and not having to worry about attackers breaking into your system"
uh, so, you sprinkled some WASM magic on some code and suddenly several decades worth of security research is obsolete? .....yeah, I'm gonna call bullshit. Compiling code or "running in a sandbox" does not stop attackers from breaking into your system. Might slow them down for a few months while they develop some new attacks.
I think the point is that a simple-enough application can be delievered as WASM and run entirely in the user's browser, so there wouldn't be any server-side system to break into? So one could ship e.g. wordpress + db + content in one bundle, and the user would be none the wiser. A wild claim, and probably self-defeating for anyone who needs to protect their content.
Otherwise, the WASM-dust at best moves the security boundry to a different service.
https://make.wordpress.org/core/2022/09/23/client-side-webas...
(By my colleague Adam!)
I think this experiment becomes interesting thinking about times you really want WordPress to be headless (like demoing a plug-in or theme), but less for serving websites to people. Potentially also useful as a testing development environment.
I was surprised at how fast it is, since it basically becomes an SPA.
On the one hand, you lose ASLR and other security features designed for native code. On the other hand, your program becomes immune to stack smashing, so arbitrary code execution becomes a lot harder for an attacker (at least that's my understanding).
#include <stdio.h>
#include <string.h>
int bad(char* src) {
int admin = 0;
char buf[2];
strcpy(buf, src);
printf("%d\n", admin);
return admin;
}
int main() {
if (bad("ADMIN!!!")) {
printf("we're admin!\n");
} else {
printf("we are not admin\n");
}
}At any rate, the example you give is arguably a better case than what we have right now with JS — anyone interested in subverting client side access policies can poke around trivially in the JS globals, they don’t even need to decompile anything, they have a DOM inspector and a REPL to make exploits that much easier to pull off. If security through obscurity is your thing, compiling to WASM could only help.
Again, though, client side shenanigans shouldn’t be of any concern anyway.
Edit: I thought I was replying to the other comment you made within the context of client side execution, but I can touch on that too.
Programming errors (and resulting exploits) aren’t something unique to WASM, and there’s nothing stopping you from using something like Go or Haskell or Rust as a source language, if you want something more safe than C.
And of course WASM won't protect from just regular ol logic bugs like SQL injection or similar.
Compiling things to WASM to make them "more secure" seems bonkers backwards. WASM's priorities are to protect the host, not the guest.
- Broken Access Control
- Cryptographic Failures
- Injection
- Insecure Design
- Security Misconfiguration
- Vulnerable and Outdated Components
- Identification and Authentication Failures
- Software and Data Integrity Failures
- Security Logging and Monitoring Failures
- Server-Side Request Forgery
If a modern hacker wants to exploit a web app, their first thought isn't shellcode.I'm not a fan on the way these features are being tacked back onto the runtime, but the approach of having to opt into them make the security boundary a lot more transparent. By disabling the file system (i.e. baking a fake one into memory) you can prevent whole classes of attacks. You won't get surprised by your logging library making network calls (log4j) if your sandbox never even enabled networking in the first place.
I'd much rather see easy and safe alternatives (like using containerization APIs) but there's still no easy way to tell your computer "run this program with a maximum amount of memory, CPU time, no network access and no file system outside this directory" that doesn't come with tons of caveats for preventing escape. For PHP, setting up a secure systemd configuration (more secure than the one that comes with your package manager) can be done, but it's still far from easy.
Correct - PHP is a scripting language with managed memory, quite different from C. Probably not all, but most WordPress vulnerabilities have to do with issues like sql injection, bad configuration defaults, etc, all in business logic. All of these will continue to exist when compiled to Wasm.
Assuming you actually have access to a database in the first place, while wasmer may have some vendor locked in solutions for it, generally with Wasm you won't get beyond SQLite for the near term.
> 1. Wrap the PHP interpreter with a layer that instruments each HTTP call
> 2. Use the existing php-cgi program and simply compile it to Wasm
> Option 2 is not only faster, but it also enables any web application on Wasmer more efficiently.
I’m confused. This seems to be suggesting that php-cgi, which has to initialise the PHP environment every time, would be faster than the likes of php-fpm, which, well, I understand and presume it has significantly less overhead per request, though I’ve never benchmarked it.
I have PHP 5.6 installed on my VPS for one old site, and it takes around 27ms to start¹ (compared to under 30μs for just plain `echo`, as a closer indicator of actual process spawn overhead). PHP 8.2 might be faster, but it’s still going to be much slower than `echo`.
By simply compiling php-cgi to WASM, it will surely be doing all that initialisation for every request. Because CGI starts everything from scratch for each request, it’s inherently less efficient. In theory you could coordinate a time to snapshot the process/VM/whatever, forking from that point, but that’s not CGI any more.
All up, what they’re claiming is so completely contrary to what I would expect (and without any explanation or justification whatsoever), and kinda follows the “dust off something old to laugh at it again” trope, that I’m honestly having to check that it’s not the first of April any more (the article is dated the 6th).
So as I say, I’m confused. Option 2 seems very clearly slower and much less efficient, by the very nature of CGI. No one targets CGI (it’s been basically dead for… I dunno, close to twenty years?), because CGI is considerably worse than the alternatives. Can someone enlighten me? Have I missed or misunderstood something?
—⁂—
¹ Measured by running this in zsh and reading the “total” figure (across sixteen runs, I got between 2.671 and 3.032 seconds):
time ( for i in {0..100}; do php56 <<<'<?="."?>'; done )
The comparative echo test uses `echo -n .` and takes one thousandth as long.`fn handler(request: Request) -> Response `
My understanding is the main function is called only once, and registers that handler. So `main` is where you'd initialize the majority of the environment, and no that is not truly CGI; definitely no process is being created for each request, but it may be the case that this is more like FastCGI where you have a pool of single-threaded runtimes all setup that way that can handle requests.
This still seems inefficient compared to a threaded or event polling process that can handle multiple requests concurrently without having to marshall data back and forth, but I'd think it can get closer to that than FastCGI or Lambda do.
To check my understanding: since CGI just takes a raw request over stdin and returns a response over stdout, would a WCGI wasm module be compatible with WAGI[1] and vice-versa?
Things might evolve a bit different on the mid term, but let's see what the future holds :)
I don't use CGI but when I do I like the simplicity of Haserl (Basic template language + any interpreter, lua by default) : https://haserl.sourceforge.net/
That would make sense, anyhoo. CGI is plain text which I don't think is optimal for this stuff.
At the top of the article it says “…compiling them to WASI”, but is that a semantically/technically correct statement? My understanding would be more that it should say something like “compiling them to WASI-compliant WASM” or something. Or can you actually “compile to WASI”
Like when you say "HTTP API" you don't necessarily need to change it to "TCP HTTP API" as it's somewhat implied (although maybe a shitty example, as HTTP is starting to appear over more things than just TCP as of late)
* If you want it to be usable, you will need to ship it with some mechanism that allows running CGI over http (kind of Apache or Nginx), so your container would be bigger than the Wasmer package
* Regarding security: Docker containers needs to rely on hardware virtualization to run securely (via KVM or simlar), aside of a virtualization on the systemcall layer (which depends on the crun layer that you use)
Because of that, Docker containers will have the downside of: being able to run only in one chipset/OS, they will be bigger-sized and they would be slower to start up (even if you use state of the art for running them, aka Firecracker, you still get 250ms vs < 1ms with Wasmer)
Is it possible to spin-up a 'container' or whatever youre calling the VM of a site, for each individual user? So if you have a high security req on data accessible by computers, you spin up an individual container of said site that only serves that user, and is destroyed on exit... so that whatever the user does cannot affect others?
ELI5?
Is wasmer stable and secure enough to be exposed to abuse of the entire Internet?
> your container would be bigger than the Wasmer package
The first Google hit for "docker php nginx" is https://hub.docker.com/r/trafex/php-nginx - they claim their Docker image is 40 MB compressed, whereas Wasmer for amd64 (latest from https://github.com/wasmerio/wasmer/releases) is a 80 MB tar.gz (unpacks to 300 MB tar). Even with larger images, like the `wordpress` image (200 MB), the size is neglible.
> Because of that, Docker containers will have the downside of: being able to run only in one chipset/OS
You probably don’t need to care about architectures other than amd64 and arm64. Both are supported by the trafex/php-nginx and wordpress Docker images.
> (even if you use state of the art for running them, aka Firecracker, you still get 250ms vs < 1ms with Wasmer)
Starting a fresh VM for every request doesn’t make sense, so this difference wouldn’t matter in real life.
Wasmer ships everything by default, including 3 compilers (LLVM is the big one!), which adds most of the size. However, the wasmer runtime in headless mode weights only about 2 megabytes.
Even more, even if you include only one compiler instead of 3 (just singlepass) it would be in the order of 5-10Mb.
Stay tuned, because if you are in macOS/iOS you will see even smaller binary sizes!
Where-as launching a cgi-bin executable- even a very small libcgi based one-has a significant cost, requires a lot of kernel work & context switching.
With WCGI making new "processes" is nearly free & you don't have to context switch.
A lot of the excitement around wasm in general is that it could potentially enable a communicating-processes model of computing that would be inefficient today. Even current "function as a service" paradigms tend to retain processes, have warm/cold start distinctions. With wasm there is a potential to have requests spawn not just their sandbox, but to create whole graphs of lightweight sandbox/processes. Sometimes you might hear this described as a "Nano-functions" architecture.
This is faster than forking a process because there are fewer operating system resources to manage.
CGI starts a new process rather than forking an existing one which makes it unsuitable for use with languages such as Python or JS which have slow initialisation times (milliseconds.) Wizer is able to snapshot a WebAssembly module to avoid that work. So in combination with the fast startup that brings initialisation down to microseconds.
Now runtimes are still somewhat slower on WebAssembly than native, and much slower for JITed languages since the JIT cannot run in WebAssembly. But there are many cases where startup time dominates and this will be faster overall for cases where you need per request isolation.
Disclosure: I'm the creator
This project is different in that it builds PHP to WASI.
The idea of exposing Python via a normal cgi script is terrifying to me