Marking crypto library as safe in sandbox for pengines

I’m working on my first sizable Prolog project using PEngines as a base. I’m running into a permission issues during remote procedure calls to predicates that utilize the crypto (or alternatively sha) library. I am using the library for sha_hash/3. I believe this is marked unsafe by the sandbox because it relies on system libraries.

In a module named hash, I create a predicate that utilizes crypto:

% hash.pl

:- module(hash, [consistent_hash/2]).
:- use_module(library(crypto)).
:- use_module(library(clpfd)).

% https://www.swi-prolog.org/pldoc/man?predicate=crypto_n_random_bytes/2
bytes_integer(Bs, N) :-
    foldl(pow, Bs, 0-0, N-_).

pow(B, N0-I0, N-I) :-
    B in 0..255,
    N #= N0 + B*256^I0,
    I #= I0 + 1.

consistent_hash(Data, Id) :-
    % this call is marked unsafe
    crypto:sha_hash(Data, Hash, []),
    bytes_integer(Hash, Id).

I create a PEngines application using this module and make it available over the default port. In another process, I attempt to call consistent_hash/2. I run into the following error:

server_1  | Hash for hello world: 1354612085418477232551576450202542006353716358698
server_1  | % Started server at http://localhost:3030/
client_1  | ERROR: No permission to call sandboxed `crypto:sha_hash(_10502,_10504,[])'
client_1  | Warning: Goal (directive) failed: user:(_440="hello world",pengine_rpc("http://server:3030",consistent_hash("hello world",_442),[application(server)]),format("Hash for ~w: ~d~n",[_440,_442]))

In response, I attempt to add the crypto:sha_hash/3 to the set of sandbox:safe_predicate/1.

% hash.pl

% attempt to sandbox
:- use_module(library(sandbox)).
:- multifile sandbox:safe_primitive/1.
sandbox:safe_primitive(crypto:sha_hash(_,_,_)).
server_1  | ERROR: /app/hash.pl:8:
server_1  | ERROR:    No permission to declare safe_goal `crypto:sha_hash(_13574,_13576,_13578)'

I have a working example in this repository for reproducing the issue: GitHub - acmiyaguchi/prolog-sandbox-pengines

Are my safe_primitive declarations incorrect? Is there a way to turn off sandboxing entirely for PEngines? I would love to be able to make more progress, but I’m running out of ideas.

You get this error if the predicate is not defined when it is declared safe. We demand the predicate to be defined such that we can do some elementary checks that the predicate is not obviously unsafe. Notably we do not want the user to define meta-predicates as safe as this allows calling arbitrary goals.

That said, the crypto predicates should have been declared safe. They do not access anything that may compromise the system. The sandbox system is based on whitelisting rather than blacklisting to stay on the safe side.

edit I see the real problem is that you try to define the imported predicate as safe. The sandbox only accepts defining the real definition as safe. Pushed a patch that defines sha_hash/3, hmac_sha/4 and hash_atom/2 as safe. Note that there is also library(crypto) from the SSL package that provides many more crypt functions that are declared as sandbox safe.

2 Likes

For those wanting to see the details of the patch.

1 Like

This explains a lot about the behavior I was seeing. Thank you for the quick response and patches to the module to add sha_hash/3 to the sandbox!