{"id":18894184,"url":"https://github.com/trailofbits/build-wrap","last_synced_at":"2026-04-26T21:01:02.438Z","repository":{"id":227674130,"uuid":"769563180","full_name":"trailofbits/build-wrap","owner":"trailofbits","description":"Help protect against malicious build scripts","archived":false,"fork":false,"pushed_at":"2026-04-22T12:49:58.000Z","size":234,"stargazers_count":27,"open_issues_count":4,"forks_count":4,"subscribers_count":10,"default_branch":"main","last_synced_at":"2026-04-22T13:25:45.757Z","etag":null,"topics":["build-scripts","rust","sandboxing"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/build-wrap","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trailofbits.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-03-09T12:38:21.000Z","updated_at":"2026-04-22T11:25:43.000Z","dependencies_parsed_at":"2026-04-26T21:00:31.180Z","dependency_job_id":null,"html_url":"https://github.com/trailofbits/build-wrap","commit_stats":null,"previous_names":["trailofbits/build-wrap"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/trailofbits/build-wrap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fbuild-wrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fbuild-wrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fbuild-wrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fbuild-wrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trailofbits","download_url":"https://codeload.github.com/trailofbits/build-wrap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fbuild-wrap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32312505,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T19:15:34.056Z","status":"ssl_error","status_checked_at":"2026-04-26T19:15:15.467Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-scripts","rust","sandboxing"],"created_at":"2024-11-08T08:19:41.610Z","updated_at":"2026-04-26T21:01:02.429Z","avatar_url":"https://github.com/trailofbits.png","language":"Rust","funding_links":[],"categories":["Build techniques"],"sub_categories":["Supply chain beyond libraries"],"readme":"# build-wrap\n\nA linker replacement to help protect against malicious build scripts\n\n`build-wrap` \"re-links\" a build script so that it is executed under another command. By default, the command is [Bubblewrap] (Linux) or [`sandbox-exec`] (macOS), though this is configurable. See [Environment variables that `build-wrap` reads] and [How `build-wrap` works] for more information.\n\n## Installation\n\nInstalling `build-wrap` requires two steps:\n\n1. Install `build-wrap` with Cargo:\n   ```sh\n   cargo install build-wrap\n   ```\n2. Create a `.cargo/config.toml` file in your home directory with the following contents:\n   ```toml\n   [target.'cfg(all())']\n   linker = \"build-wrap\"\n   ```\n\n### Ubuntu 24.04\n\nUbuntu's default AppArmor profiles [changed with version 24.04]. The changes [affect Bubblewrap], which in turn affect `build-wrap`. Thus, installing `build-wrap` on Ubuntu 24.04 requires some additional steps:\n\n```sh\nsudo apt install apparmor-profiles\nsudo cp /usr/share/apparmor/extra-profiles/bwrap-userns-restrict /etc/apparmor.d\nsudo systemctl reload apparmor\n```\n\nNote that following these additional steps, Bubblewrap still runs unprivileged. More information on AppArmor profiles can be found on [Ubuntu Server] and the [Ubuntu Community Wiki].\n\n## Environment variables that `build-wrap` reads\n\nNote that the below environment variables are read **when a build script is linked**. So, for example, changing `BUILD_WRAP_CMD` will not change the command used to execute already linked build scripts.\n\n- `BUILD_WRAP_ALLOW`: When set to a value other than `0`, `build-wrap` uses the following weakened strategy. If running a build script under `BUILD_WRAP_CMD` fails, report the failure and rerun the build script normally.\n\n  Note that to see the reported failures, you must invoke Cargo with the `-vv` ([\"very verbose\"]) flag, e.g.:\n\n  ```sh\n  BUILD_WRAP_ALLOW=1 cargo build -vv\n  ```\n\n  To disable sandboxing entirely for specific directories or packages, use [`$HOME/.config/build-wrap/config.toml`] (see below).\n\n- `BUILD_WRAP_CMD`: Command used to execute a build script. Linux default:\n  - With comments:\n\n    ```sh\n    bwrap\n      --ro-bind / /              # Allow read-only access everywhere\n      --dev-bind /dev /dev       # Allow device access\n      --bind {OUT_DIR} {OUT_DIR} # Allow write access to `OUT_DIR`\n      --bind /tmp /tmp           # Allow write access to /tmp\n      --unshare-net              # Deny network access\n      {}                         # Build script path\n    ```\n\n  - On one line (for copying-and-pasting):\n\n    ```sh\n    bwrap --ro-bind / / --dev-bind /dev /dev --bind {OUT_DIR} {OUT_DIR} --bind /tmp /tmp --unshare-net {}\n    ```\n\n  Note that `bwrap` is [Bubblewrap].\n\n  macOS default:\n\n  ```sh\n  sandbox-exec -f {BUILD_WRAP_PROFILE_PATH} {}\n  ```\n\n  See [Environment variables that `build-wrap` treats as set] regarding `BUILD_WRAP_PROFILE_PATH`.\n\n- `BUILD_WRAP_LD`: Linker to use. Default: `cc`\n\n- `BUILD_WRAP_PROFILE`: macOS only. `build-wrap` expands `BUILD_WRAP_PROFILE` [as it would `BUILD_WRAP_CMD`], and writes the results to a temporary file. `BUILD_WRAP_PROFILE_PATH` then expands to the absolute path of that temporary file. Default:\n\n  ```\n  (version 1)\n  (deny default)\n  (allow file-read*)                               ;; Allow read-only access everywhere\n  (allow file-write* (subpath \"/dev\"))             ;; Allow write access to /dev\n  (allow file-write* (subpath \"{OUT_DIR}\"))        ;; Allow write access to `OUT_DIR`\n  (allow file-write* (subpath \"{TMPDIR}\"))         ;; Allow write access to `TMPDIR`\n  (allow file-write* (subpath \"{PRIVATE_TMPDIR}\")) ;; Allow write access to `PRIVATE_TMPDIR` (see below)\n  (allow process-exec)                             ;; Allow `exec`\n  (allow process-fork)                             ;; Allow `fork`\n  (allow sysctl-read)                              ;; Allow reading kernel state\n  (deny network*)                                  ;; Deny network access\n  ```\n\n## `$HOME/.config/build-wrap/config.toml`\n\nIf a file at `$HOME/.config/build-wrap/config.toml` exists, `build-wrap` reads it to determine which directories and packages should be allowed to build without sandboxing. Like the environment variables above, this file is consulted when a build script is linked. Changing it does not affect already linked build scripts.\n\nThe file supports `[allow]` and `[ignore]` sections, which are treated as synonyms:\n\n```toml\n[allow]\ndirectories = [\"/home/user/project-a\"]\npackages = [\"aws-lc-fips-sys\"]\n\n[ignore]\ndirectories = [\"/home/user/project-b\"]\npackages = [\"svm-rs-builds\"]\n```\n\n- `directories`: A list of directory paths. If `cargo build` is run from within a listed directory (or any subdirectory), `build-wrap` will not sandbox the build scripts. A leading `~` or `~/` is expanded to the current user's home directory.\n- `packages`: A list of package names. Build scripts belonging to listed packages will not be sandboxed.\n\nBoth sections are merged, so entries from `[allow]` and `[ignore]` are combined.\n\nFor example, if you frequently build in a project that has dependencies requiring unrestricted build scripts:\n\n```sh\nmkdir -p \"$HOME/.config/build-wrap\"\ncat \u003e \"$HOME/.config/build-wrap/config.toml\" \u003c\u003c 'EOF'\n[allow]\npackages = [\"svm-rs-builds\"]\nEOF\n```\n\n## Environment variables that `build-wrap` treats as set\n\nNote that we say \"treats as set\" because these are considered only when [`BUILD_WRAP_CMD` is expanded].\n\n- `BUILD_WRAP_PROFILE_PATH`: Expands to the absolute path of a temporary file containing the expanded contents of `BUILD_WRAP_PROFILE`.\n\n- `PRIVATE_TMPDIR`: If `TMPDIR` is set to a path in `/private` (as is typical on macOS), then `PRIVATE_TMPDIR` expands to that path. This is needed for some build scripts that use [`cc-rs`], though the exact reason it is needed is still unknown.\n\n## How `BUILD_WRAP_CMD` is expanded\n\n- `{}` is replaced with the path of a renamed copy of the original build script.\n- `{VAR}` is replaced with the value of environment variable `VAR`.\n- `{{` is replaced with `{`.\n- `}}` is replaced with `}`.\n- `\\` followed by a whitespace character is replaced with that whitespace character.\n- `\\\\` is replaced with `\\`.\n\n## How `build-wrap` works\n\nWhen invoked, `build-wrap` does the following:\n\n1. Link normally using `BUILD_WRAP_LD`.\n2. Parse the arguments to determine whether the output file is a build script.\n3. If not, stop; otherwise, proceed.\n4. Let `B` be the build script's original name.\n5. Rename the build script to a fresh, unused name `B'`.\n6. At `B`, create a \"wrapped\" version of the build script whose behavior is described next.\n\nThe \"wrapped\" version of the build script does the following when invoked:\n\n1. Expand `BUILD_WRAP_CMD` in the [manner described above], with `{}` expanding to `B'`.\n2. Execute the expanded command.\n\n## Goals\n\n- Aside from configuration and dealing with an occasional warning, `build-wrap` should not require a user to adjust their normal workflow.\n\n[\"very verbose\"]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script\n[Bubblewrap]: https://github.com/containers/bubblewrap\n[Environment variables that `build-wrap` reads]: #environment-variables-that-build-wrap-reads\n[Environment variables that `build-wrap` treats as set]: #environment-variables-that-build-wrap-treats-as-set\n[How `build-wrap` works]: #how-build-wrap-works\n[Ubuntu Community Wiki]: https://help.ubuntu.com/community/AppArmor\n[Ubuntu Server]: https://documentation.ubuntu.com/server/how-to/security/apparmor/\n[`$HOME/.config/build-wrap/config.toml`]: #homeconfigbuild-wrapconfigtoml\n[`BUILD_WRAP_CMD` is expanded]: #how-build_wrap_cmd-is-expanded\n[`cc-rs`]: https://github.com/rust-lang/cc-rs\n[`sandbox-exec`]: https://keith.github.io/xcode-man-pages/sandbox-exec.1.html\n[affect Bubblewrap]: https://github.com/containers/bubblewrap/issues/505#issuecomment-2093203129\n[as it would `BUILD_WRAP_CMD`]: #how-build_wrap_cmd-is-expanded\n[changed with version 24.04]: https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces\n[manner described above]: #how-build_wrap_cmd-is-expanded\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fbuild-wrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrailofbits%2Fbuild-wrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fbuild-wrap/lists"}