facebook / facebook/buck2

Suggestion: SRI-hashes for content integrity APIs like `download_file`

Open
#439 8 comments 1 reaction 0 assignees View on GitHub
enhancement
Dominant language
Rust
Stars
4.4k
Forks
394
PR merge metrics
No merged PRs in 30d

Description

Consider the following parameter to the `download_file` call:

```
ctx.actions.download_file(sha1 = "deadbeef")
```

The `sha1` attribute has been superseded by attributes like `sha256`, but remains for backwards compatibility. In the future, there could be other hashes like `blake3`. But this is awkward because every single rule that wants to mention a content hash has to have every possible hash option exposed in its interface, which is a lot of plumbing for nothing.

Many tools suffer from this problem; for instance Nix had a similar design for a long time. However, recently, Subresource Integrity ("SRI") in browsers, and now more recently Nix, instead use a "self describing" hash scheme that attaches the name of the hash algorithm directly to a base64-encoded copy of the hash. So, the above example would look more like this, in a hand-wavy way:

```
ctx.actions.download_file(hash = "sha1-" + base64enc([0xde,0xad,0xbe,0xef]))
```

That is, every function that checks content integrity simply takes a generic `hash` parameter, and the name is instead embedded into the literal directly, followed by the bytes of the hash as a base64-encoded string. This means that supporting new hash algorithms is centralized completely inside the implementation of `download_file` and does not need to be reflected inside Starlark at all. The algorithm which consists of "split on `-` and decode base64 into bytes" is simple enough to not meaningfully increase the chance of errors in the implementation.

I suggest that this is implemented for all buck2-core functions that (currently) take `sha1` or `sha256` parameters. I'd like this to be used in my own Prelude, for instance.

Note that this only needs to be implemented in the core buck2 executable in a few key spots; all existing APIs that are exposed from `buck2-prelude` can be ported to use this core API without breaking any client code (assuming a base64 encoding builtin.)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.