fix(security): prevent outbound webhook SSRF - #552
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough
Changes웹훅 SSRF 방어 및 SaaS 앱 통합
Estimated code review effort: 5 (Critical) | ~120 minutes Merge Risk: 🟠 High · up to This PR changes outbound webhook delivery and OIDC login handling, but the current head can resend POST requests after a response has started, potentially duplicating webhook actions or breaking one-time login exchanges; OIDC discovery destinations also remain insufficiently bounded, and an OIDC configuration response contract disagrees with its tests. Required current-head checks and independent approval are not yet available, so merge should be blocked until these issues are fixed and evidence is refreshed. Sequence Diagram(s)sequenceDiagram
participant Client
participant AppFacade
participant CoreApp
participant WebhookTransport
participant DNSResolver
participant HTTPSRequest
Client->>AppFacade: 웹훅 등록 또는 이벤트 요청
AppFacade->>CoreApp: 인증·tenant·권한 검사
CoreApp->>WebhookTransport: 서명된 웹훅 전달
WebhookTransport->>DNSResolver: 매 시도 A/AAAA 조회
DNSResolver-->>WebhookTransport: 주소 목록 반환
WebhookTransport->>WebhookTransport: 공용 주소 재검증 및 소켓 고정
WebhookTransport->>HTTPSRequest: redirect 없는 HTTPS POST
HTTPSRequest-->>WebhookTransport: 응답 상태
WebhookTransport-->>CoreApp: 전송 결과 또는 안정적 오류
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
|
@opencode-agent Repair this existing Draft branch only. Exact current head is |
|
@coderabbitai review |
|
|
|
|
Fresh current-head revalidation for the transient SQLite writer-lock finding:
RED is preserved rather than inferred: predecessor The current one-line production repair sets SQLite The PR body’s older exact-head text is historical; use the head/base above until the body is refreshed. Hosted PR checks are still non-authorizing where they materialize the synthetic merge ref rather than the exact contributor commit, so this evidence does not relax the existing exact-head/independent-review merge gate. |
|
@jules Continue this existing branch only; do not create a competing PR and do not touch unrelated ScopeWeave lanes. Fresh serialization point: exact current contributor head is Repair the root cause on THIS branch by replacing process-wide fetch interception with explicit, fail-closed sensitive outbound collaborators. Keep the existing SSRF/OIDC security semantics intact. Required bounded design:
This also addresses the still-current architectural review observations that webhook SSRF safety depends on import order/global fetch interception. Do not resolve those threads until the exact new head is inspected and GREEN evidence exists. Preserve all unrelated long-lived #552 repairs. |
Security and buyer outcome
Refs #551. Protected
developstill ships the historical outbound-webhook behavior until this PR integrates. This branch replaces that boundary with a bounded public-HTTPS transport, closes DNS-rebinding and Request-object bypasses, preserves signing/retry accounting, hardens the adjacent OIDC callback path, bounds public authentication request bodies, and keeps existing insecure webhook rows fail-closed with a tenant-visible replacement action.The latest repair also removes a startup availability hazard in the legacy-webhook reconciliation path: a database whose active webhook destinations already comply with current policy no longer reserves SQLite's single writer merely to discover that no migration work is required.
Exact current state
develop@2c328875e00e86537df3e965170be80532571cad;92487d1f9e5215cd4b7302275c23393596799ba3;948d8484c27e456e6ad7709dca4df92ca6c0b272;fix/webhook-ssrf-551;Any contributor-head or protected-base movement invalidates head/base-sensitive evidence until the exact revisions, review state, actual checkout attestations, checks, and live-base identity are freshly revalidated.
Implemented security and reliability contract
globalThis.fetchreplacement; unclassified core egress fails closed;Request.clone();(jwks_uri, kid)with a fixed bound;BEGIN IMMEDIATEtransaction before disabling rows and writing audit evidence; andLatest test-first startup-lock repair
A realistic SQLite contention regression was added before the production change. It opens a compliant legacy-webhook database, has a second connection hold
BEGIN IMMEDIATE, and requiresmigrateLegacyWebhookDestinations()to remain a read-only no-op rather than competing for the writer.RED predecessor:
6228733d4676a69f596742be765ac95f2dd9ab76;33125882051,unit-and-apijob98703805992;database is lockedatmigrateLegacyWebhookDestinations, proving the unconditional transaction was reachable.GREEN current head:
92487d1f9e5215cd4b7302275c23393596799ba3;33126053154is terminal success;unit-and-apijob98704354241is terminal success and explicitly reports bothlegacy HTTP webhook migration regression passedandlegacy private HTTPS webhook migration regression passedtogether with the full unit/API suite;948d8484c27e456e6ad7709dca4df92ca6c0b272, loggingMerge 92487d1f9e5215cd4b7302275c23393596799ba3 into 2c328875e00e86537df3e965170be80532571cad.The repair is intentionally two-part.
server/webhook_legacy_migration.mjsnow uses a read-only preflight and reacquires/re-reads underBEGIN IMMEDIATEonly if a policy-incompatible active destination exists.server/db.mjsremoves the two duplicated unconditional startup transactions and delegates all deterministic legacy-webhook reconciliation to that helper. This changes the actual application startup path rather than merely making the helper test green.Retained test-first repair evidence
The current branch also retains realistic RED→GREEN regressions for Request-object webhook bypasses, OIDC signature/claim validation and
email_verified, OIDC metadata SSRF, multi-key JWKS reuse, public-auth body bounding, historical mixed-case identity compatibility, webhook transport framing/replay semantics, legacy HTTP/private-HTTPS webhook migration, facade/core request observability, and module-local fail-closed egress ownership. Review threads are resolved only after the relevant behavior is repaired or freshly shown not to be a current defect.Current workflow evidence
For exact contributor head
92487d1f9e5215cd4b7302275c23393596799ba3, the latest fresh workflow inventory is:33126053154— terminal success;33126053151— terminal success;33126053168— terminal success;33126053133— terminal success;33126053576— terminal success; and33126053159— still in progress at the last fresh refetch and therefore non-passing until terminal substantive evidence exists.These hosted results are behavior/regression evidence, not yet merge authority, because the Server Tests run above materialized a synthetic PR merge rather than the immutable contributor SHA. ScopeWeave PR #523 owns the repository-native Server Tests/coverage exact-head checkout prerequisite.
ContextualWisdomLab/.github#1222is the canonical central owner issue for reusable SAST/Security exact-head evidence. Once those controls integrate, this unchanged contributor head (or its freshly revalidated successor) must regenerate every applicable test, browser, coverage/docstring, CodeQL/SAST/security, dependency/supply-chain, package/provenance and review gate with actual checkout identity proven against the exact contributor SHA.Standards and traceability
docs/doctoring/outbound-webhook-ssrf.mdrecords protected-shipped versus active-PR truth, SSRF/DNS-rebinding threats, pinned-address decisions, redirect/error semantics, executable acceptance, rollback boundaries, and applicable primary standards/official references.Merge gate
Do not mark Ready, merge, or enable auto-merge until the unchanged exact contributor head remains reconciled to freshly resolved protected
develop, #523's repository exact-head control and the central SAST/Security exact-head repair are protected-shipped, every applicable repository and organization CI/browser/owned-coverage/docstring/CodeQL/SAST/security/dependency/supply-chain/package/provenance gate is substantively terminal-passing under corrected evidence contracts, valid unresolved findings are zero, and a qualifying independent current-head approval genuinely exists under live governance. Pending, queued, skipped-required, cancelled, absent, neutral-required, failed, stale, predecessor, synthetic-only, status-only, author-only, model-only, rate-limited, or infrastructure-only evidence is non-passing.