Commit Graph

16 Commits

Author SHA1 Message Date
Ben Sabic 6adca3617e feat(slack): support egress proxies (#916)
Adds proxy configuration for Slack connections that previously bypassed
`webClientOptions.agent`. Socket Mode now uses that agent for HTTP and
WebSocket connections, and new `fetch` and `fileTransport` options cover
response URLs, webhook forwarding, and attachment downloads.

```ts
createSlackAdapter({
  webClientOptions: { agent },
  fetch: proxyFetch,
  fileTransport,
});
```

Includes a setup example and guidance on the destination restrictions
custom download transports need to enforce.

Closes #596

---------

Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-09-09 17:46:53 +00:00
Akazawa Daisuke e71bfead52 fix(slack): preserve first line of incoming code blocks (#843)
## Summary

fixes #842

normalizes incoming Slack triple-backtick code fences before parsing
them as CommonMark

Slack treats text immediately after an opening fence as code content,
while CommonMark treats it as the fence's info string; putting Slack
fences on their own lines preserves the first code line in both
`message.text` and `message.formatted`

the normalization also separates fences from surrounding text so inline
Slack code blocks are parsed as fenced code blocks instead of regular
Markdown text

## Test plan

- added format-level regression coverage for code starting immediately
after an opening fence and for fences adjacent to surrounding text
- added converter-level assertions for the parsed code node and
extracted plain text
- ran the focused Slack format and Markdown test suites
- ran `pnpm validate`

## Checklist

- [x] All commits are signed and verified
- [x] All commits are signed off for the DCO (`git commit -s`)
- [x] `pnpm validate` passes
- [x] Changeset added (or N/A — see
[CONTRIBUTING.md](./CONTRIBUTING.md))
- [x] Documentation updated (or N/A)

---------

Signed-off-by: akkadaska <akkadaska@gmail.com>
Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-08-28 15:09:03 +10:00
Ben Sabic b6fa24c68f fix(adapters): guard attachment downloads across slack, discord, telegram, and whatsapp (#865)
Follows up on #850, #856, and #859 by adopting the shared guarded
downloader (`downloadAttachment` in `@chat-adapter/shared`) in the
remaining adapters that fetch attachment bytes from event-supplied URLs.

- Slack, Discord, and WhatsApp attachment downloads now refuse private
and internal addresses (as URL literals, through DNS resolution, and
after redirects), cap responses at 25 MB, and time out after 30 seconds.
- Slack sends the bot token only on hops to trusted Slack origins, so a
redirect can never carry it to another host, and keeps the
HTML-login-page detection. A protected `createFileTransport()` override
routes downloads through a proxy.
- WhatsApp keeps its access token on Meta's media hosts, and the
configured Graph origin via the hosts allowlist; `downloadMedia()`
accepts a custom transport.
- Telegram keeps downloads on the Web Fetch API because a downstream
Cloudflare Workers consumer depends on portability (#828), enforcing the
same 25 MB cap and 30-second timeout with web streams.
- `downloadAttachment` now resolves `headers` per hop (function form
decides what each redirect target receives), forwards the resolved
headers to custom transports, and accepts an `onResponse` hook that can
reject a final response before its body is read.
- Adds "Inbound attachments" docs sections for all four adapters.

---------

Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-08-27 13:05:06 +10:00
josh 153bd9640d fix(messenger): guard attachment downloads (#856)
## summary

- restrict Messenger attachment downloads to Meta's `fbsbx.com` and
`fbcdn.net` hosts while preserving external URLs on `attachment.url`
- reject untrusted URLs before connecting using HTTPS validation,
connection-bound DNS checks, manual redirect validation, timeouts, and
streamed size limits
- move the guarded downloader into `@chat-adapter/shared` and keep the
Teams implementation behaviorally equivalent
- normalize malformed redirect locations and other download failures as
typed `NetworkError` values
- document the inbound attachment policy for Messenger
- stacked on #850 and should merge after it

## test plan

- verified valid Meta image, audio, video, and file CDN hosts remain
downloadable
- verified external hosts, private addresses, malformed URLs, unsafe
ports, trailing dots, and suffix attacks are rejected
- verified mixed private and public DNS results fail closed
- verified redirects are revalidated and malformed or external
destinations are rejected
- verified declared and streamed size limits and stalled body timeouts
- ran workspace build, affected package tests and typechecks,
integration checks, Knip, Ultracite, and diff validation

Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-08-25 21:30:21 +10:00
josh bb926884a2 fix(teams): secure attachment downloads (#850)
## summary

- restrict anonymous attachment downloads to current Microsoft 365
SharePoint and OneDrive for Business hosts
- reject internal addresses using connection-bound DNS validation
- revalidate every redirect and disable connection reuse outside the
guarded transport
- enforce a 25 MB streaming response limit and a 15 second request
timeout
- preserve connector-origin bot authentication and the protected custom
fetch override
- document the default anonymous download policy

## test plan

- verify trusted Microsoft 365 attachment hosts remain supported
- verify HTTP, custom ports, lookalike domains, trailing-dot hosts, and
generic off-origin URLs are rejected
- verify private IPv4, encoded IPv4, bracketed IPv6, and mixed DNS
results are rejected
- verify redirects are revalidated before another request
- verify oversized streamed responses are stopped
- verify activity parsing and attachment rehydration use the guarded
transport
- run Teams tests, typecheck, formatting, and production builds

---------

Signed-off-by: dancer <josh@afterima.ge>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-08-25 21:09:08 +10:00
Ben Sabic d4c52cade3 refactor(shared): share the bare-mention scanner across Discord, Teams, and Slack (#652)
The Discord adapter (fixed in #651) converts bare `@mentions` with a
regex. A single-character lookbehind can't tell whether an `@` sits
inside a URL, a code span, or an email host, so it still mangles cases
the regex can't see. The Slack adapter already had a robust
character-scanning resolver — `replaceBareMentions` — that handles
exactly those cases, but it lived inside `adapter-slack`.

This lifts that scanner into `@chat-adapter/shared` and points every
adapter that does bare-mention conversion at it: Slack (dedup, no
behavior change), Discord, and Teams — which had the identical
`/@(\w+)/g` → `<at>$1</at>` bug in two places.

## What changed

- **`@chat-adapter/shared`** — new `replaceBareMentions` (+
`MentionReplacer` type), moved verbatim from Slack. It skips
inline/fenced code, scheme + schemeless URLs, and existing `<…>` tokens
before handing each real `@name` to a platform-specific replacer. Adds a
dedicated test file (the scanner had no direct tests before).
- **Slack** — sources `replaceBareMentions` from `@chat-adapter/shared`;
local `mentions.ts` deleted. Behavior unchanged.
- **Discord** — regex → scanner in both conversion sites.
- **Teams** — same fix for `<at>…</at>` mention tags.

## What this fixes (Discord + Teams)

Across both the `{markdown}`/AST and `{raw}`/plain-string paths:

| input | before | after |
|---|---|---|
| `https://github.com/@vercel` | `https://github.com/<@vercel>` |
preserved |
| `twitter.com/@jack` | `twitter.com/<@jack>` | preserved |
| `` `ping @here` `` | `` `ping <@here>` `` | preserved |
| `<@123>` (Discord, raw) | `<<@123>>` | preserved |

Emails (`user@example.com`), period-prefixed mentions
(`docs.@everyone`), and existing tokens keep working.

## Notes

- `.changeset/config.json` uses `fixed: [["chat", "@chat-adapter/*"]]`,
so the `@chat-adapter/shared` **minor** bump carries the whole family to
a minor release; the `discord` / `teams` `patch` changesets exist for
their changelog text. Slack has no behavioral change, so it gets no
changeset.
- Rebased on top of #651. That PR's `discord-email-mentions.md`
changeset stays; this PR's scanner supersedes its regex implementation,
so the two Discord changelog entries read as a progression.

Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com>
Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-07-02 18:45:16 +01:00
josh add27309fb feat(telegram): support typed attachment uploads (#485) 2026-05-11 18:56:42 -07:00
Malte Ubl 9824d3335e Adapter hardening pass (#441)
* Adapter hardening pass

* chore: remove redundant changeset

---------

Co-authored-by: dancer <josh@afterima.ge>
2026-05-02 08:37:45 -07:00
Malte Ubl 02e7ef605c Implement markdown and AST rendering for tables across adapters (#160)
* Implement markdown and AST rendering for tables across adapters

* Render the default instead

* Fix bot app

* lint

* streaming-rendering

* fix-streaming

* fix-streaming-agent

* fix-streaming-again2

* fix-streaming-again3

* prefix tests

* no final edit

* changeset

* feedback

* lint

* Copilot feedback
2026-03-03 09:43:18 -08:00
Nicolás Montone 5b3090a7a6 add CardLink Element (#109) 2026-02-25 08:05:30 -08:00
Hayden Bleasel e970a6939b Upgrade Biome configuration to use Ultracite preset (#81)
* Upgrade Biome to Ultracite

* Remove package commands

* Update biome.jsonc

* Update biome.jsonc

* Initial fixes

* Update biome.jsonc

* Remaining fixes

* Update pnpm-lock.yaml

* Fix commands

* Update knip.json

* Merge Claude files

* Fix skipped test

* Misc fixes
2026-02-20 22:01:10 -08:00
John Pham 18ce1d070e Exclude actions from card fallback text
Action buttons (e.g. Cancel) were showing as [Cancel] in Slack
notification previews. The fallback text field powers notifications
and screen readers where buttons aren't actionable — strip them.
2026-02-12 10:45:04 -08:00
Malte Ubl 50f06527e7 Add discord adapter (#7)
* Implement a discord adapter

* Integration tests
2026-01-04 12:44:34 -08:00
Malte Ubl 0363a04dab More refactoring 2026-01-04 08:22:30 -08:00
Malte Ubl 82440f657a Test coverage 2026-01-04 08:05:01 -08:00
Malte Ubl fb7c41d3a5 Refactoring duplication 2026-01-03 20:32:35 -08:00