Skip to content

fix(webhooks): блокировать DNS rebinding в outbound fetch#559

Merged
xlabtg merged 4 commits into
xlabtg:mainfrom
konard:issue-530-c1bc9af7dba1
Jun 7, 2026
Merged

fix(webhooks): блокировать DNS rebinding в outbound fetch#559
xlabtg merged 4 commits into
xlabtg:mainfrom
konard:issue-530-c1bc9af7dba1

Conversation

@konard
Copy link
Copy Markdown

@konard konard commented Jun 5, 2026

Fixes #530

Что изменено

  • Общий outbound-url-guard теперь резолвит hostname перед outbound-запросом, проверяет все A/AAAA адреса на private/loopback/link-local/metadata ranges и возвращает validated address set.
  • Добавлен безопасный fetchValidatedOutboundUrl: запрос выполняется через одноразовый undici.Agent с pinned lookup, поэтому подключение использует только уже проверенные IP; redirects переведены в manual, чтобы не следовать на непроверенный URL.
  • Alerting webhook delivery и WebhookDispatcher используют новый pinned fetch на request-time. Create/update webhooks сохраняют синхронную shape-проверку, а DNS SSRF-блокировка происходит непосредственно перед отправкой.
  • Workflow call_api переведен на тот же pinned outbound fetch helper, чтобы execution-time защита соответствовала workflow validation.
  • README.md синхронизирован с текущей версией 0.8.32, чтобы существующий docs-тест оставался зеленым.

Как воспроизвести

До исправления webhook hostname вроде https://rebind.example.com/hook мог пройти literal URL validation, а затем при фактическом fetch резолвиться в 169.254.169.254 или другой internal address. Также DNS lookup, который делал обычный fetch, не был привязан к предварительно проверенному IP, что оставляло окно для DNS rebinding между validation и connect.

Регрессионные проверки

  • src/services/__tests__/alerting.test.ts: validateWebhookUrl и anomaly webhook dispatch отклоняют hostname, который резолвится в metadata IP, и не вызывают fetch.
  • src/services/__tests__/webhook-dispatcher.test.ts: delivery в metadata-resolved hostname помечается как permanent failure без outbound fetch.
  • src/services/__tests__/workflow-executor.test.ts: successful call_api получает pinned dispatcher и redirect: "manual"; DNS lookup выполняется с { all: true, verbatim: true }.

Проверки

  • npm run build:sdk
  • npm run typecheck
  • npm run lint
  • npm test -- src/services/__tests__/alerting.test.ts src/services/__tests__/webhook-dispatcher.test.ts src/services/__tests__/workflow-executor.test.ts src/webui/__tests__/workflows-routes.test.ts
  • npm test -- src/docs/__tests__/readme.test.ts
  • npm test (222 files, 3631 tests)
  • npm run format:check
  • npm run build:backend

Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: xlabtg#530
@konard konard changed the title [WIP] [AUDIT/V4] Outbound webhook SSRF guard validates only literal IPs/hostnames, never the resolved address (DNS-rebinding bypass) fix(webhooks): блокировать DNS rebinding в outbound fetch Jun 5, 2026
@konard konard marked this pull request as ready for review June 5, 2026 14:16
@konard konard deployed to pr-preview June 5, 2026 14:22 — with GitHub Actions Active
@konard
Copy link
Copy Markdown
Author

konard commented Jun 5, 2026

Working session summary

Готово: PR #559 обновлен и переведен в ready for review: #559

Сделано:

  • Добавлена DNS-проверка всех resolved A/AAAA адресов для outbound URL guard.
  • Outbound fetch теперь идет через pinned undici.Agent, чтобы подключение использовало только проверенные IP.
  • Redirects отключены через redirect: "manual".
  • Alerting webhooks, WebhookDispatcher и workflow call_api переведены на общий защищенный fetch helper.
  • Добавлены регрессионные тесты для hostname, который резолвится в metadata IP.
  • README синхронизирован с версией 0.8.32.

Проверки локально прошли:

  • npm run build:sdk
  • npm run typecheck
  • npm run lint
  • targeted webhook/workflow tests
  • npm test — 222 files, 3631 tests
  • npm run format:check
  • npm run build:backend

CI на свежем head 5e00d30aa1c76a22e5fc4fbbd0604c196f5abf9c зеленый: CI, CodeQL и Secret Scanning успешны; E2E skipped. Merge state PR: CLEAN. Рабочее дерево чистое.


This summary was automatically extracted from the AI working session output.

@konard
Copy link
Copy Markdown
Author

konard commented Jun 5, 2026

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Model: GPT-5.5
  • Provider: OpenAI
  • Public pricing estimate: $15.400462

📊 Context and tokens usage:

  • 321.1K / 1.1M (31%) input tokens, 54.2K / 128K (42%) output tokens

Total: (321.1K + 9.8M cached) input tokens, 54.2K output tokens, $15.400462 cost

🤖 Models used:

  • Tool: OpenAI Codex
  • Requested: gpt-5.5
  • Model: GPT-5.5 (gpt-5.5)

📎 Log file uploaded as Repository (60591KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard
Copy link
Copy Markdown
Author

konard commented Jun 5, 2026

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

@xlabtg xlabtg merged commit 9eddda1 into xlabtg:main Jun 7, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[AUDIT/V4] Outbound webhook SSRF guard validates only literal IPs/hostnames, never the resolved address (DNS-rebinding bypass)

2 participants