Cherry-pick backport of #24474 and #24529 to `release/2.32`.
- #24474: fix(coderd): add frame-ancestors CSP directive to prevent
clickjacking
- #24529: fix(coderd): omit frame-ancestors CSP for embed routes
Both commits cherry-picked cleanly with no conflicts.
> Generated by Coder Agents
The Azure instance-identity authentication endpoint parsed the PKCS7
envelope and verified the certificate chain, but never verified the
PKCS7 signature itself. An attacker could forge a PKCS7 envelope with a
legitimate, publicly obtainable Azure certificate and arbitrary vmId
content to obtain any agent auth token.
Add verifyPKCS7Signature(), a custom PKCS7 signature verification that
handles Azure non-standard use of sha256WithRSAEncryption (OID
1.2.840.113549.1.1.11) as the DigestAlgorithm. The upstream
go.mozilla.org/pkcs7 library Verify() rejects this combination.
The verification checks:
1. Content digest matches the signed message-digest attribute
2. Signature over the authenticated attributes is valid
Tests added:
- TestValidate_TamperedContent: forges a PKCS7 with modified vmId,
confirms rejection
- TestValidate_UntrustedCertWithValidSignature: valid PKCS7 signature
with untrusted cert chain, confirms rejection
Co-authored-by: Jakub Domeracki <jakub@coder.com>
## Summary
Update the IronBank Dockerfile to use UBI9 (9.6) instead of UBI8 (8.7)
and explicitly remove `python3-urllib3` to address CVE-2026-44431.
### Changes
- **Dockerfile**: Upgrade base image from `ubi8-minimal:8.7` to
`ubi9-minimal:9.6`
- **Dockerfile**: Add `microdnf remove python3-urllib3` step after
package install
- **build_ironbank.sh**: Update local build args to match the new UBI9
base image
### Context
urllib3 1.26.5 is bundled in the UBI base image. Coder is a Go binary
and does not invoke Python at runtime, so this library is unused. The
removal step is a belt-and-suspenders safeguard in case UBI9 still ships
the package.
Fixes: ENT-52
> [!NOTE]
> This PR was generated by [Coder
Agents](https://coder.com/docs/agents).
Go 1.25.10 (released 2026-05-07) includes 11 security fixes for CVEs
affecting the go command, pack tool, html/template, net, net/http,
net/http/httputil, net/mail, and syscall packages.
Fixes IronBank v2.32.x Go stdlib CVE exposure by upgrading from Go
1.25.9 to 1.25.10.
Reference: https://groups.google.com/g/golang-dev/c/h6eZjndBMqQ
### Changed files
- `go.mod`: `go 1.25.9` to `go 1.25.10`
- `dogfood/coder/Dockerfile`: `GO_VERSION` and `GO_CHECKSUM`
- `.github/actions/setup-go/action.yaml`: default version
> Generated by Coder Agents
Cherry-pick of #24165 to `release/2.32`.
Moves the flaky pagination query key test from vitest to a Storybook
story. The test timed out in CI because `renderWithAuth` boots 12+ MSW
round-trips before the page mounts. The story uses decorators to
pre-seed the query cache, skipping the MSW waterfall entirely.
> 🤖 Generated by Coder Agent
Co-authored-by: Danielle Maywood <danielle@themaywoods.com>
Cherry-pick of go-git v5.19.0 bump to `release/2.32` to fix
CVE-2026-45022 (improper object parsing).
Original PR: https://github.com/coder/coder/pull/25124
Ref:
https://github.com/go-git/go-git/security/advisories/GHSA-389r-gv7p-r3rp
Supersedes #25226 (rebased on top of #25224).
> [!NOTE]
> This PR was authored by Coder Agents.
<details><summary>Context</summary>
The cherry-pick of the original commit (`c1c3b978`) had merge conflicts
in `go.mod`/`go.sum` due to dependency drift between `main` and
`release/2.32`. Instead, the bump was applied directly via `go get
github.com/go-git/go-git/v5@v5.19.0` followed by `go mod tidy`,
producing equivalent results.
Linear: ENT-24
</details>
Cherry-pick of #24650 and #24765 to release/2.32.
Adds a confirmation dialog before executing commands from the
`?command=` URL parameter in the terminal page. Canceling closes the
terminal window.
> 🤖 Generated by Coder Agents
---------
Co-authored-by: Seth Shelnutt <seth@coder.com>
Partial backport of #24369 to `release/2.32`.
Only the `CreateChat` fix in `coderd/x/chatd/chatd.go` applies here —
the second call site in `subagent.go`
(`createChildSubagentChatWithOptions`) doesn't exist on this branch
since the child-subagent-chat creation path was added after the branch
cut.
The fix hoists the `resolveDeploymentSystemPrompt` call out of the
`InTx` closure so the transaction doesn't hold one DB connection while
the helper tries to check out another via `p.db`. Under concurrent chat
creation load this pattern can cause pool starvation.
This is not urgent enough to warrant an immediate patch release — the
bug only manifests under high concurrent chat creation load. It should
be fine to ride along with the next scheduled 2.32.x patch.
## Summary
- backport `go-getter` 1.8.6 and its indirect dependency updates to
`release/2.32`
- backport the Go toolchain bump to 1.25.9
- include the latest local backport commits on
`sec/release-2.32-security`
## Testing
- not run
## Cherry-pick of #24187 onto `release/2.32`
This cherry-picks commit ad2415ede7 to
bring the `coder/tailscale` bump (`e956a95`, [PR
#113](https://github.com/coder/tailscale/pull/113)) onto the
`release/2.32` branch.
### Context
On Darwin, `RTM_MISS` route-socket messages (fired on every failed route
lookup) were not filtered by `netmon`, causing each one to be treated as
a `LinkChange`. When netcheck sends STUN probes to an IPv6 address with
no route, this creates a self-sustaining feedback loop: `RTM_MISS` →
`LinkChange` → `ReSTUN` → netcheck → v6 STUN probe → `RTM_MISS` → …
The loop drives DERP home-region flapping at ~70× baseline, which at
fleet scale saturates PostgreSQL's `NOTIFY` lock and causes coordinator
health-check timeouts.
The upstream fix adds a single `if msg.Type == unix.RTM_MISS { return
true }` check to `skipRouteMessage`, which is safe because `RTM_MISS` is
a lookup-path signal, not a table-mutation signal.
This issue has been reported since users updated to macOS 26.4.
Relates to ENG-2394
> 🤖 Generated by Coder Agents
Co-authored-by: Ethan <39577870+ethanndickson@users.noreply.github.com>
I said I wouldn't but the illustrious @jakehwll added a ResizeObserver
recently so imma do that too.
This makes `<ExpandableText>` determine if it should be expandable or
not on resize
The default `net.Dialer` in the Coder Connect path had no timeout,
falling back to the OS TCP timeout when the tunnel was broken but DNS
still resolved. Add a 5s dial timeout and 30s TCP keepalive.
Fixes#24006
When `coder ssh` connects to a workspace after laptop wake, DNS or the
control plane may be briefly unavailable. Previously this caused an
immediate failure, which VS Code Remote SSH classified as permanent
("Reload Window").
Wrap each network step (workspace resolution, template version fetch,
agent connection info, Coder Connect dial, tailnet dial) with
`retryWithInterval` so transient errors (DNS, connection refused, 5xx)
are retried individually. Non-retryable errors (auth, 404) and context
cancellation stop immediately. Data transfer is never retried.
RC tags are now created directly on `main`. The `release/X.Y` branch is
only cut when the actual release is ready. This eliminates the need to
cherry-pick hundreds of commits from main onto the release branch
between the first RC and the release.
## Workflow
```
main: ──●──●──●──●──●──●──●──●──●──
↑ ↑ ↑
rc.0 rc.1 cut release/2.34, tag v2.34.0
\
release/2.34: ──●── v2.34.1 (patch)
```
1. **RC:** On `main`, run `./scripts/release.sh`. The tool detects main
(or a detached HEAD reachable from main), prompts for the commit SHA to
tag, suggests the next RC version, and tags it.
2. **Release:** When the RC is blessed, create `release/X.Y` from `main`
(or the specific RC commit). Switch to that branch and run
`./scripts/release.sh`, which suggests `vX.Y.0`.
3. **Patch:** Cherry-pick fixes onto `release/X.Y` and run
`./scripts/release.sh` from that branch.
## Changes
### `scripts/releaser/release.go`
- Two modes based on branch:
- **`main` (or detached HEAD from main)** — RC tagging. Prompts for the
commit SHA to tag (defaults to HEAD). Always checks out the target
commit so the flow operates in detached HEAD. Suggests the next RC based
on existing RC tags.
- **`release/X.Y`** — Release/patch mode. Suggests `vX.Y.0` if the
latest tag is an RC, or the next patch otherwise.
- Detached HEAD support: if `git branch --show-current` is empty, checks
whether HEAD is an ancestor of `origin/main` and enters RC mode
automatically.
- Commit selection prompt in RC mode: shows current commit, lets the
user confirm or provide a different SHA.
- Warns if you try to tag a non-RC on main, or an RC on a release
branch.
- Skips open-PR check and branch sync check in RC mode (not useful on
main).
### `scripts/releaser/main.go`
- Updated help text.
### `.github/workflows/release.yaml`
- RC tags (`*-rc.*`): skip the release-branch validation (they live on
main).
- Non-RC tags: still require the corresponding `release/X.Y` branch.
### `docs/about/contributing/CONTRIBUTING.md`
- Rewrote the Releases section with the new workflow, release types
table, and ASCII diagram.
- Replaced the old "Creating a release" / "Creating a release (via
workflow dispatch)" subsections.
<details><summary>Decision log</summary>
### Why this approach?
Previously, cutting a release branch early for an RC meant
cherry-picking all of main's progress onto that branch before the actual
release — often hundreds of commits. This approach avoids that entirely:
RCs are just tagged snapshots of main, and the release branch only
exists once you need it for stabilization and backports.
### Files NOT changed
- **`scripts/release/publish.sh`** — `--rc` flag controls GitHub
prerelease marking (tag-level, not branch-level). `target_commitish`
already defaults to `main` when the tag isn't on a release branch.
- **`scripts/release/tag_version.sh`** — No RC-specific branch logic.
- **`scripts/releaser/version.go`** — Version parsing/comparison
unchanged.
- **`docs/install/releases/index.md`** — Public-facing docs describe RC
as a release channel with no branch-level detail.
</details>
> Generated by Coder Agents
This pull-request resolves an regression where the spread was overriding
the required styles from the `react-window` virtualised rows. This was
causing the scroll to act a little crazy.
Fixescoder/internal#1455
Three changes to eliminate the timing-sensitive flake in
`TestSubscribeRelayEstablishedMidStream`:
1. **Reduce `PendingChatAcquireInterval` from `time.Hour` to
`time.Second`.**
The primary trigger is still `signalWake()` from `SendMessage`, but a
short fallback poll ensures the worker picks up the pending chat
even under heavy CI goroutine scheduling contention.
2. **Increase context timeout from `WaitLong` (25s) to `WaitSuperLong`
(60s).**
The worker pipeline (model resolution, message loading, LLM call)
involves multiple DB round-trips that can be slow when PostgreSQL
is shared with many parallel test packages.
3. **Add a status-polling loop while waiting for the streaming
request.**
If the worker errors out during chat processing, the test now
fails immediately with the error status and message instead of
silently timing out.
> Generated by Coder Agents
Two fixes for the release script:
**1. Branch regex cleanup** — Simplified to only match `release/X.Y`.
Removed
support for `release/X.Y.Z` and `release/X.Y-rc.N` branch formats. RCs
are
now tagged from main (not from release branches), and the three-segment
`release/X.Y.Z` format will not be used going forward.
**2. Changelog range for first release on a new minor** — When no tags
match
the branch's major.minor, the commit range fell back to `HEAD` (entire
git
history, ~13k lines of changelog). Now computes `git merge-base` with
the
previous minor's release branch (e.g. `origin/release/2.32`) as the
changelog
starting point. This works even when that branch has no tags pushed yet.
Falls
back to the latest reachable tag from a previous minor if the branch
doesn't
exist.
Migrated LogLine and Logs components from Emotion CSS-in-JS to Tailwind
CSS classes.
- Replaced Emotion `css` prop and theme-based styling with Tailwind
utility classes in `LogLine` and `LogLinePrefix` components
- Converted CSS-in-JS styles object to conditional Tailwind classes
using the `cn` utility function
- Updated log level styling (error, debug, warn) to use Tailwind classes
with design token references
- Migrated the Logs container component styling from Emotion to Tailwind
classes
- Removed Emotion imports and theme dependencies
Refactored the tab overflow hook by renaming `useTabOverflowKebabMenu`
to `useKebabMenu` and removing the configurable `alwaysVisibleTabsCount`
parameter.
- Renamed `useTabOverflowKebabMenu` to `useKebabMenu` and moved it to a
new file
- Removed the `alwaysVisibleTabsCount` parameter and hardcoded it to 1
tab as `ALWAYS_VISIBLE_TABS_COUNT`
- Removed the `utils/index.ts` export file for the Tabs component
- Updated the import in `AgentRow.tsx` to use the new hook name and
removed the `alwaysVisibleTabsCount` prop
- Refactored the internal logic to use a more functional approach with
`reduce` instead of imperative loops
- Added better performance optimizations to prevent unnecessary
re-renders
This PR improves the agent log download functionality by replacing the
single download button with a comprehensive dropdown menu system.
- Replaced single download button with a dropdown menu offering multiple
download options
- Added ability to download all logs or individual log sources
separately
- Updated download button to show chevron icon indicating dropdown
functionality
- Enhanced download options with appropriate icons for each log source
<img width="370" height="305" alt="image"
src="https://github.com/user-attachments/assets/ddf025f5-f936-499a-9165-6e81b62d6860"
/>
Moves the `charm.land/fantasy` replace directive from
`github.com/kylecarbs/fantasy` to `github.com/coder/fantasy`, pointing
at the same `cj/go1.25` branch and commit (`112927d9b6d8`).
> Generated by Coder Agents
Update queries as prep work for user secrets API development:
- Switch all lookups and mutations from ID-based to user_id + name
- Split list query into metadata-only (for API responses) and
with-values (for provisioner/agent)
- Add partial update support using CASE WHEN pattern for write-only
value fields
- Include value_key_id in create for dbcrypt encryption support
- Update dbauthz wrappers and remove stale methods from dbmetrics
Previously, after creating a provider config in the agents provider
editor, the Save changes button stayed enabled for the lifetime of the
mounted form. The form kept the pre-create local baseline, so the
freshly-saved values still looked dirty.
Key `ProviderForm` by provider config identity so React remounts the
form when a config is created and re-establishes the pristine state from
the saved provider values.
## Summary
Replaces N per-chat heartbeat goroutines with a single centralized
heartbeat loop that issues one `UPDATE` per 30s interval for all running
chats on a worker.
## Problem
Each running chat spawned a dedicated goroutine that issued an
individual `UPDATE chats SET heartbeat_at = NOW() WHERE id = $1 AND
worker_id = $2 AND status = 'running'` query every 30 seconds. At 10,000
concurrent chats this produces **~333 DB queries/second** just for
heartbeats, plus ~333 `ActivityBumpWorkspace` CTE queries/second from
`trackWorkspaceUsage`.
## Solution
New `UpdateChatHeartbeats` (plural) SQL query replaces the old singular
`UpdateChatHeartbeat`:
```sql
UPDATE chats
SET heartbeat_at = @now::timestamptz
WHERE worker_id = @worker_id::uuid
AND status = 'running'::chat_status
RETURNING id;
```
A single `heartbeatLoop` goroutine on the `Server`:
1. Ticks every `chatHeartbeatInterval` (30s)
2. Issues one batch UPDATE for all registered chats
3. Detects stolen/completed chats via set-difference (equivalent of old
`rows == 0`)
4. Calls `trackWorkspaceUsage` for surviving chats
`processChat` registers an entry in the heartbeat registry instead of
spawning a goroutine.
## Impact
| Metric | Before (10K chats) | After (10K chats) |
|---|---|---|
| Heartbeat queries/sec | ~333 | ~0.03 (1 per 30s per replica) |
| Heartbeat goroutines | 10,000 | 1 |
| Self-interrupt detection | Per-chat `rows==0` | Batch set-difference |
---
> 🤖 Generated by Coder Agents
<details><summary>Implementation notes</summary>
- Uses `@now` parameter instead of `NOW()` so tests with `quartz.Mock`
can control timestamps.
- `heartbeatEntry` stores `context.CancelCauseFunc` + workspace state
for the centralized loop.
- `recoverStaleChats` is unaffected — it reads `heartbeat_at` which is
still updated.
- The old singular `UpdateChatHeartbeat` is removed entirely.
- `dbauthz` wrapper uses system-level `rbac.ResourceChat` authorization
(same pattern as `AcquireChats`).
</details>
Audit and connection log pages were timing out due to expensive COUNT(*)
queries over large tables. This commit adds opt-in count capping: requests can
return a `count_cap` field signaling that the count was truncated at a threshold,
avoiding full table scans that caused page timeouts.
Text-cast UUID comparisons in regosql-generated authorization queries
also contributed to the slowdown by preventing index usage for connection
and audit log queries. These now emit native UUID operators.
Frontend changes handle the capped state in usePaginatedQuery and
PaginationWidget, optionally displaying a capped count in the pagination
UI (e.g. "Showing 2,076 to 2,100 of 2,000+ logs")
Related to:
https://linear.app/codercom/issue/PLAT-31/connectionaudit-log-performance-issue