Security hardening: tighten cross-origin policies#595
Merged
Conversation
35ee931 to
ca1cb60
Compare
heyitsaamir
approved these changes
May 26, 2026
ca1cb60 to
c6a2ab3
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens cross-origin behavior in the SDK by removing permissive default CORS headers for served tab assets and by restricting DevTools WebSocket upgrades to same-origin requests.
Changes:
- Removed wildcard
cors()middleware fromExpressAdapter.serveStatic()so static assets no longer emitAccess-Control-Allow-Origin: *. - Added a
verifyClientgate to the DevToolsWebSocketServerto reject upgrades whoseOrigindoes not match the request host (and reject missing Origin).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/dev/src/plugin.ts | Adds origin verification for DevTools WebSocket upgrades. |
| packages/apps/src/http/express-adapter.ts | Drops default wildcard CORS headers when serving static tab assets and updates method documentation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
lilyydu
approved these changes
May 27, 2026
c6a2ab3 to
f672f4f
Compare
Locks in the absence of `Access-Control-Allow-Origin` (and friends) on responses from `serveStatic()` so a future regression that reintroduces wildcard CORS would fail this test.
b5ddf6e to
e24abda
Compare
rido-min
approved these changes
May 27, 2026
7 tasks
corinagum
added a commit
that referenced
this pull request
May 27, 2026
## Summary
Brings `origin/main` into `release` for the **2.0.12** release. **No
carve-outs this time** — Quoted Replies is included.
`version.json`: `2.0.12-preview.{height}` → `2.0.12`.
Aligns with teams.py 2.0.12 (PR #442 already on PyPI / pending publish).
## What's in this release (delta from 2.0.11)
**Features**
- Quoted Replies + new quotes features — previously held back via the
2.0.11 carve-out (#576)
- SuggestedActionSubmitActivity for `suggestedAction/submit` invoke
(#591)
- Default targeted replies for targeted inbound messages (#592)
- Filter colliding keys before `Object.assign` in `ActivityContext`
(#596)
- Prompt Preview support (#536)
- A2A sample (#584)
- AI/MCPClient (#572)
- Allow passing custom HTTP client via `AppOptions`-equivalent
- Reactions API marked GA (#575), Rename `ReactionClient.remove()` →
`delete()` (#567)
**Security & fixes**
- Security hardening: tighten cross-origin policies (#595)
- Lock JsonWebToken trust-boundary contract (#586)
- `fix(deps)`: npm audit fix — clears all high-severity advisories
(#599)
- `fix(apps)`: log inbound activities at info, warn on missing
Authorization (#568)
- `fix`: App user-agent merging (#573)
- `fix`: Add null checks in `local-memory.ts` to prevent role crash
(#438)
- `fix`: `@microsoft/teams.client` import error in webpack 5 (#566)
- Switch to named imports without subpaths (#561)
**Deprecations / package changes**
- Deprecate `DevtoolsPlugin` in favor of Microsoft 365 Agents Playground
(#593)
- Remove in-repo Teams CLI package (#580) — moved to
`teams-sdk/packages/cli`
- Deprecate AI Libraries (#588)
- Correct imports + return types in misc. packages (#589)
**Dependency bumps**
- turbo 2.8.11 → 2.9.14 (#587)
- qs 6.15.0 → 6.15.2 (#594)
- hono 4.12.14 → 4.12.16 (#562)
- npm audit fix bundle (#599): axios 1.13.5 → 1.16.1, fast-uri 3.1.0 →
3.1.2, ws 8.19.0 → 8.21.0, @azure/msal-node hoisted 5.2.2, uuid 11.1.0 →
11.1.1, @azure/identity 4.13.0 → 4.13.1, express-rate-limit, ip-address,
brace-expansion, etc.
## Quoted Replies inclusion notes
- Teams client rendering is in-sync with the wire format as of
2026-05-06.
- APX QR rollout completed: Public 2026-04-10, GCCH/DoD/Gallatin
2026-04-14.
- No SDK-side carve-outs needed; this matches the teams.py 2.0.12 (PR
#442) decision.
## Branch structure note
`prep-release/2.0.12` is reset to `origin/main` + a one-line
`version.json` bump. Diff against `release` (this PR) shows the full
delta from 2.0.11. We deliberately did not use a 2-parent merge commit —
the auto-merge tried to interleave non-overlapping hunks from main's QR
additions with release's QR carve-outs in `activity.ts`, producing a
semantically broken file. Reset-to-main + version bump is the clean way
to express "release should equal main."
## Test plan
- [x] `npm install` clean (post-audit-fix lockfile)
- [x] `npm run build` — 33/33 targets clean
- [x] `npm test` — 14/14 task targets, 279+ tests pass
- [x] E2E echo bot smoke test against `cg-test-bot-py` via canary ABS —
done on `cg/audit-deps-ts` (now merged); covers axios + msal-node code
paths
- [ ] Pipeline Build + Test stages green on `release` after merge
- [ ] Publish pipeline run with **Public** → ESRP → npm
`@microsoft/teams.*@2.0.12`
- [ ] Smoke install: `npm view @microsoft/teams.apps@2.0.12` after
publish
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two narrow tightenings of cross-origin policy in the TS SDK.
Changes
1.
ExpressAdapter.serveStatic— drop wildcardcors()middlewareTab static content was served with a wildcard
Access-Control-Allow-Originheader. Teams loads tab content inside an iframe, governed by CSPframe-ancestors, not by CORS. The wildcard served no documented use case and risked surprising any future endpoint mounted under the same path.Callers that legitimately need cross-origin reads of the served assets can layer their own CORS middleware at the consuming route.
2.
DevtoolsPluginWebSocket — require same-origin upgradesThe DevTools WebSocket server previously accepted upgrades from any origin (the
wslibrary's default when noverifyClientis provided). The DevTools UI is always loaded from the same origin as the bot server, so legitimate clients send an Origin header matching the request Host. AverifyClientcallback now rejects upgrades whose Origin does not match the request Host; absent Origin is also rejected.What this does not change
HttpPlugin(already marked deprecated in-code) still uses a globalcors(); that path will be removed with the plugin.Validation
npm run build,npm run test,npm run lintclean.examples/tabsample: tab index, JS, and CSS still served with HTTP 200 and noAccess-Control-Allow-Originheader. Cross-origin probe returns the asset with noAccess-Control-Allow-*headers, so browsers would block cross-origin fetch as intended.examples/echowith devtools enabled: same-origin WebSocket upgrade succeeds (101); cross-origin and missing-Origin probes return 401 from thewslibrary.