Skip to content

fix(ai-proxy): validate the Zendesk subdomain and refuse redirects on integration requests - #2039

Merged
PMerlet merged 1 commit into
mainfrom
security/fix-ai-proxy-prd-1724
Oct 25, 2026
Merged

PMerlet merged 1 commit into
mainfrom
security/fix-ai-proxy-prd-1724

Conversation

@PMerlet

@PMerlet PMerlet commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Refs PRD-1724

What

  • getZendeskConfig requires the subdomain to be a single DNS label (^[A-Za-z0-9-]{1,63}$), like Snowflake's ACCOUNT_IDENTIFIER_RE; anything else throws AIBadRequestError (400) before a request is sent.
  • New integrations/fetch-without-redirect.ts: every Zendesk and Snowflake request (tools and config validation) goes through it. It sends redirect: 'manual' and throws AIToolUnprocessableError (422) on any 3xx. Neither API redirects, so no legitimate call is affected.

Tests

  • test/integrations/fetch-without-redirect.test.ts runs real local servers (no fetch mock): 301/302/303/307/308 are refused and the redirect target receives nothing, including through a Zendesk tool and a Snowflake POST tool.
  • zendesk/utils.test.ts: valid and invalid subdomains, and no request sent for an invalid one.
  • 35 existing exact fetch assertions now also expect redirect: 'manual'.

Behavioral change

A connector saved with a subdomain that is not a single DNS label now fails when its tools load, as an invalid Snowflake account identifier already does.

Definition of Done

General

  • Write an explicit title for the Pull Request, following Conventional Commits specification
  • Test manually the implemented changes
  • Validate the code quality (indentation, syntax, style, simplicity, readability)

Security

  • Consider the security impact of the changes made

🤖 Generated with Claude Code

Note

Refuse redirects on Zendesk and Snowflake integration requests and validate the Zendesk subdomain

  • Adds fetchWithoutRedirect in fetch-without-redirect.ts. It forces manual redirect handling and raises AIToolUnprocessableError for any HTTP 300–399 response instead of following the Location target
  • Switches all Zendesk and Snowflake tool calls plus config validation to use fetchWithoutRedirect. Request URLs, headers, payloads, and response handling are unchanged
  • Adds assertValidSubdomain in utils.ts. It requires one DNS-label-like segment of 1–63 ASCII letters, digits, or hyphens. getZendeskConfig now calls it before building the base URL and throws AIBadRequestError on invalid values
  • Risk: integration requests that relied on redirects being followed now fail with AIToolUnprocessableError; check fetchWithoutRedirect and any integration not listed here that still uses direct fetch

Macroscope summarized 08f5247.

@linear-code

linear-code Bot commented Oct 23, 2026

Copy link
Copy Markdown

PRD-1724

@qltysh

qltysh Bot commented Oct 23, 2026

Copy link
Copy Markdown

2 new issues

Tool Category Rule Count
qlty Duplication Found 28 lines of similar code in 2 locations (mass = 106) 2

@qltysh

qltysh Bot commented Oct 23, 2026

Copy link
Copy Markdown

Qlty


Coverage Impact

This PR will not change total coverage.

Modified Files with Diff Coverage (12)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/get-tickets.ts100.0%
Coverage rating: A Coverage rating: A
...ges/ai-proxy/src/integrations/snowflake/tools/execute-query.ts100.0%
Coverage rating: A Coverage rating: A
...ges/ai-proxy/src/integrations/snowflake/tools/cortex-search.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/create-ticket.ts100.0%
Coverage rating: A Coverage rating: A
...es/ai-proxy/src/integrations/snowflake/tools/cortex-analyst.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/update-ticket.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/integrations/snowflake/utils.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/utils.ts100.0%
Coverage rating: A Coverage rating: A
...-proxy/src/integrations/zendesk/tools/create-ticket-comment.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/get-ticket.ts100.0%
Coverage rating: A Coverage rating: A
...ai-proxy/src/integrations/zendesk/tools/get-ticket-comments.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/fetch-without-redirect.ts100.0%
Total100.0%
🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@PMerlet PMerlet left a comment •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spec (PRD-1724): conforms.

Comment thread packages/ai-proxy/src/integrations/fetch-without-redirect.ts
… integration requests

The Zendesk subdomain must now be a single DNS label, and Zendesk and Snowflake
integration requests fail with a 422 on any redirect.

fixes PRD-1724

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PMerlet
PMerlet force-pushed the security/fix-ai-proxy-prd-1724 branch from 3640dde to 08f5247 Compare October 23, 2026 17:26

@Tonours Tonours left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spec (PRD-1724): the ai-proxy fix matches the ticket, subdomain pattern and redirect: 'manual' included. The server-side scope is not covered.

Applies to: the PR description
Claude Opus 5.5 (claude-opus-5-5): Should fix: merging closes PRD-1724 while its server-side half is still open.

Code

PRD-1724 also asks to whitelist config keys per integration server-side, and fixes PRD-1724 closes it on merge.

A way out: link with Refs PRD-1724, or split the server work into its own ticket.

Reproduction
  1. Merge this PR.
  2. Open PRD-1724: it is Done while the server-side item has no change.

Comment thread packages/ai-proxy/src/integrations/zendesk/utils.ts
@PMerlet

PMerlet commented Oct 24, 2026

Copy link
Copy Markdown
Member Author

Claude Opus 5.5 (claude-opus-5-5): The PR description now links the ticket with Refs PRD-1724 instead of fixes PRD-1724, so merging leaves it open.

Why

The ticket also needs a change in another repository before it can close, so it stays open after this merge.
No commit was needed, since only the description changed.

@Tonours

Tonours commented Oct 24, 2026

Copy link
Copy Markdown
Member

Closed: the description now links Refs PRD-1724 instead of fixes PRD-1724, as the finding asked.

How it was checked

The predicate is a closing keyword for PRD-1724 in the pull request description.
The body read at head 08f5247f9 carries Refs PRD-1724 and no closing keyword.
No regression test can pin a pull request description, so this close is unpinned.

@Tonours Tonours left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after /verify-fixes run 2039-20261024121938-Tonours-verify: 2 findings of 2039-20261023191852-Tonours closed or accepted, none reopened.

@PMerlet
PMerlet merged commit 0f23cd0 into main Oct 25, 2026
33 checks passed
@PMerlet
PMerlet deleted the security/fix-ai-proxy-prd-1724 branch October 25, 2026 12:03
forest-bot added a commit that referenced this pull request Oct 25, 2026
## @forestadmin/ai-proxy [1.15.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/ai-proxy@1.15.0...@forestadmin/ai-proxy@1.15.1) (2026-10-25)

### Bug Fixes

* **ai-proxy:** validate the Zendesk subdomain and refuse redirects on integration requests ([#2039](#2039)) ([0f23cd0](0f23cd0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants