Very neat! Unfortunately can't get the `curl` example to work no matter what I do (on Arch Linux).
$ pledge.com -p 'stdio rpath wpath cpath dpath flock tty recvfd fattr inet unix dns proc thread id exec' curl http://justine.lol/hello.txt
curl: (6) getaddrinfo() thread failed to start
I tried following the Troubleshooting section and looking through strace output, but unfortunately I'm not sure what I'm looking for, I see a few EPERMs for calls that I don't know what they do: rseq, set_robust_list, and sysinfo to name a few.
It works fine for me if Curl is built with Musl Libc. I can see you're using a very cutting edge glibc. I tried reproducing this on Debian 10. The only calls that got EPERM'd were set_robust_list() and prlimit64(). I recompiled pledge.com by adding those, and Curl is still failing for reasons that aren't obvious. I've encountered issues like this in the past. Me personally I've always solved this by keeping a healthy distance from Glibc by using things like Musl and Cosmo. However I want to see Glibc users benefitting from our work too! So I'd welcome contributions from anyone who can help us do that.
That could mean that the clone3 system call fails with EPERM instead of ENOSYS. Suppressing system call implementations with ENOSYS is generally safer because it just looks like an older kernel, while EPERM is an regular error code for some system calls.
Put differently, ENOSYS tells userspace that the system call isn't implemented and you need use some fallback code. EPERM means that the operation was denied by policy. But in that case, it might not be a good idea to approximate it by using different system calls because it might circumvent the intended security policy.