GitHub webhook IP ranges: review the Meta API change
New delivery addresses can stop at an old firewall rule. Review a live hooks snapshot, then verify the receiver still accepts the right events.
Quick answer
GitHub's 29 October 2026 announcement adds webhook delivery ranges to the Meta API's `hooks` list. Teams maintaining static allowlists should review the additions; teams already synchronizing that list should verify their synchronization succeeded. Fetch the live list when making the change, preserve existing valid ranges, and keep webhook signature verification in place.
On this page
GitHub's 29 October 2026 announcement adds webhook delivery ranges to the Meta API's hooks list. Teams maintaining static allowlists should review the additions; teams already synchronizing that list should verify their synchronization succeeded. Fetch the live list when making the change, preserve existing valid ranges, and keep webhook signature verification in place. [1][2]
What changed on 29 October?#
GitHub announced additional IP ranges for webhook deliveries on github.com, including GitHub Enterprise Cloud across its plans. The announcement identifies 9.234.98.160/28, 9.234.98.176/28 and 9.234.106.48/28. It says the additional ranges are present in the Meta API's hooks field. These are additions to review alongside existing ranges, not a complete replacement list. [1]
This is a dated adoption analysis of that announcement. It does not promise that the listed ranges will remain the complete current answer when you read it. GitHub's API documentation explicitly says its response examples are illustrative and instructs users to query the API for current values. Build the operational change from that live response. [2]
Check the configuration owner first. The immediate change concerns incoming webhook policies with a static list that misses newly valid delivery sources. A team that already refreshes the hooks list may need no configuration change for these additions, but it still needs evidence that its refresh reached the actual enforcement point. Read the synchronizer's applied snapshot and the firewall result. [1]
The announcement concerns github.com webhook delivery addresses. It is not a general authorization to open all GitHub service ranges, nor evidence about the outbound addresses of every Actions runner. A self-hosted GitHub Enterprise Server installation has its own deployment context. Keep the change's service boundary explicit in the review.
Where can a valid delivery be rejected?#
At the first network enforcement point that sees an address outside its allowlist. That may be a cloud firewall, load balancer, edge service or reverse proxy. An application log containing no request does not prove GitHub never attempted delivery. The request may have been rejected before reaching the process.
Scenario: an illustrative engineering team receives repository webhooks through an edge firewall and reverse proxy. The application checks signatures and queues accepted events. Its allowlist was copied into infrastructure configuration months earlier. After a delivery failure, the team sees no application error and starts changing webhook secrets. A new webhook secret will not get a connection through the firewall.
Trace the observed source address at each boundary. The edge may see the original connection, while the application sees the reverse proxy. A forwarded-address header is trustworthy only within a deliberately configured proxy trust boundary. Do not implement an allowlist against arbitrary caller-supplied headers and assume it provides the same protection as the network control.
Map the path before editing policy: GitHub delivery, edge admission, proxy forwarding, application signature validation, durable acceptance and background processing. For each transition, name an observable signal. This makes a failure distinguishable from a missing log and prevents the IP change from being used as a universal explanation for every delayed webhook.
The transactional outbox discussion is relevant after the receiver begins accepting work. It addresses durable handoff and retries. The agent action identity guide covers the separate problem of repeated business actions. Neither replaces network admission or signature verification.
How do you produce a reviewable candidate list?#
Fetch the live Meta API response, validate the hooks field and produce a candidate artifact before touching a firewall. GitHub documents the public Meta endpoint and its request headers. The response includes other service address groups, so select hooks deliberately rather than merging every field that happens to contain CIDRs. [2]
curl --fail --silent --show-error \
--connect-timeout 10 --max-time 30 \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2026-03-10' \
https://api.github.com/meta > meta-candidate.jsonThis read-only request does not modify a firewall or repository. Treat a failed fetch as a failed refresh. Do not interpret an empty or truncated output file as an intentional empty allowlist. Keep the last reviewed valid configuration while the source is unavailable, and alert the owner of the refresh path.
The following parser checks the response shape and normalizes the network entries. It prints a review artifact, not firewall commands. Save its output separately and let a reviewed deployment step consume it. The fixture does not assume that every GitHub feature supports every address family simply because the Meta API can return both. [2]
import ipaddress
import json
from pathlib import Path
document = json.loads(Path("meta-candidate.json").read_text())
hooks = document.get("hooks")
if not isinstance(hooks, list) or not hooks:
raise ValueError("nonempty hooks list required")
networks = set()
for value in hooks:
if not isinstance(value, str):
raise ValueError("CIDR must be text")
network = ipaddress.ip_network(value, strict=True)
if network.prefixlen == 0:
raise ValueError("unrestricted network rejected")
networks.add(network)
for network in sorted(networks,
key=lambda n: (n.version,
int(n.network_address),
n.prefixlen)):
print(network)Syntax validation establishes only that the values are networks in an acceptable format. It does not establish trust in an arbitrary file. Fetch from the documented HTTPS endpoint, retain the retrieval timestamp and source URL, and review the diff against the applied snapshot. Do not accept a candidate supplied through an unrelated issue comment or build artifact without checking its origin.
For the illustrative receiver, the change record includes the current applied list, the fetched candidate, the additions and removals, the configuration owner and a rollback reference. Hash the snapshots if that helps bind approval to the exact artifacts. The change should be understandable without repeatedly copying a mutable API response into a discussion.
Why should additions and removals be reviewed separately?#
Adding a newly announced source and deleting an old source have different failure consequences. The announcement calls for adding its prefixes alongside existing webhook ranges. Replacing an entire allowlist with only those additions would reject previously valid sources. An additive change is therefore the narrow response to this specific announcement. [1]
For an automated synchronizer, define how it handles a candidate that removes many entries, introduces an unexpected address family or changes the list dramatically. Our recommendation is to require review for unusual diffs and retain a last-known-good snapshot. The threshold is a local operational policy, not a limit supplied by GitHub.
Do not keep obsolete sources forever merely because removals require care. Plan a separate reconciliation process against the documented current list, provider requirements and your exposure policy. The immediate safety property is that a failed or malformed refresh cannot erase the working policy. The longer-term property is that the list remains deliberately maintained.
| Receiver state | Appropriate response | Evidence to retain |
|---|---|---|
| Static list misses announced additions | Review an additive policy change | Existing and candidate list plus applied diff |
| Synchronizer already applied current hooks | Verify delivery and leave policy alone | Successful refresh and enforcement result |
| Live source fetch fails | Retain last reviewed list and investigate | Fetch failure and age of applied snapshot |
| Candidate requests unexpected broad access | Hold automatic application | Parsed diff and named reviewer decision |
Apply the candidate through the infrastructure path that owns the actual enforcement point. Editing a console rule while a controller later restores the previous configuration creates a short-lived illusion of repair. Verify the rendered configuration and a delivery observation after the normal reconciliation cycle.
Does the allowlist authenticate a webhook?#
It is only one admission control. Keep signature verification over the actual received payload. GitHub documents the X-Hub-Signature-256 HMAC signature and recommends validating deliveries before processing them. An address that belongs to the permitted network does not express which repository event your application should act on. [4]
Verify the signature using the expected webhook secret and the raw payload bytes before decoding or acting on the event. Keep the secret out of source control and use the comparison method appropriate to your language. Also verify event type, action and the repository or installation context that your application expects. These controls address different boundaries. [3][4]
The proxy trust issue matters here again. An incoming request that claims a GitHub source address through a header should not be admitted solely on that claim. Likewise, an invalid signature must remain invalid after a network-policy update. Include a negative signature test in the rollout so the connectivity repair cannot accidentally become an authentication bypass.
Return successful receipt only when the receiver has reached its chosen durable acceptance point. GitHub's best-practice guide says receivers should respond promptly and suggests asynchronous processing. A fast success response followed by losing the event is still an application reliability defect. Define the queue failure path as carefully as the happy path. [3]
What proves the rollout restored the whole path?#
You need evidence at both the network and application boundaries. Start with a controlled test delivery or an appropriately authorized redelivery of a harmless event. Confirm that the edge admits the connection, the proxy forwards it, the signature check succeeds and the receiver records durable acceptance. A firewall policy compilation result proves none of those later steps.
Store the applied list with the deployment record so a later investigation can compare the source snapshot, the reviewed candidate and the enforced policy. If those disagree, find the configuration boundary that failed before fetching another candidate. Repeatedly replacing the file can hide the evidence needed to explain why the first approved change never reached the edge.
Check the negative cases, too. A request from an unauthorized source should still fail the intended network control. A request that reaches the application with an invalid signature should fail authentication. A valid but irrelevant event should not trigger the wrong business action. Keep these outcomes distinct in the review record.
If missed deliveries need recovery, use the product's documented redelivery path and reconcile accepted work. GitHub notes that a redelivery retains the original X-GitHub-Delivery value. A receiver that treats every repeated identifier as already completed can lose work when the earlier attempt failed before durable acceptance. Track accepted or completed state, rather than simply remembering that a header was once observed. [3]
This article's parser and source retrieval are inspectable examples. They do not establish that a production firewall was changed or that a GitHub tenant delivered an event successfully. Recheck the live hooks list when executing the rollout and preserve your own enforcement and application evidence. That keeps this dated analysis useful as the list evolves.
Frequently asked questions#
- Should I replace the allowlist with the announced prefixes?
- No. The announcement describes additions alongside existing webhook ranges. Fetch the current hooks list and review the actual change. Treating the announced additions as the entire replacement list can reject deliveries from previously valid sources. [1][2]
- Does an existing Meta API synchronizer need a code change?
- Not necessarily. GitHub says no change is needed for these additions when the allowlist already stays current through the API. Verify that your actual synchronizer applied the current list at the real enforcement point, rather than assuming its schedule proves success. [1]
- Can I copy addresses from the API documentation example?
- No. GitHub identifies the documented response values as examples and directs users to query the API for current values. Use a retrieved snapshot with its observation time, then validate and review it before applying policy. [2]
- Can IP filtering replace signature validation?
- No. Keep webhook signature verification and event-context checks even when source filtering is present. GitHub documents HMAC signatures as the mechanism for validating delivery contents. Network admission and application authorization address different parts of the receiving path. [3][4]