Stream: git-wasmtime

Topic: wasmtime / issue #13293 FIPS Support


view this post on Zulip Wasmtime GitHub notifications bot (May 05 2026 at 21:54):

markmsmith opened issue #13293:

Feature

I'd like to be able to run a build of Wasmtime that has wasi-http configured to run in FIPS mode. This would mean that all https requests and responses would use a NIST-certified crypto module.
This could just be a separate build of Wasmtime and wouldn't need to be dynamic per-request or per-VM.

Benefit

If I want to run Wasmtime in a US Gov "FedRAMP Moderate" or higher environment, I need to be able to show auditors that any encryption-in-transit is done with a crypto module that's been NIST-certified as FIPS-140-2 or FIPS-140-3 compliant. As an example, the Golang 1.24+ crypto module 1.0.0 was just validated last week, so any golang programs built with the appropriate flags are guaranteed to use the appropriate crypto implementation. Ideally Wasmtime could support something similar for its WASI implementations.

Implementation

It looks like wasi-http depends on rustls:
https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi-http/Cargo.toml#L43

I'm not a rust expert, but I believe Rustls can support support FIPS via the aws-lc-rs backend

This could potentially allow either a FIPS build of Wasmtime, or for FIPS a mode to be surfaced via config.

Here's are the NIST certificates for the various versions of the aws-lc crypto module:
https://csrc.nist.gov/projects/cryptographic-module-validation-program/validated-modules/search?SearchMode=Basic&ModuleName=aws-lc&CertificateStatus=Active&ValidationYear=0

Alternatives

  1. Have wasi-http delegate to wasi-crypto and have wasi-crypto be the one that supports FIPS at a lower-level. This would be a more generic solution, making FIPS also available to applications that are using wasi-crypto instead of just consumers of wasi-http, but that also increases the API surface area and scope of this request. My use case only require https requests and responses go through a NIST-certified crypto module, so a narrower scoped solution seemed the best incremental approach. If successful, wasi-crypto could still be considered in a future iteration, but might use aws-lc-rs directly instead of going through rustls.
  2. Allow some other way to plugin in a FIPS-140-3 compliant crypto module. If this doesn't ship as part of Wasmtime, it would make the setup of the containerd shim in SpinKube more complicated.
  3. Implement a pure-wasm implementation of the crypto and get it NIST certified. This would be an extremely lengthy and expensive process, which doesn't seem worth the effort when there are multiple performant solutions available within the ecosystem that have already been validated and certified. I admit it would be cool though.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2026 at 23:05):

markmsmith commented on issue #13293:

These rustls docs may be all that's needed to configure it for FIPS mode:
https://docs.rs/rustls/latest/rustls/manual/_06_fips/index.html

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2026 at 23:32):

alexcrichton commented on issue #13293:

From those docs it looks like Wasmtime might not need any changes at all? As an embedder of Wasmtime you could activate the crate feature and call the installation method, so would that work for your use case?

view this post on Zulip Wasmtime GitHub notifications bot (May 06 2026 at 01:36):

markmsmith commented on issue #13293:

My (possibly wrong) understanding is that Wasmtime is implementing the wasi-http entrypoint, which is doing the TLS termination for inbound http requests and the wasm component that it's running (which might be compiled from golang instead of rust) is at the mercy of whatever Wasmtime did upstream for that crypto.

view this post on Zulip Wasmtime GitHub notifications bot (May 06 2026 at 14:42):

alexcrichton commented on issue #13293:

Looking at the link you shared there are two primary steps:

  1. Activate a crate feature -- you can do this in addition to Wasmtime. There's no hard requirement that wasmtime-wasi-http is the one that activates the feature.
  2. Invoke a function from rustls independent of any TLS connection. Your embedding can also do this completely orthogonally of Wasmtime.

The one thing you can't do is assert!(client_config.fips());, however.

Additionally something else you can do is to turn off the default-send-request feature of wasmtime-wasi-http in which case you're the one responsible for linking in rustls and you have full control over all HTTP details. You could, for example, copy Wasmtime's implementation (~1 or 2 functions) and control things locally.

