Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Security Review

BSecurity

Comprehensive security review for Termote. Use when reviewing PRs, auditing code, or before releases. Covers auth bypass, request guards (Host/Origin/Content-Type), terminal WebSocket stream, child-process lifetime, command/argument injection (tmux, psmux, herdr), the Go CLI (install layout, saved config, update, service registration, process kill) and container setup.

57 stars
0 votes
0 copies
0 views
Added 10/1/2026
developmentrustgoshellbashreactdockerawsgitapibackend

Works with

terminalcliapi

Security Analysis

B75/100
criticalAccesses sensitive system or user directories

Pro scans all 2 files and shows the line behind each finding

Scanned 10/1/2026

$npx -y skills add lamngockhuong/termote --skill security-review --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Security Review?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Security Review
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/lamngockhuong-security-review/badge)](https://www.skillsdirectory.com/skills/lamngockhuong-security-review)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: security-review
description: Comprehensive security review for Termote. Use when reviewing PRs, auditing code, or before releases. Covers auth bypass, request guards (Host/Origin/Content-Type), terminal WebSocket stream, child-process lifetime, command/argument injection (tmux, psmux, herdr), the Go CLI (install layout, saved config, update, service registration, process kill) and container setup.
allowed-tools: Read, Grep, Glob, Bash(git diff*, git log*, git show*), Agent
argument-hint: "[--full | --diff-only] [--focus auth|api|stream|herdr|cli|docker|shell]"
---

# Termote Security Review

Review Termote for security vulnerabilities, tailored to its 1.0 architecture: one Go binary (`termote`) that is both the server (PWA + `/api/mux/*` + terminal WebSocket stream + auth) and the CLI (`termote start`/`container up`/`update`/...), a React PWA, an online installer (`scripts/install.sh`/`install.ps1`) plus a checkout-only dev shim (`scripts/termote.sh`/`termote.ps1`), and a Docker image. There is no `install` command, no ttyd and no `/terminal/` iframe any more: the server runs the terminal itself on a PTY (Unix) or ConPTY (Windows) and streams it over `/api/mux/stream`. Backends: tmux (psmux on Windows) and herdr (Unix only, via its socket and CLI).

## Arguments

- `--full`: Scan entire codebase (default if no unstaged changes)
- `--diff-only`: Only review changed files
- `--focus <area>`: Focus on specific area (auth, api, stream, herdr, cli, docker, shell)

Current arguments: $ARGUMENTS

## Step 1: Determine Scope

```
If --diff-only or there are uncommitted/staged changes:
  Run git diff + git diff --cached to get changed files
If --full or clean tree:
  Scan all key files
If --focus specified:
  Filter to relevant files only
```

For a release review, diff against the previous tag:
`git diff <prev-tag>..HEAD -- server pwa/src scripts Dockerfile entrypoint.sh docker-compose.yml`.

## Step 2: Review by Area

Launch parallel review agents for each relevant area. Pass the diff or file contents to each agent.

### Area: Auth & Request Guards (`server/serve.go`, `server/guard.go`)

Check against [checklist.md](checklist.md#auth--access-control):

- Basic auth on ALL routes except the PWA public paths (manifest, `sw.js`, `workbox-*.js`)
- When a saved config exists (`server/serve_config.go`), `termote serve` reads it and ignores
  every `TERMOTE_*` variable; only without one (container, manual run) does
  `validateConfig`/the environment apply — empty password without `TERMOTE_NO_AUTH=true`
  refuses to start either way
- herdr with auth off needs `TERMOTE_HERDR_ALLOW_NO_AUTH=true` (`--allow-herdr-no-auth`)
- Host allowlist (`hostGuard`, `TERMOTE_ALLOWED_HOSTS`) on every request (DNS rebinding); no wildcard
- Cross-site writes rejected (`writeGuard`): `Sec-Fetch-Site`, `Origin` in the allowlist, JSON-only `Content-Type` on every non-GET `/api/` method
- Rate limiting on auth failures; constant-time password comparison
- Session cookie: `HttpOnly`, `SameSite=Strict`, `Secure` when HTTPS; bounded store
- No credentials in logs, error responses or child-process environments

### Area: API & Command Injection (`server/mux.go`, `server/mux_tmux.go`, `server/mux_herdr.go`)

Check against [checklist.md](checklist.md#api--command-injection):

- tmux targets validated with `validTmuxID` (no ':' → no other session, no leading '-' → no flag injection) and qualified server-side
- herdr IDs match `herdrWorkspaceIDRe` / `herdrTabIDRe` / `herdrPaneIDRe` and must exist in the current snapshot
- No user input reaches `exec.Command` without validation; herdr socket calls go through `json.Marshal`
- Body size limit (8KB) and keys length limit (4096) on writes
- Method enforcement on every handler; wrong method → JSON 405
- Error responses generic (`mux command failed`); only `inputError` text is echoed

### Area: Terminal Stream (`server/stream.go`, `server/pty_*.go`, `server/herdr_stream.go`)

Check against [checklist.md](checklist.md#terminal-stream):

- `/api/mux/stream` requires auth + Host allowlist + `Sec-Fetch-Site`/`Origin` check + single-use 30s token
- Size limits: `cols`/`rows` clamped to [1, 500], 64 KiB client messages, at most 8 streams, 32 live tokens
- Keepalive and write timeouts; no URL (token) logging
- Closing a stream, SIGTERM and a hard kill of the server all end the whole child process tree (process group / `Pdeathsig` / Job Object); orphan reaping never matches unrelated processes

### Area: Herdr Backend (`server/herdr_rpc.go`, `server/mux_herdr.go`, `server/herdr_stream.go`)

Check against [checklist.md](checklist.md#herdr-backend):

- Socket JSON-RPC: one request per connection, request < 1 MiB, reply bounded, deadlines from ctx
- `herdr terminal session observe <pane>` argv built from a validated pane ID and integer sizes only
- NDJSON frames decoded defensively (bad lines skipped, never executed or echoed)
- Input queue bounded per pane; writes ordered

### Area: Go CLI (`server/cli*.go`, `server/install_layout.go`, `server/tailscale.go`)

Check against [checklist.md](checklist.md#go-cli):

- Config file 0600 (Unix) / owner-only ACL (Windows), atomic write; password AES-256-CBC with an
  HMAC keyed by a random per-install `secret` file (0600) on Unix, DPAPI on Windows
- The password never ends up in the systemd unit, launchd plist, Scheduled Task or any process
  command line (container: passed as `-e NAME` from the CLI's own environment, not a file)
- `update`: version regex, HTTPS download, sha256 check (mandatory), tar extraction refuses
  escaping paths, symlinks and backslashes; the versioned install layout (`install_layout.go`)
  switches `current` atomically and never partially removes a version
- External commands (`tailscale serve` — never with `sudo`, `off` never `reset` — `podman`/`docker run`,
  `powershell -EncodedCommand`, `netsh`) get only validated values as separate argv entries
- Process matching before kill: exact command line / image path, PID file cross-checked; never kill unrelated processes

### Area: Docker & Container (`Dockerfile`, `entrypoint.sh`, `docker-compose.yml`)

Check against [checklist.md](checklist.md#docker--container):

- Base image pinned by digest; `tini` as PID 1
- No world-writable sensitive files (/etc/passwd, /etc/group)
- No secrets in image layers; minimal installed packages
- Port published on 127.0.0.1 unless `--lan`; password and allowed hosts passed as `-e NAME`
  values from the CLI's own environment, never an env file or a command-line argument
- Runs as `--user <uid>:<gid>` (rootless podman: `--userns=keep-id`; rootless Docker: no
  `--user`); the workspace is mounted with `--mount`, not `-v`
- Sensitive host dirs excluded from mounts (.ssh, .gnupg, .aws)

### Area: Shell Scripts (`scripts/install.sh`, `scripts/install.ps1`, `scripts/termote.sh`, `scripts/termote.ps1`)

Check against [checklist.md](checklist.md#shell-scripts):

- `install.sh`/`install.ps1` (release installers): version validated, HTTPS download, `.sha256`
  checksum verification mandatory (no way to skip it), never start the server themselves
- `termote.sh`/`termote.ps1` (checkout-only dev shims): only resolve/build the `termote-dev`
  binary and `exec` it; no logic that handles secrets
- Variables quoted; no `eval` or sourcing of the saved config file

## Step 3: Report

Output a structured report:

```
## Security Review Report

### Summary
- Scope: [full / diff-only / focused]
- Files reviewed: N
- Issues: X critical, Y high, Z medium, W low

### Critical / High (must fix)
| # | Area | File:Line | Issue | Exploit path | Recommendation |

### Medium (should fix)
| # | Area | File:Line | Issue | Exploit path | Recommendation |

### Low / Informational
| # | Area | File:Line | Issue | Recommendation |

### Passed Checks
- [list of areas that passed cleanly]
```

Known, accepted decisions (do not re-raise as findings):

- `requestIsHTTPS` trusts `X-Forwarded-Proto` from any source (only affects that client's own cookie)
- Container running as root is out of scope (rejected hardening scope) — note `container up`
  otherwise runs as `--user <uid>:<gid>` (rootless podman: `--userns=keep-id`; rootless Docker:
  no `--user`)

## Step 4: Fix (if requested)

If the user asks to fix issues, apply changes directly. For each fix:

1. Edit the source file
2. Run `go build` to verify (for Go changes)
3. Run `go test` to verify tests pass

Attribution

lamngockhuonglamngockhuong
View sourceSee grades on GitHubMore from lamngockhuong →
SSkills Directory ProSkills Directory

Get any skill into Claude in one click.

Download any skill as a ZIP for Claude.ai, Claude Desktop, or .claude/skills. $9/mo.

See Pro

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills Directory ProSkills Directory

Get any skill into Claude in one click.

Download any skill as a ZIP for Claude.ai, Claude Desktop, or .claude/skills. $9/mo.

See Pro

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

286712 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Writing Plans

Use when you have a spec or requirements for a multi-step task, before touching code

2927051 votes
View all in development →