fix(container-exec): harden with security fixes, validation, and test coverage (#577)

* fix(container-exec): harden with security fixes, validation, and test coverage

- Enforce admin role at WebSocket upgrade for container exec sessions
- Validate container is running before creating exec
- Fix bash-to-sh fallback (move .start() inside try/catch)
- Register container-exec as a capability for fleet visibility
- Add standard and diagnostic logging for exec lifecycle
- Fix false Admiral license claim in API docs
- Fix design system violations in BashExecModal (hardcoded colors)
- Remove duplicate legacy xterm dependencies
- Add 18-test suite covering auth, validation, fallback, and cleanup

* fix(container-exec): use correct Duplex type for exec stream

The stream variable was typed as NodeJS.ReadWriteStream, which lacks
.destroy(). Dockerode's Exec.start() returns stream.Duplex per its
type definitions. This caused tsc to fail while Vitest (which skips
full type checking) passed.
This commit is contained in:
Anso
2026-04-14 08:23:05 -04:00
committed by GitHub
parent 5908898395
commit c4ff58347e
11 changed files with 487 additions and 60 deletions
+1 -1
View File
@@ -203,5 +203,5 @@ ws.send(JSON.stringify({ type: "resize", cols: 120, rows: 40 }));
</CodeGroup>
<Warning>
Container exec requires a Sencho **Admiral Team** license and is blocked for API tokens and node proxy tokens.
Container exec requires an **admin** role. API tokens with `read-only` or `deploy-only` scope are blocked, as are node proxy tokens.
</Warning>
+25 -2
View File
@@ -64,12 +64,35 @@ The terminal supports search (find text within the log output) and export (downl
### Container terminal (exec)
The terminal modal from the container action buttons gives you an interactive bash shell inside a running container, equivalent to `docker exec -it <id> bash`. It uses a full xterm.js emulator with color support and tab completion.
The terminal modal from the container action buttons gives you an interactive bash shell inside a running container, equivalent to `docker exec -it <id> bash`. It uses a full terminal emulator with colour support, tab completion, and automatic resizing when you resize the browser window.
#### Access requirements
- **Admin role required.** Only admin users see the terminal button in the container actions. Non-admin users cannot open a shell session.
- **Container must be running.** The button is disabled for stopped containers, and the backend will reject exec attempts against non-running containers.
- **API token restrictions.** API tokens with `read-only` or `deploy-only` scope cannot open exec sessions. Only `full-admin` API tokens are permitted.
<Frame>
<img src="/images/editor/container-exec-modal.png" alt="Container exec modal showing a connected bash session with a root shell prompt" />
</Frame>
#### Shell selection
Sencho tries `/bin/bash` first. If bash is not available inside the container, it automatically falls back to `/bin/sh`. This happens transparently; no user action is needed.
<Warning>
The container terminal requires the container to have `bash` (or `sh`) installed. Minimal images (e.g. Alpine-based) may need `sh` instead.
The container terminal requires the container to have `bash` or `sh` installed. Minimal base images (e.g. `scratch`, `distroless`) that ship no shell will not work with container exec.
</Warning>
#### Troubleshooting
| Symptom | Cause | Resolution |
|---------|-------|------------|
| "Container is not running" error | The container stopped between clicking the button and the exec starting | Start the container and try again |
| "Failed to start shell" error | The container image has no shell binary (`/bin/bash` or `/bin/sh`) | Use an image that includes a shell, or install one in your Dockerfile |
| Terminal connects but immediately shows "Session ended" | The shell process inside the container exited immediately | Check the container logs for errors; the container's entrypoint may be overriding the shell |
| Terminal is unresponsive | WebSocket connection dropped silently | Close the modal and reopen it to establish a new session |
## Log viewer
The log viewer (opened from the container action buttons) streams output from a single container in real-time using Server-Sent Events. Logs auto-scroll to the bottom as new lines arrive. Close the modal to stop the stream.
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB