Skip to content

fix(webhook): reject literal private and reserved destinations - #680

Draft
seonghobae wants to merge 4 commits into
developfrom
sentinel-ssrf-webhook-10410793400108152594
Draft

fix(webhook): reject literal private and reserved destinations#680
seonghobae wants to merge 4 commits into
developfrom
sentinel-ssrf-webhook-10410793400108152594

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Current authority

  • protected base snapshot: develop@2c328875e00e86537df3e965170be80532571cad
  • semantic repair head/tree: de3baaf43af211af4cc2099b336dc946f853b47b
  • exact current head: f941f969c98174ca8325938a3927a020fcc874b0
  • lifecycle: Draft / valid literal-address repair / complete SSRF authority still unresolved

The BlockList/isIP validation is retained as a bounded repair for literal loopback/private/link-local IPv4/IPv6 destinations. It is not a complete High-severity SSRF fix and must not be represented as one.

Source-neutral intervening history

After semantic head de3baaf..., the branch received three consecutive commits named ci: re-kick required checks to bypass flake: c10374f..., bc4fb6a..., and current f941f969.... Git data shows all three use the same tree ad0e132d57bd5de81d14e74b90a230f49ea112c7; they do not add product/test/contract delta.

They are preserved as ordinary history and are not treated as security progress or evidence-generating source fixes. Do not repeat this source-neutral/no-op retrigger pattern. Future branch movement must carry a real causal repair or a required non-force restack/adoption delta.

Remaining P1 owner defect

The leaf still cannot safely own the complete outbound destination boundary:

  1. non-literal hostnames may resolve to loopback/private/link-local/metadata space;
  2. create-time validation does not reauthorize a stored destination at delivery time;
  3. ordinary fetch(url, ...) can follow a redirect to a target that was never independently authorized;
  4. a separate DNS precheck is TOCTOU because the HTTP client may resolve again before connect;
  5. authorization is not yet cryptographically/evidentially bound to the authored hostname, authorized address set, actual connection target, redirect chain and TLS hostname authority under one bounded lifecycle.

Required hostile acceptance remains: hostname→private/metadata resolution, changed DNS answer between authorization and connect, public→private redirect, delivery-time reauthorization of a stored destination, and bounded end-to-end resource/time semantics. Every rejection must prove no unauthorized outbound connection occurred.

Canonical owner path

EgressWeave owns special-purpose-address handling, DNS-rebinding resistance, redirect/proxy/TLS policy, bounded outbound lifecycle and stable denial evidence. Existing owner issue ContextualWisdomLab/EgressWeave#237 has now been extended with this exact ScopeWeave consumer canary and RED/GREEN acceptance. Durable GREEN is an immutable released EgressWeave API/schema/ACL with hostile conformance vectors, SBOM/provenance/reproducibility/rollback evidence, followed by a thin ScopeWeave adapter and exact-head consumer tests. Mutable sibling source, commit vendoring, duplicated policy and cross-service SQL are not accepted.

Exact-head workflow evidence

On exact current f941f969..., Server Tests 34243452570, Security Scan 34243452469, SAST Semgrep 34243452722, and Fuzz 34243452538 are terminal SUCCESS.

CodeQL PR 34243452627 is terminal FAILURE in the central receipt path: language detection succeeded; JavaScript/TypeScript compatibility failed enforcement at 15:25:26Z, Python at 15:25:39Z, and Actions at 15:25:43Z, while the same generation's Dispatch current-head CodeQL scan did not start until 15:30:39Z and then succeeded. This is central sequencing/receipt-availability evidence, not a reason for another ScopeWeave no-op commit or gate waiver.

There are currently zero inline review threads. Keep Draft because a released owner contract, complete hostile consumer GREEN, terminal central CodeQL evidence and qualifying independent review are still absent.

No force push, destructive rebase, self-approval, gate weakening, synthetic status, predecessor-GREEN transfer, protected merge or release is claimed.

This patch adds validation to the webhook creation endpoint using
`node:net.BlockList` to block internal, loopback, and cloud metadata IPs.
@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae marked this pull request as draft September 8, 2026 14:22

Copy link
Copy Markdown
Contributor Author

현재 exact head de3baaf43af211af4cc2099b336dc946f853b47b를 다시 검토했습니다. literal IP 차단은 유효한 부분 수리지만, High SSRF를 닫기에는 아직 P1 경계가 남아 있어 PR을 Draft로 되돌렸습니다.

현재 isSafeWebhookUrl()은 hostname을 DNS resolve하지 않으므로 외형상 공인 hostname이 loopback/private/link-local/metadata 주소로 resolve되는 경우를 막지 못합니다. 더 중요하게는 생성 시점에만 검증하고 실제 sendWebhook()은 저장된 URL을 raw fetch(url, ...)로 다시 사용합니다. fetch의 별도 DNS resolution과 기본 redirect 처리 때문에 단순 dns.lookup() precheck를 추가해도 authorize→connect 사이 DNS rebinding/TOCTOU가 남고, 공인 endpoint가 private/link-local로 redirect하는 경로도 재승인되지 않습니다.

현실적인 RED는 최소한 다음을 포함해야 합니다: (1) hostname→127.0.0.1 / 169.254.169.254, (2) authorization 후 DNS answer가 바뀌는 경우, (3) public URL→private/link-local redirect, (4) 저장된 webhook의 delivery-time 재승인 실패. 네 경우 모두 outbound network call이 발생하지 않아야 합니다.

GREEN은 ScopeWeave에 별도 outbound-policy 구현을 확장하는 것이 아니라 canonical EgressWeave boundary를 소비하는 방향이어야 합니다. destination/특수주소/DNS rebinding/redirect/proxy/TLS/resource policy는 EgressWeave 소유입니다. released immutable contract가 준비되면 hostname + 모든 resolved address + 실제 connect target + 각 redirect hop을 하나의 bounded authorization/execution contract로 묶고, ambient proxy를 허용하지 않으며, unsupported/unavailable authority는 fail closed해야 합니다. mutable EgressWeave source copy나 dns.lookup() 후 일반 fetch() 식의 부분 workaround는 acceptance가 아닙니다.

@seonghobae seonghobae changed the title 🛡️ Sentinel: [High] 웹훅 SSRF 취약점 수정 fix(webhook): reject literal private and reserved destinations Sep 8, 2026
@seonghobae seonghobae added bug Something isn't working priority: high High-priority or P1 work labels Sep 12, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: high High-priority or P1 work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant