Prim+RPC is a low-level library and keeps a narrow scope: handling RPC and providing the tools to easily integrate with other libraries. There are a few things to keep in mind when using Prim+RPC to keep your functions secure.
By default, Prim+PRC validates that messages passed to it are RPC but it does not validate what’s in that RPC. Validation is especially important if your RPC is sent over a network like an HTTP server. Prim+RPC provides several options to easily set up validation.
The first option is the most flexible: choose any validation library and use it directly in your function to overwrite arguments. Here is an example using ArkType:
The second option is to wrap your function in another library that validates arguments for you. This example using Zod may look familiar if you are coming from tRPC:
The third option is to have Prim+RPC enforce validation through preCall
and/or postCall
hooks, instead of
validating within the function. First, we must set up a preCall
hook. This example will use Valibot:
Notice that we parse arguments according to the params
property defined on the given function. Let’s add that to our
example:
Now we can be certain that not only will this function’s arguments be validated but functions added in the future will
require validation through the params
property.
By default, when Prim+RPC is used over a network, it only accepts requests over a POST request. However, you can still
make an RPC with a GET request using the special keyword "idempotent"
.
However, you should take caution when doing so. We can demonstrate with an example. This is an idempotent function:
No matter how many times that we call this function, we will always get the same result. This can be exposed over a URL (with a GET request) because simply visiting that URL won’t change the state of the server. Here’s a bad example:
If we expose this function over a URL, then visiting that URL will change the state of the server which may not be intended.
It’s also important to note that GET requests are often logged so functions that use the "idempotent"
keyword should
never have sensitive arguments passed to them. All functions where .rpc = true
will be POST requests and cannot be
accessed with a GET request. All functions where .rpc = "idempotent"
may be accessed from either a GET or POST
request.
Prim+RPC is very selective about what gets exposed from the server. Functions (and functions only) must be passed to the server, must explicitly be marked as RPC, must not be defined on another function, and cannot access built-in functions.
While this provides a lot of protection against accidental imports, you should still be cautious about what is passed to the Prim+PRC server. If Prim+RPC doesn’t need access to a function or variable then don’t pass it to the server.
Prim+RPC does not transport your RPC messages. It creates RPC messages and passes them to your server and client frameworks. Securing the transport means something different for every environment and falls outside of Prim+RPC’s scope. When sending RPC over a network for instance, you will want to use a security certificate and implement relevant security headers. These may be provided by or be options of your server framework.
Prim+RPC uses the default JSON “stringify” method to serialize RPC and the destr library to deserialize RPC by default. You may override this behavior by providing your own alternative JSON handler. However you should be aware of any possible security implications of doing so.
Particularly, consider whether the library has protection for prototype pollution or has any unpatched security vulnerabilities. If your custom JSON handler allows additional types or supports circular references, consider how this may impact your code.
Report an Issue