Safeguard
Security Guides•

How do I find webhooks sending our repo events to outside services?

List repository webhooks with the GitHub API, read the destination URL and events, and check the audit log for who added them. A shadow integration search.

Safeguard Security Team
4 min read

List the webhooks on each repository through the GitHub REST API, read the destination URL, events and active flag for each, and match the hosts against services you have approved. Then use the audit log to see who created the hook and when. Unknown hosts are your shadow integrations.

Why webhooks are a quiet shadow IT channel

A webhook sends events from a repository to a URL. Push events, pull request events and others can flow to a service that nobody in security has reviewed. They are easy to add, they do not show up in a package manifest, and they keep running after the person who made them moves on.

Hosted tools often receive your code activity this way, which is why webhooks belong in an inventory.

Step 1: list the hooks

GitHub's REST API documents an endpoint to list a repository's webhooks: GET /repos/OWNER/REPO/hooks. Each result includes whether the hook is active, the list of events, and a config object with the destination URL, content type and an insecure SSL flag. It also returns the last response status, which may be null if there have been no deliveries within 30 days.

With the GitHub CLI, a loop over your repos looks like this:

gh repo list YOUR_ORG --limit 1000 --json name -q '.[].name' | while read r; do
  gh api "repos/YOUR_ORG/$r/hooks" --jq '.[] | [env.r, .config.url, (.events|join(",")), .active] | @tsv' 2>/dev/null
done

Check the current API documentation for required token permissions before running it, because access to hook data is restricted. The documentation notes that OAuth app tokens and classic personal access tokens need the read:repo_hook or repo scope for the config endpoints.

Step 2: classify the destinations

Group by destination host and sort by count. Then label each host:

LabelMeaningAction
ApprovedOn your integration listRecord the owner
InternalYour own serviceCheck it is still running
UnknownNobody recognizes itFind the creator
StaleLast response is an error or nullCandidate for removal

Look closely at hooks with the insecure SSL flag set, and at hooks that send every event type to a destination that needs only one.

Step 3: find who added them

The organization audit log records webhook activity under the hook category, plus app installation and OAuth events. Only organization owners can open it. Events are kept for 180 days and the default view shows three months, so set a date range. You search with qualifiers such as actor, action, repo and created. If a hook is older than the retention window, you will not find its creator there, so ask the repo's owners directly.

Step 4: decide and clean up

For each unknown hook, ask the repository owner what it does. If the answer is "I do not know", disable it first and watch for complaints for a week before deleting. Record each approved hook with its owner and purpose, so the next sweep is shorter.

Also check secrets: the config can hold a secret used to sign deliveries. Rotate it when you take over a hook.

Make it routine

Run the listing monthly and diff it against last month. New destinations are the interesting lines. For apps that arrive by OAuth, see how to see which OAuth apps can reach your GitHub org.

Quick check

Do organization level webhooks exist too?

Possibly. The page we reviewed documents only the repository endpoint, so check GitHub's current documentation for organization level hooks before you assume coverage.

Is deleting an unknown hook safe?

Disable it first. Some hooks drive a deploy or a notification someone relies on. A week of watching costs little.

Safeguard offers asset discovery and compliance evidence automation that can keep an integration list with owners. You can also run a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.