This confuses two different problems. The problem most people think of is how to sandbox a specific series of functional operations they have in mind, like opening and reading a PDF file. And then they think to themselves, what kind of API would I need to restrict a PDF viewer to just the file I'm passing.

But the problem for ubiquitously minimizing privileges across myriad tools (almost all OpenBSD command-line tools use pledge and/or unveil, now) is that the calling program can't make assumptions about the permissions and files a child program might need. So for example, a PDF viewer (or for the sake of simplicity, let's say a PDF text extractor) might need to access /bin/gunzip. The calling program can't know this ahead of time. So it has no way of reliably including those necessary files in its permitted set. But even if it did, without major refactoring it would end up w/ a union of the privileges it needs itself and of all the privileges its child processes might need, which is the opposite of what you're trying to achieve with privilege minimization. Ultimately, the only program that can truly know--and the only one that should be tasked with knowing--what privileges are needed to perform an operation is the program performing that operation.

(And note that major refactoring, such as splitting a program into a series of interoperating processes w/ discrete privileges sets, is usually not a realistic option. If it were then solutions like Capsicum would be more than adequate. Certainly new software should try to use this approach if it can.)

At the end of the day, when it comes to security you can't really save vulnerable software from itself without touching that software. Attempting to build sandboxes outside that software doesn't work well in practice. Witness SELinux, which most people disable because the rules (invariably written by people other than the authors of the programs) are too brittle and prone to breaking functionality. But neither, of course, is it practical to rearchitect all our software.

The reason why pledge and unveil and their default semantics of non-inheritance work so well is that they provide an optimal middle-ground. Each program concerns itself w/ minimizing its own privileges, and relies on programs it invokes to do the same. And w/ a good API, like pledge and unveil, in a shockingly short period of time those expectations (that a child program does know how to restrict its own permissions) can be substantially met w/ minimal effort. The typical patch to OpenBSD utilities included just several lines of code spread around various critical areas. For example, open or (if you can't open immediately) unveil any file paths passed on the command-line. Ditto for extraneous resources like /bin/gzip or /etc/magic. Then drop as many other privileges as you can as soon as you can, like network access. The appropriate way to do this is always highly dependent on the function and architecture of the program.

Of course, if you're a leaf program then, yes, you want restrictions to be inherited by default in case some bug permits uncontrolled invocation of a utility. But in most of these cases this can be solved by, e.g., blocking exec. As a framework matures, sure, extensions can be added for the niche cases where you want to toggle inheritance and/or pre-specify restrictions as the invoker of another program. But these features should not be the emphasis, and they definitely shouldn't be provided in lieu of interfaces for non-inherited restrictions.