Report it privately through GitHub: on the repository's Security tab, click Report a vulnerability (https://github.com/storymode7/taproot/security/advisories/new). Please do not open a public issue.
- No backend. Taproot runs no server. The CLI runs on your machine, and the extension and the web app run in your browser. No part of Taproot sends your code to a server; the browser surfaces only fetch from GitHub, with the requests listed below.
- No OAuth and no tokens. Taproot never asks for, stores or sends a
GitHub token. The extension's requests to github.com carry your
github.com session because they are same-origin requests from the GitHub
page; its
api.github.comrequests carry none. The web app makes only unauthenticated requests. - No telemetry. No analytics, no error reports and no update checks.
- Read-only toward GitHub. No part of Taproot writes to GitHub. Verdicts and notes made in a browser stay in that browser.
- It makes no network requests of its own. It runs
git,stty, your$VISUAL/$EDITORfor theokey, anddeltaorbatwhen one is installed. - It writes
.git/taproot/verdicts.jsonin your repository. In the default review,y,xandralso stage or unstage snippets in the git index;--no-apply,--staged,--refand--baseturn that off. It never changes the files in your working tree. - For
oin--baseand--stagedreviews, it can write read-only temporary copies of reviewed files. It deletes them when it exits.
apps/extension/manifest.json declares:
- one content script,
content.js, that matcheshttps://github.com/*; - no
permissionsand nohost_permissions; - one web-accessible resource,
panel/panel.html, forhttps://github.com/*; - a content security policy for its own pages:
script-src 'self' 'wasm-unsafe-eval'; object-src 'self'.
Chrome still shows "Read and change your data on github.com" when you install it, because the content script runs on github.com.
The content script acts only on the Files changed page of a pull request:
/<owner>/<repo>/pull/<n>/changes, or /<owner>/<repo>/pull/<n>/files,
which GitHub shows to signed-out visitors. On /changes it makes same-origin GET
requests to github.com, so the browser sends your github.com cookies with
them:
- the pull request page, when GitHub switched to it without a reload;
- the diff entries that the page has not loaded yet
(
/<owner>/<repo>/pull/<n>/page_data/diff_entries); - the raw source of each changed file in a supported language
(
/<owner>/<repo>/raw/<commit>/<path>). GitHub answers with a redirect toraw.githubusercontent.com, and the browser fetches the file from there without your cookies. For a private repository, the redirect URL carries a short-lived token from GitHub.
On /files it gets the pull request and its file list from
https://api.github.com/repos/<owner>/<repo>/pulls/<n> and
…/pulls/<n>/files?per_page=100&page=<k>, without credentials, then
fetches the raw sources as above.
It sends the result to the panel, an extension page in an iframe, which runs the engine. The panel and the content script accept messages only from each other's origin. Verdicts and notes go to the extension's IndexedDB.
The web app in apps/pwa/ makes only these requests, all without
credentials:
https://api.github.com/repos/<owner>/<repo>/pulls/<n>and…/pulls/<n>/files?per_page=100&page=<k>, for the pull request and its file list;https://raw.githubusercontent.com/<owner>/<repo>/<commit>/<path>, for the source of each changed file in a supported language;- its own files, from the host that serves it.
Verdicts and notes go to IndexedDB for the app's origin. When the page is not a secure context (plain HTTP from a host other than localhost or 127.0.0.1), they stay in memory only.
The Go module has no third-party dependencies (go.sum is empty). The web
code is plain JavaScript modules, with no npm packages and no build step.
These files are vendored and pinned by SHA-256:
| File | What it is | Pinned in |
|---|---|---|
vendor/core/taproot-core.wasm |
The engine, built from core/ by make core-wasm |
vendor/core/checksums.txt |
vendor/core/wasm_exec.js |
Go's WebAssembly loader, copied from the Go toolchain by make core-wasm |
vendor/core/checksums.txt |
apps/pwa/vendor/core/, apps/extension/vendor/core/ |
Copies of vendor/core/, written by scripts/sync-extension-lib.sh |
the checksums.txt in each copy |
apps/extension/vendor/highlight.min.js |
highlight.js 11.11.1 with its Go, Java, JavaScript, Python, Rust and TypeScript languages, bundled and minified | apps/extension/vendor/checksums.txt |
To check them:
(cd vendor/core && sha256sum -c checksums.txt)
(cd apps/extension/vendor && sha256sum -c checksums.txt)
sh scripts/sync-extension-lib.sh --check
make parityThe sync check confirms that the copies in both apps match vendor/core/
and shared/lib/. make parity runs the committed WASM on the fixtures in
core/testdata/parity/ and compares its output with the Go golden files.
CI runs the vendor/core checksum check, the sync check and the parity
check on every push and pull request.
Limits of these checks:
- Parity shows that the WASM gives the Go code's output on the fixtures.
It does not prove that the WASM was built from this source. If you do
not want to trust the committed file, run
make core-wasmand thensh scripts/sync-extension-lib.sh, and both web surfaces use your build. The bytes depend on your Go toolchain, so they can differ from the committed file. - The highlight.js bundle was built once with esbuild, from an entry file that is not in this repository, so it cannot be rebuilt from here. Its checksum pins the exact bytes that ship.
- Releases are built on GitHub by
.github/workflows/release.ymlwhen av*tag is pushed. It runsmake diston the tagged commit and creates a draft release, which a maintainer reviews and publishes. - The release job is the only job with write access. It uses only
GitHub-owned actions (
checkout,setup-go,attest-build-provenance) and the preinstalledghCLI. - Each release file has a build provenance signed through Sigstore. Run
gh attestation verify <file> --repo storymode7/taprootto check that the file came from this repository's release workflow and which commit it was built from. This is not a code signature: macOS and Windows do not know about it. SHA256SUMSdetects a damaged download, but it comes from the same place as the files, so on its own it does not prove who built them.- There is no reproducible-build guarantee. The bytes depend on the Go toolchain and the build settings.
go version -m taprootprints the Go version, the build settings and the commit (vcs.revision) that a binary says it was built from.- To avoid trusting a binary, build the CLI from source with
make cli.