Report a suspected vulnerability privately. Don't open a public issue — that publishes the flaw before there is a fix.
Use GitHub's private vulnerability reporting: open this repository's Security tab and choose Report a vulnerability. That opens an advisory only you and the maintainers can see. If you would rather not use GitHub, email info@codeforbreakfast.co instead.
Say enough to reproduce it: the commit you saw it at, the bd and herdr
versions in play, the config you were running under with any credentials taken
out, and what you observed. There is no SLA — this is a small project — but we
will acknowledge the report, keep you posted, and credit you in the advisory
unless you ask us not to.
Only the latest release carries fixes. Report against it or against main, and
name the version or the commit.
bdi issues reads, with two exceptions. bdi bd <project> human respond runs
that write against the named project's tracker, and bdi gates settles gh:pr
gates. Every other bd command line it spells is a read, and the pane tail it draws is output it was handed rather
than a shell it runs. That is a property of those command lines rather than a
guarantee about your tracker —
a bd older than 1.3.0 writes on its own account when it opens one, rewriting
.beads/.local_version and migrating the schema before it runs whatever it was
asked for, even under --readonly. docs/configuration.md has that, and it is not a
vulnerability.
The places worth pointing a report at are where the reading stops being the whole story.
It runs commands its config names. environment_command and
credential_command are run per project, and a directory holding an .envrc is
entered with direnv exec .. The config file is as trusted as the account that
can write it. What would be a vulnerability is a way to reach any of those
commands from something that is not the config — a tracker's contents, a
pane's output, the change socket.
It handles a tracker password. A credential_command's output is captured
rather than put on a command line, so it stays out of ps. Anywhere it reaches a
process argument, an environment a child did not need, the screen, or --json is
worth a report.
It takes connections on a socket. $XDG_RUNTIME_DIR/beady-eye/changes.sock is created
mode 0600 under the user's own runtime directory, and its whole protocol is one
project name per line. Anything that lets a line do more than schedule a read of
a project the config already names belongs here.
It passes one write through. bdi bd runs bd human respond against the
tracker of the project it names, with that project's credential. A command line
that gets it to run anything else, or to reach another project's tracker, is
worth a report.
It settles pull-request gates. bdi gates runs gh pr view on the
repository and number a gh:pr gate names, as whoever gh is signed in as. On
GitHub's word that the pull request merged, it runs bd gate resolve on that
gate. On its word that the pull request closed unmerged, it runs bd comments add on each bead the gate holds back. Each runs against a configured project's
tracker, with that project's credential. A gate's repo and await id come from
the tracker, so anyone who can write to a tracker can point bdi gates at a
pull request. Anything that gets it to close a gate whose pull request did not
merge, to write to any other bead, to run any other command, or to reach a
tracker the config does not name is worth a report.
It takes GitHub's deliveries over HTTP. bdi gates --listen answers on a
network address, which may face the internet, and it is the one part of bdi
that does. It speaks plain HTTP and expects TLS to be ended in front of it. It
reads at most 1 MiB of a body before checking its signature, gives each request
ten seconds to arrive, answers at most eight at once, and keeps at most 64
signed deliveries waiting to be settled. A sender that holds it at the limit of
eight delays deliveries until the next look, which settles them anyway, so that
alone is not a vulnerability. Anything that lets a sender without the secret
take one of the 64 places is. A delivery is taken only where its
X-Hub-Signature-256 is the HMAC-SHA256 of its body under the configured
secret, compared in constant time, and only a pull_request delivery is acted
on. All it reads from one is a repository and a number, which it settles
exactly as a gate naming them would be settled:
GitHub is asked where that pull request stands, and only the gates a
configured tracker already holds for it are touched. The secret is read from a
file or the environment, and taken out of the environment before any bd or
gh starts. Anything that gets an unsigned or wrongly signed request past the
check, gets a delivery to do more than settle the pull request it names, or
gets the secret out of the process is worth a report.
It draws what other programs say. Bead titles, bead metadata and pane output
all come from outside bdi and end up on a terminal. Content that escapes the
region it is drawn in, or that reaches the terminal as control sequences rather
than as text, is in scope.
A flaw in the tracker itself belongs with beads, and one in the multiplexer with herdr.