Commit 2502369
feat(integrations): SAP S/4HANA (#4301)
* feat(integrations): SAP S/4HANA tools, block, and proxy with multi-deployment support
* fix(sap_s4hana): address PR review comments
- Validate baseUrl/tokenUrl in Zod schema and at runtime to prevent SSRF
(https-only, deny loopback/link-local/cloud-metadata hosts)
- Cap proxy token cache at 500 entries with LRU eviction
- Add 30s timeout to outbound token, CSRF, and OData fetches
- Make parseJsonInput return T | undefined so missing input is type-safe
- Reset authType when deploymentType changes and surface OAuth fields
whenever auth is not basic, so cloud_public users always see clientId/
clientSecret after switching from a basic-auth private deployment
- Reject OData service names that are not uppercase identifiers and
paths containing ".." or "." traversal segments
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): allow versioned service names; tighten proxy SSRF defenses
- Permit ";v=NNNN" suffix on ServiceName regex so the four delivery tools
(API_OUTBOUND_DELIVERY_SRV;v=0002, API_INBOUND_DELIVERY_SRV;v=0002) pass
schema validation
- Restrict subdomain to RFC 1123 label characters and region to lowercase
alphanumeric short codes; run the constructed cloud_public host through
assertSafeExternalUrl so a crafted subdomain (e.g. "evil.com#") cannot
redirect requests carrying SAP credentials
- Block RFC-1918 (10/8, 172.16/12, 192.168/16), 127/8, 169.254/16, and
0.0.0.0 via isPrivateIPv4, plus IPv4-mapped IPv6 variants
(::ffff:10.0.0.1, ::10.0.0.1) so private internal hosts cannot be
reached from baseUrl, tokenUrl, or the resolved cloud_public URL
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): catch hex-form IPv4-mapped IPv6 in SSRF check
The WHATWG URL parser normalizes IPv4-mapped IPv6 addresses to hex form
(e.g. [::ffff:169.254.169.254] → [::ffff:a9fe:a9fe]), which slipped past
the dotted-decimal-only extractor. Decode the trailing two 16-bit hex
groups back into IPv4 octets and run them through isPrivateIPv4. Also
add isPrivateOrLoopbackIPv6 so pure IPv6 loopback (::, ::1), unique
local addresses (fc00::/7), and link-local (fe80::/10) cannot be reached.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): scope CSRF metadata fetch and isolate token cache by secret
- buildOdataUrl skips request query params when called with an internal
pathOverride so the /$metadata CSRF probe never carries user OData
options ($filter, $top, $select), which were causing write operations
through the generic odata_query tool to fail.
- tokenCacheKey now mixes a sha256 hash of clientSecret into the cache
key so two tenants sharing the same tokenUrl + clientId but different
secrets get isolated entries (no cross-tenant token leak).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): reject ?/# in service path; trim long update tool descriptions
- ServicePath validator now rejects "?" and "#" so a caller can't smuggle
query options through the path field (e.g.,
"/A_BusinessPartner?$format=atomsvc"); the Zod refine now reports
".." / "." segments, "?", and "#" together.
- Update Customer / Update Supplier / Update Purchase Requisition tool
descriptions exceeded the docs generator's 600-char regex window, so
they were rendering with empty descriptions on the integrations
landing page. Trimmed them to fit while keeping the limited-fields
note and the If-Match guidance, then regenerated integrations.json
and tool docs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): reject percent-encoded path traversal; widen Set-Cookie split
- ServicePath now also rejects %2e/%2E, %2f/%2F, %5c/%5C, %3f/%3F, %23
so a caller cannot smuggle ".." / "." / "/" / "\" / "?" / "#" past the
validator and have SAP's ABAP/ICM gateway decode them server-side.
- joinSetCookies fallback regex now allows the ", " separator that's
used when multiple Set-Cookie values are folded onto one header line
(older runtimes without Headers.getSetCookie). Prevents CSRF cookies
from being concatenated into a single value during write operations.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): preserve $ in OData query params; reject empty items array
- buildOdataUrl now constructs query strings manually with
encodeURIComponent and restores literal "$" so OData system options
($filter, $top, $select, $expand, $orderby, $skip, $format) reach
SAP and any intermediary proxies/WAFs as-is, not as "%24filter".
URLSearchParams was percent-encoding "$" to "%24" which most ICMs
decode but some intermediaries silently drop, returning unfiltered
results.
- create_sales_order now rejects an empty items array (matches
create_purchase_requisition) so callers get a clear client-side
error instead of an opaque SAP validation failure on the deep-insert.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): ignore baseUrl on cloud_public to prevent token redirection
Why: resolveHost previously preferred baseUrl unconditionally. A caller
sending deploymentType=cloud_public with a baseUrl pointing elsewhere
would obtain a real SAP UAA token, then forward it as Bearer to the
attacker host. Zod superRefine did not validate baseUrl for cloud_public.
Fix: resolveHost now constructs the SAP host from subdomain when
deploymentType is cloud_public and only uses baseUrl for cloud_private
and on_premise (where it is already SSRF-checked in superRefine).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(icons): use useId for SapS4HanaIcon and PipedriveIcon gradients
Why: hardcoded SVG gradient/mask IDs collide when an icon renders more
than once on a page (e.g. integrations listing). All other icons in this
file use React's useId() — these were inconsistent.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* icons
* fix(icons): use useId for AWS-style icon gradients
Why: IAMIcon, IdentityCenterIcon, STSIcon, SESIcon, and SecretsManagerIcon
all used hardcoded `id='xxxGradient'` values that collide when an icon
renders more than once on a page (e.g. integrations listing).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap_s4hana): ignore tokenUrl on cloud_public to prevent UAA redirection
Why: resolveTokenUrl previously honored caller-supplied tokenUrl
regardless of deploymentType, mirroring the same redirection class as
the prior baseUrl bug. A cloud_public caller could send tokenUrl to an
attacker host, causing the proxy to POST clientId:clientSecret as Basic
auth to it. superRefine for cloud_public did not validate tokenUrl.
Fix: derive UAA URL from subdomain+region for cloud_public; only honor
tokenUrl for cloud_private/on_premise (already SSRF-checked).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(icons): remove unused mask in PipedriveIcon
Why: the <mask> element had no consumer (no mask='url(#...)' anywhere
in the SVG), so both it and the maskId variable were dead code.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>1 parent 8266f0a commit 2502369
51 files changed
Lines changed: 8495 additions & 30 deletions
File tree
- apps
- docs
- components
- ui
- content/docs/en/tools
- sim
- app
- (landing)/integrations/data
- api/tools/sap_s4hana/proxy
- blocks
- blocks
- components
- tools
- sap_s4hana
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
| 157 | + | |
157 | 158 | | |
158 | 159 | | |
159 | 160 | | |
| |||
369 | 370 | | |
370 | 371 | | |
371 | 372 | | |
| 373 | + | |
372 | 374 | | |
373 | 375 | | |
374 | 376 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
150 | 150 | | |
151 | 151 | | |
152 | 152 | | |
| 153 | + | |
153 | 154 | | |
154 | 155 | | |
155 | 156 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
| 157 | + | |
157 | 158 | | |
158 | 159 | | |
159 | 160 | | |
| |||
351 | 352 | | |
352 | 353 | | |
353 | 354 | | |
| 355 | + | |
354 | 356 | | |
355 | 357 | | |
356 | 358 | | |
| |||
Lines changed: 167 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11379 | 11379 | | |
11380 | 11380 | | |
11381 | 11381 | | |
| 11382 | + | |
| 11383 | + | |
| 11384 | + | |
| 11385 | + | |
| 11386 | + | |
| 11387 | + | |
| 11388 | + | |
| 11389 | + | |
| 11390 | + | |
| 11391 | + | |
| 11392 | + | |
| 11393 | + | |
| 11394 | + | |
| 11395 | + | |
| 11396 | + | |
| 11397 | + | |
| 11398 | + | |
| 11399 | + | |
| 11400 | + | |
| 11401 | + | |
| 11402 | + | |
| 11403 | + | |
| 11404 | + | |
| 11405 | + | |
| 11406 | + | |
| 11407 | + | |
| 11408 | + | |
| 11409 | + | |
| 11410 | + | |
| 11411 | + | |
| 11412 | + | |
| 11413 | + | |
| 11414 | + | |
| 11415 | + | |
| 11416 | + | |
| 11417 | + | |
| 11418 | + | |
| 11419 | + | |
| 11420 | + | |
| 11421 | + | |
| 11422 | + | |
| 11423 | + | |
| 11424 | + | |
| 11425 | + | |
| 11426 | + | |
| 11427 | + | |
| 11428 | + | |
| 11429 | + | |
| 11430 | + | |
| 11431 | + | |
| 11432 | + | |
| 11433 | + | |
| 11434 | + | |
| 11435 | + | |
| 11436 | + | |
| 11437 | + | |
| 11438 | + | |
| 11439 | + | |
| 11440 | + | |
| 11441 | + | |
| 11442 | + | |
| 11443 | + | |
| 11444 | + | |
| 11445 | + | |
| 11446 | + | |
| 11447 | + | |
| 11448 | + | |
| 11449 | + | |
| 11450 | + | |
| 11451 | + | |
| 11452 | + | |
| 11453 | + | |
| 11454 | + | |
| 11455 | + | |
| 11456 | + | |
| 11457 | + | |
| 11458 | + | |
| 11459 | + | |
| 11460 | + | |
| 11461 | + | |
| 11462 | + | |
| 11463 | + | |
| 11464 | + | |
| 11465 | + | |
| 11466 | + | |
| 11467 | + | |
| 11468 | + | |
| 11469 | + | |
| 11470 | + | |
| 11471 | + | |
| 11472 | + | |
| 11473 | + | |
| 11474 | + | |
| 11475 | + | |
| 11476 | + | |
| 11477 | + | |
| 11478 | + | |
| 11479 | + | |
| 11480 | + | |
| 11481 | + | |
| 11482 | + | |
| 11483 | + | |
| 11484 | + | |
| 11485 | + | |
| 11486 | + | |
| 11487 | + | |
| 11488 | + | |
| 11489 | + | |
| 11490 | + | |
| 11491 | + | |
| 11492 | + | |
| 11493 | + | |
| 11494 | + | |
| 11495 | + | |
| 11496 | + | |
| 11497 | + | |
| 11498 | + | |
| 11499 | + | |
| 11500 | + | |
| 11501 | + | |
| 11502 | + | |
| 11503 | + | |
| 11504 | + | |
| 11505 | + | |
| 11506 | + | |
| 11507 | + | |
| 11508 | + | |
| 11509 | + | |
| 11510 | + | |
| 11511 | + | |
| 11512 | + | |
| 11513 | + | |
| 11514 | + | |
| 11515 | + | |
| 11516 | + | |
| 11517 | + | |
| 11518 | + | |
| 11519 | + | |
| 11520 | + | |
| 11521 | + | |
| 11522 | + | |
| 11523 | + | |
| 11524 | + | |
| 11525 | + | |
| 11526 | + | |
| 11527 | + | |
| 11528 | + | |
| 11529 | + | |
| 11530 | + | |
| 11531 | + | |
| 11532 | + | |
| 11533 | + | |
| 11534 | + | |
| 11535 | + | |
| 11536 | + | |
| 11537 | + | |
| 11538 | + | |
| 11539 | + | |
| 11540 | + | |
| 11541 | + | |
| 11542 | + | |
| 11543 | + | |
| 11544 | + | |
| 11545 | + | |
| 11546 | + | |
| 11547 | + | |
| 11548 | + | |
11382 | 11549 | | |
11383 | 11550 | | |
11384 | 11551 | | |
| |||
0 commit comments