On one hand I think it's useful to keep Wasmtime's default implementation example-like insofar as it works but doesn't have all the bells and whistles. For example the skills needed to maintain a WebAssembly runtime are not necessarily indicative of good skills to maintain a high-quality HTTP implementation.

On the other hand if it's a useful and easy feature then it's also just that. I wanted to make sure to lay out the various options here, and notably point out that using FIPS-certified cryptography I believe is not blocked on work in upstream Wasmtime, it's just one particular approach is blocked on upstream work (if you decide that's the best route)

view this post on Zulip Wasmtime GitHub notifications bot (May 06 2026 at 20:44):

markmsmith commented on issue #13293:

In my use case I'm not embedding Wasmtime in something I compile, I'm just using the prebuilt binary with the runtime-class-manager that sets up a containerd shim to use the wasmtime runtime to run a wasm binary that was dynamically pulled by k8s.

My mental model here is that it's wasmtime's implementation of the wasi-http entrypoint (for the http/http-proxy world) that is handling TLS termination for the request, and the unwrapped http request details are then just passed to the component (which may have been compiled from golang and use the wasi p3 SDK to bind back to the runtime's implementation of that outer harness).
So it would be
http request -1-> wasm time wasi-http listener -2-> component expecting an unwrapped request
and Wasmtime would own the crypto that happens between 1 and 2, and the component wouldn't be able to influence that at all (kind of like an AWS lambda that's just receiving an http request "event" function call from the outer harness).

I'm still a learner to all this though, so it's possible that I'm wrong though, and the part doing the https/tls processing is whatever WASI SDK was used to make the component, not the wasmtime runtime, that's the part I'm not sure about.

view this post on Zulip Wasmtime GitHub notifications bot (May 06 2026 at 22:38):

alexcrichton commented on issue #13293:

Your mental model is right, yeah. The issue is that we're unlikely to turn this on by default in Wasmtime so the option needs to be somewhere. Wasmtime does not distribute a binary that you're using but instead you're using Wasmtime through a separate embedder (Spin I believe). What I'm pointing out is that something needs to turn on a Cargo feature and run some Rust code, and that can be in Wasmtime but it can additionally be external. My hunch is that what you probably want is whatever is producing the Rust binaries that is being run wants this configuration flag. I realize that you were redirected here from #spin in CNCF, but given Rustls's documented requirements I believe it's not required that this change be made in Wasmtime itself. For example even if Wasmtime were to add options here you'd still need whatever is building the final Rust binary to actually activate those options and such.

Because the final Rust binary needs to be produced no matter what, that's what makes me think that the best location for this configuration is whereve this Rust binary is being built. Are you able to identify where that is? For example is it the spin binary? The wasmtime binary? Some other binary?

view this post on Zulip Wasmtime GitHub notifications bot (May 07 2026 at 15:43):

markmsmith edited a comment on issue #13293:

In my use case I'm not embedding Wasmtime in something I compile, I'm just using the prebuilt binary with the runtime-class-manager that sets up a containerd shim to use the wasmtime runtime to run a wasm binary that was dynamically pulled by k8s.

My mental model here is that it's wasmtime's implementation of the wasi-http entrypoint (for the http/http-proxy world) that is handling TLS termination for the request, and the unwrapped http request details are then just passed to the component (which may have been compiled from golang and use the wasi p3 SDK to bind back to the runtime's implementation of that outer harness).
So it would be
http request -1-> wasm time wasi-http listener -2-> component expecting an unwrapped request
and Wasmtime would own the crypto that happens between 1 and 2, and the component wouldn't be able to influence that at all (kind of like an AWS lambda that's just receiving an http request "event" function call from the outer harness).

I'm still a learner to all this though, so it's possible that I'm wrong, and the part doing the https/tls processing is whatever WASI SDK was used to make the component, not the wasmtime runtime, that's the part I'm not sure about.

view this post on Zulip Wasmtime GitHub notifications bot (May 07 2026 at 16:00):

markmsmith commented on issue #13293:

I've done some more digging, and I think Wasmtime is being embedded within containerd-shim-spin. I was previously (incorrectly) thinking that the shim just invoked the vanilla wasmtime binary directly, but I see now that it's built in to it.

