Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Implements a new internal API route ( Registers a new Reviewed by Cursor Bugbot for commit de70b89. Configure here. |
Greptile SummaryThis PR introduces a full SAP S/4HANA integration with 37 OData v2 tools (Business Partner, Customer, Supplier, Sales Order, Product, Purchase Order/Requisition, Supplier Invoice, Inbound/Outbound Delivery, Material Stock/Documents, Billing Document) plus a generic OData escape-hatch, backed by a single internal proxy route that manages BTP UAA token caching (LRU-capped at 500 entries), CSRF fetch-and-retry, OData payload normalization, and multi-deployment auth (OAuth 2.0 or HTTP Basic). All previously flagged security issues (SSRF via unvalidated URLs, unbounded token cache, missing fetch timeouts, unsafe Confidence Score: 5/5Safe to merge — no outstanding P0 or P1 findings; all previously flagged security issues have been addressed. The PR is a large but well-structured new feature. Security mitigations (SSRF blocklists covering loopback, link-local, RFC-1918, and IPv4-mapped IPv6 addresses; HTTPS enforcement; fetch timeouts; LRU token cache cap) are thorough. Tool implementations follow consistent patterns with proper input validation. No P1 or P0 findings identified in the current revision. apps/sim/app/api/tools/sap_s4hana/proxy/route.ts — most complex file; worth a final read-through, but no blocking issues found. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as Sim Client (Tool)
participant Proxy as /api/tools/sap_s4hana/proxy
participant SAP_Auth as SAP OAuth / BTP UAA
participant SAP as SAP OData Service
Client->>Proxy: POST (deploymentType, auth creds, service, path, method, body)
Proxy->>Proxy: Zod validation (URL safety, required fields)
Proxy->>Proxy: checkInternalAuth()
alt OAuth (cloud_public / cloud_private)
Proxy->>Proxy: Check TOKEN_CACHE (LRU, max 500)
alt Cache miss / expired
Proxy->>SAP_Auth: POST /oauth/token (client_credentials)
SAP_Auth-->>Proxy: access_token + expires_in
Proxy->>Proxy: rememberToken() into LRU cache
end
end
alt Write method (POST/PATCH/PUT/DELETE/MERGE)
Proxy->>SAP: GET /$metadata (X-CSRF-Token: Fetch)
SAP-->>Proxy: x-csrf-token + Set-Cookie
end
Proxy->>SAP: OData request (Authorization, CSRF token if write)
SAP-->>Proxy: Response
alt 403 + CSRF required
Proxy->>SAP: GET /$metadata (re-fetch CSRF)
SAP-->>Proxy: New CSRF token
Proxy->>SAP: Retry OData request
SAP-->>Proxy: Response
end
Proxy->>Proxy: unwrapOdata() strip .d / .d.results wrapper
Proxy-->>Client: { success, output: { status, data } }
Reviews (3): Last reviewed commit: "fix(sap_s4hana): allow versioned service..." | Re-trigger Greptile |
- 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>
|
@greptile |
|
@cursor review |
…fenses - 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>
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit de70b89. Configure here.
| } | ||
| } | ||
| return null | ||
| } |
There was a problem hiding this comment.
IPv4-mapped IPv6 SSRF check bypassed by URL normalization
Medium Severity
extractIPv4MappedHost expects dotted-decimal IPv4 after the ::ffff: prefix, but Node.js's WHATWG URL parser normalizes IPv4-mapped IPv6 addresses to hex form. For example, https://[::ffff:169.254.169.254]/ yields parsed.hostname of ::ffff:a9fe:a9fe, not the dotted form. The candidate a9fe:a9fe fails the IPv4 regex, so the check returns null. Likewise, FORBIDDEN_HOSTS entries like [::ffff:127.0.0.1] never match because the normalized form is ::ffff:7f00:1. This allows private/loopback addresses to bypass SSRF protections when supplied as IPv4-mapped IPv6 in baseUrl or tokenUrl. The HTTPS-only requirement limits impact but doesn't eliminate it for internal services with valid TLS.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit de70b89. Configure here.


Summary
Type of Change
Testing
Tested manually
Checklist