Webhook or access token: what to give a tool that reads your repo

PeerPost6 min read

Two keys lying on a scratched workbench in hard light, one cut and one uncut, beside an open padlock.

Somewhere in the setup flow of every tool that touches your code, there is a screen that asks for access. It usually offers two or three ways to grant it, describes them in one line each, and pre-selects the one that is easiest for the vendor.

These options are not variations on a theme. They differ in what the tool can see, what it holds while it is not looking, and what an attacker gets if the vendor has a bad quarter. It is worth ten minutes to understand the difference once, because you will make this decision repeatedly for the rest of your career.

The three shapes of the ask

Public read. The repository is already public. The tool reads what any stranger can read. No credential exists, so there is nothing to leak, nothing to revoke, and nothing to rotate. This is not a security posture so much as the absence of a decision, and it is the correct choice whenever it applies.

A webhook. You configure your host to send events to a URL. The direction of travel is the whole point: your side pushes, their side receives. The receiving service holds no credential of yours. It cannot decide to look at something. It cannot read your history. It sees exactly the events you configured, when they happen, and nothing else - and if you stop wanting that, you delete the hook.

An access token. You mint a credential and hand it over. The tool can now call your host's API as you, within whatever scope you set, whenever it likes, until the token expires or you revoke it. This is a standing capability, not a stream of notifications, and that is a genuinely different thing to give away.

The asymmetry people miss

The framing that clarifies it: a webhook is a notification, a token is a capability.

A notification tells you something happened. A capability lets the holder go and find out.

That difference shows up most sharply in history. A webhook that started sending events today knows nothing about last year. A read token scoped to the same repository can read the entire history the moment it is issued - including whatever was committed before anyone was careful, which for most repositories is a real category.

It also shows up in what breach means. If a service holding a webhook endpoint is compromised, the attacker learns which commits you pushed. If a service holding your read token is compromised, the attacker has your read token, and can use it against your host directly until somebody notices and revokes it.

Neither outcome is good. They are not the same size.

Two panels. Webhook: your repository sends the events you configured one way to the tool, which holds nothing. Access token: a two-way arrow labelled full history, on request, and the tool holds your key.

When a token is the right answer anyway

None of this means tokens are a mistake. Plenty of legitimate work requires one:

  • The tool needs history, not just what changed today.
  • The repository is private and you are not willing to configure a hook on every repository you own.
  • You need a backfill of anything that happened before the integration existed.
  • The host's webhooks do not carry the data the job actually needs.

When you do issue one, the details are not busywork:

Prefer fine-grained over classic. A classic token is an all-repositories key that happens to be pointed at one. A fine-grained token names the repository and the permission, which means a leak has a bounded blast radius.

Read-only, and check that it means it. Contents read is not the same permission as anything that can open a pull request or write a comment. A marketing tool has no business holding either.

Set an expiry. A credential that expires is a credential that eventually stops being a liability without anyone remembering to do anything. Tokens with no expiry outlive the integrations they were made for, sometimes by years.

Know where the revoke button is before you need it. If revoking access to this one tool means breaking three others, the token is too broad.

The decision is per repository, not per company

The useful mental model is that this is not one choice about one vendor. It is a choice about each repository, made on that repository's own facts.

An open-source web client is public: there is nothing to protect and no credential to issue. The private backend where the interesting logic lives might be worth the small annoyance of configuring a webhook, precisely because a webhook cannot read it. A mobile client that needs a historical backfill might genuinely warrant a scoped, expiring read token.

Three repositories, three different answers, all correct. Any tool that forces one answer across all of them has made your security decision for you, for its own convenience.

What we do, since it is the obvious question

PeerPost reads what you shipped in order to write about it, so it lands squarely in this territory and should be held to the standard above.

It supports all three modes, chosen per repository rather than per account. A public repository needs no credential at all. A webhook holds none either - it receives what you configured it to send, and it cannot read your source even in principle. A read token is available when you want the convenience, scoped to the one branch you name, revocable in a click.

Two details fall out of the design and are worth stating. The engine that writes the post receives a flat stream of changes and is never told which repository each one came from, so an internal repository name cannot end up in a public post. And nothing publishes without you approving it, which matters here because the failure mode of a code-reading marketing tool is not just what it reads, it is what it says about what it read.

If that is the shape of tool you want pointed at your work, request an invite.

Questions.

Is a webhook safer than a personal access token?

For a tool that only needs to know what changed, yes, and the reason is structural rather than a matter of trust. A webhook holds no credential of yours: your host pushes the events you configured and the receiving service has no way to ask for anything else. A token is a standing key that can be used at any time, for everything in its scope, until you revoke it.

What can a read-only token actually see?

Everything inside its scope, whenever the holder chooses to look - which for a repository-scoped read token means your full history, not just what changed today. That is not a reason to never issue one; it is the reason to scope it to the narrowest repository and branch that does the job, and to prefer fine-grained tokens with an expiry over classic ones without.

What should I check before connecting a third-party tool to my repository?

Whether it can write as well as read, what happens to your access if the vendor is breached, whether you can revoke it in one action without breaking anything else, and whether the credential expires on its own. If a tool only needs to know that you shipped, it should not be asking for the ability to read your source.

Ask for an invite.

The platform turns the commits you already push into posts, and stays quiet when you have not shipped. Private beta, by invitation.