I think there would still be value in a separate build or command-line flag for Wasmtime, to let people running it standalone have it run in FIPS mode, but I agree that it's not needed from the primary use case.
Thanks for helping me better understand how the pieces fit together.
Do you think it would be valid to still keep this feature request open, but just as a lower priority?

view this post on Zulip Wasmtime GitHub notifications bot (May 07 2026 at 20:13):

fibonacci1729 commented on issue #13293:

@markmsmith That's correct -- containerd-shim-spin embeds wasmtime through spin. So what Alex proposes should work, i.e. adding a feature flag to wasmtime and spin that containerd-shim-spin activates.

view this post on Zulip Wasmtime GitHub notifications bot (May 07 2026 at 20:33):

alexcrichton commented on issue #13293:

In the case of that Cargo.toml there's probably a lot of other parts of the system, notably Spin, that you'd want to be FIPS-compliant. For example containerd-shim-spin depends on openssl and there's a number of other dependencies which probably transitively depend on openssl or rustls or such. Given that I think that I still feel that Wasmtime isn't the right place for a FIPS flag of sorts and instead containerd-shim-spin is the place to put this. It should be possible for containerd-shim-spin to configure Wasmtime appropriately by depending on rustls and activating the feature, as well as invoking the appropriate API.

@fibonacci1729 does that sound reasonable to you? Having the FIPS support live in containerd-shim-spin due to there being other deps to take care of there too?

view this post on Zulip Wasmtime GitHub notifications bot (May 08 2026 at 21:11):

markmsmith edited a comment on issue #13293:

In my use case I'm not embedding Wasmtime in something I compile, I'm just using the prebuilt binary with the runtime-class-manager that sets up a containerd shim to use the wasmtime runtime to run a wasm binary that was dynamically pulled by k8s.

My mental model here is that it's wasmtime's implementation of the wasi-http entrypoint (for the http/http-proxy world) that is handling TLS termination for the request, and the unwrapped http request details are then just passed to the component (which may have been compiled from golang and use the wasi p3 SDK to bind back to the runtime's implementation of that outer harness).
So it would be
http request -1-> wasmtime wasi-http listener -2-> component expecting an unwrapped request
and Wasmtime would own the crypto that happens between 1 and 2, and the component wouldn't be able to influence that at all (kind of like an AWS lambda that's just receiving an http request "event" function call from the outer harness).

I'm still a learner to all this though, so it's possible that I'm wrong, and the part doing the https/tls processing is whatever WASI SDK was used to make the component, not the wasmtime runtime, that's the part I'm not sure about.

view this post on Zulip Wasmtime GitHub notifications bot (May 08 2026 at 21:21):

markmsmith commented on issue #13293:

I won't disagree too hard, but one argument in favor of there being a Wasmtime-level flag (that a higher-level containerd-shim-spin could leverage for a flag of its own) is that rustls is just an implementation detail internal to Wasmtime, so relying on the embedding parent flipping that config for the transitive dependency seems like it breaks the encapsulation a bit, and introduces more coupling between Spin and Wasmtime's internals.

I agree that Spin would likely have other dependencies of its own that would also need flipped to FIPS mode to cover everything, but it seems like the natural interface for flipping it for Wasmtime as a blackbox would be a feature flag, so that Wasmtime would be free to change implementations as necessary (and potentially apply it to any other relevant WASI implementations added in the future).

view this post on Zulip Wasmtime GitHub notifications bot (May 12 2026 at 19:29):

alexcrichton commented on issue #13293:

That's definitely true yeah, and to be clear I don't think that adding a flag to Wasmtime is a bad idea, it's moreso I wanted to try to suss out if adding such a flag were the totality of what was necessary or whether there was other bits to handle as well (such as having a flag in Spin)

view this post on Zulip Wasmtime GitHub notifications bot (May 12 2026 at 22:53):

markmsmith commented on issue #13293:

Yeah, I think a flag for both makes sense.

One of the engineers on the Spin team suggested I open a matching issue over there:
https://github.com/spinframework/spin/issues/3502.
From his investigations, spin seemed to need to reimplement the http triggers when embedding wasmtime, so wasmtime implementing the flag may not be on the critical path (but could still help people test).


Last updated: Jun 01 2026 at 09:49 UTC