Conversation
Syncs fork's main branch with upstream daily at 6 AM UTC using GitHub's native merge-upstream API. Can also be triggered manually from the Actions tab. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- notification-relay: extend isPrivateIP to block 0.0.0.0/8, 169.254.x.x (link-local), and fe80: (IPv6 link-local) in SSRF guard - cross-module-integration: add explicit null check for sanctions before property access (TypeScript narrowing fix) - market-watchlist: replace `as any` with `Record<string, unknown>` for stricter type checking in coerceEntry() - ChatAnalystPanel: deduplicate scrollToBottom rAF calls during streaming to avoid excessive layout thrashing; clean up on destroy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@plato23 is attempting to deploy a commit to the Elie Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR applies targeted security hardening and code-quality fixes across five files. The most substantive change is expanding the SSRF private-IP guard in Key observations:
Confidence Score: 5/5Safe to merge — all changes are correct improvements with no functional regressions. No P0 or P1 issues found. The single comment is P2 (dead IPv6 code paths in isPrivateIP) and does not affect correctness or security — the SSRF guard is still effective for the IPv4 path that actually runs. All other changes (RAF guard, null check, type cast, sync workflow) are clearly correct. The PR's stated goals are fully met. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["sendSlack(userId, webhookEnvelope, text)"] --> B["decrypt(webhookEnvelope)"]
B -->|fail| Z1["return - warn"]
B -->|ok| C["Validate against SLACK_RE regex"]
C -->|invalid| Z2["return - warn"]
C -->|valid| D["dns.resolve4 - A records only"]
D -->|throws| Z3["return - warn, catches IPv6-only hosts"]
D -->|resolved IPs| E["addresses.some(isPrivateIP)"]
E -->|private range matched| Z4["return - SSRF blocked"]
E -->|public IP| F["fetch webhookUrl POST"]
F -->|404 or 410| G["deactivateChannel slack"]
F -->|ok| H["Message delivered"]
Reviews (1): Last reviewed commit: "Merge branch 'main' into fix/security-an..." | Re-trigger Greptile |
|
|
||
| function isPrivateIP(ip) { | ||
| return /^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|127\.|::1|fc|fd)/.test(ip); | ||
| return /^(0\.|10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|169\.254\.|127\.|::1$|fe80:|fc|fd)/.test(ip); |
There was a problem hiding this comment.
IPv6 patterns unreachable via
dns.resolve4
The IPv6 patterns added (::1$, fe80:, fc, fd) can never match in the current code path because dns.resolve4() resolves only A records and always returns IPv4 address strings. If a webhook host resolves exclusively via AAAA (IPv6), dns.resolve4 will throw a ENODATA/ENOTFOUND error, which is caught and the request is safely blocked — so there is no vulnerability, but the IPv6 guards in this function are currently dead code.
If IPv6 SSRF protection is desirable in future, consider also calling dns.resolve6() and checking those results through isPrivateIP. For now the defensive patterns don't cause any harm.
Summary
Type of change
Affected areas
/api/*)Checklist
api/rss-proxy.jsallowlist (if adding feeds)npm run typecheck)Screenshots