winx-code-agent 0.2.346

Remote-first Rust MCP runtime with Streamable HTTP, durable PTYs, and guarded agent tools
Documentation
# Security Policy

## Supported Versions

Security fixes are provided for the current `0.2.x` line.

| Version   | Supported |
|-----------|-----------|
| `0.2.x`   | Yes       |
| `< 0.2.0` | No        |

## Reporting a Vulnerability

Do not report security vulnerabilities through public issues, discussions, or pull requests.

Preferred reporting path:

1. Use GitHub private vulnerability reporting for this repository, if available.
2. If private reporting is unavailable, contact the maintainer privately through GitHub.

Include:

- affected version or commit;
- operating system and MCP client;
- exact reproduction steps;
- expected and actual impact;
- proof of concept, logs, or screenshots when useful;
- whether the issue involves command execution, path traversal, symlinks, persistence, or file edits.

We aim to acknowledge reports within 48 hours and provide an assessment within 7 days. Fix timing depends on severity and complexity.

## Threat Model

Winx supports local stdio and a primary network-reachable Streamable HTTP deployment. An authenticated MCP client can
ask it to:

- read files;
- write or edit files;
- execute shell commands;
- interact with foreground and background PTY sessions;
- persist and reload shell state;
- save context snapshots.

This is powerful by design. Only connect Winx to MCP clients and agent workflows you trust.

## Operational Guidance

- Run Winx in the smallest workspace that is practical for the task.
- Prefer `architect` mode for read-oriented work.
- Use `code_writer` mode with explicit `allowed_globs` and `allowed_commands` for constrained write sessions.
- Review tool calls from untrusted or experimental agents.
- Keep secrets out of project files that agents can read.
- Avoid running Winx with elevated privileges.
- Treat shell access as equivalent to local user access.
- Keep HTTP on loopback; use `--allow-non-loopback` only as an explicit, reviewed exception.
- Store HTTP tokens in regular chmod-600 files, use one principal per remote client, and rotate leaked credentials.
- Prefer bearer headers. Query-string tokens are opt-in because they leak into URL logs and history.
- Keep HTTP concurrency/rate limits and the daemon guardian quota/tiered idle TTL enabled.
- Keep the default `--session-affinity workspace` for stateless clients. Use `thread` only when the client can retain stable
  IDs and operators accept responsibility for abandoned-session cleanup.
- Review redacted configuration with `winx-code-agent doctor`.
- Review durable sessions with `winx-code-agent list`; use `prune`, `kill <thread_id>`, or `kill --all` when cleanup is needed.
- Follow the complete [Streamable HTTP deployment guide]docs/streamable-http.md before exposing remote access.

## Filesystem Safety

Winx validates workspace paths and tracks read-before-edit state. Security-sensitive changes should preserve:

- workspace path validation (default-on; widened only by the operator-set `WINX_ALLOW_PATHS`, read once at
  startup so no tool argument or agent-run command can relax it at runtime - `WINX_ALLOW_PATHS=/` disables
  containment for the file tools and should be treated as such);
- symlink and path traversal protections;
- read-before-edit enforcement;
- hash/range based overwrite tracking;
- mode checks for file writes and edits.

## Shell Safety

`BashCommand` runs local commands. Security-sensitive changes should preserve:

- thread-id validation;
- one foreground command at a time;
- mode checks for allowed commands;
- background command identifiers;
- clear behavior for interrupts and input forwarding.

The optional `verify_command` on edit tools is shell execution: it uses the same command/mode checks as `BashCommand`,
is rejected before writing when its syntax or mode policy is invalid, and requires `BashCommand` in an HTTP principal's
tool policy. A verification failure does not roll back an already-committed edit and must be reported as such.

## HTTP Authentication and Isolation

HTTP bearer tokens must be at least 32 bytes unless the operator explicitly enables weak local-development tokens.
`--principal-config` assigns each client an independent identity: external thread IDs and MCP Task IDs are scoped before
they reach the shared service registry, preventing accidental or deliberate cross-principal session reuse.

Remote first calls default to one durable session per `(principal, canonical workspace)`. This prevents stateless clients
and cosmetic model-generated ID changes from exhausting the guardian quota. It also means parallel conversations using
the same principal in the same repository intentionally share one shell, cwd, foreground-command lock, and output stream.
Use separate principals or `--session-affinity conversation` when that sharing is unacceptable. Conversation affinity
prefers `Mcp-Session-Id`, accepts an edge-provided `X-Winx-Conversation-Id`, and falls back to the first-call `thread_id`;
the identity is hashed and never returned or logged raw. A gateway must strip untrusted copies before injecting its header.
`--session-affinity thread` remains the caller-owned option and requires stable IDs plus explicit cleanup.

Optional `WINX_USAGE_LOG` telemetry is filtered to metadata-only `winx::usage` events. It includes hashed request/session
correlation, tool/action, principal, scoped thread, client/protocol, outcome, duration, and response size. It must never
include command text, file contents, tool output, bearer tokens, or raw conversation identities; regression tests enforce
that boundary. On Unix each initial/rotated file is opened with `O_NOFOLLOW` and mode `0600`, existing broader modes are
reduced to `0600`, and newly created log directories use `0700`. Landlock is applied before the non-blocking writer thread
is created, so the logger cannot escape the sandbox domain; a sandboxed deployment must explicitly allow the chosen log
path. Workspace paths and timing remain sensitive operational metadata despite these protections.

Authentication is not authorization inside a shell. A principal permitted to use Winx still receives the capabilities of
the selected Winx mode. Use `architect`, a constrained `code_writer`, containers, and OS-level isolation where needed.
Per-principal tool policies narrow MCP discovery and reject dispatch outside the configured catalog, but a catalog that
contains `BashCommand` is still shell access and is not an operating-system sandbox. Winx does not currently provide
built-in TLS, OAuth/OIDC, or mTLS; those controls belong at a reviewed network edge when required. OAuth/OIDC well-known
probes are intentionally ordinary `404 Not Found` responses; only `/mcp` is protected by Winx bearer authentication.

## Guardian Lifecycle Safety

Protocol `1.3` guardians own their creation, activity, and last-command clocks. Protocol `1.4` additionally transports a
runtime-owned `BashCommandState` independently of terminal output. MCP orchestration and Tasks consume only that typed
state; child output and background-command summaries are never parsed for process status. Older guardians lacking
`typed_action_result` fail closed for execution and must be removed and initialized again instead of enabling a
text-parser fallback. Files beside guardian sockets
are a control-plane cache, not the authoritative clock, because runtime directories may be tmpfs and recreated after
reboot. Compatibility logic for protocol `1.2` distinguishes passive metadata reconstruction from real adapter activity
and uses socket age for never-used legacy guardians.

The default retention policy is deliberately tiered:

- never-used guardians: 30 minutes (`WINX_UNUSED_SESSION_IDLE_TTL_SECS`);
- guardians that ran a command: 24 hours (`WINX_SESSION_IDLE_TTL_SECS`);
- active foreground or background commands: never removed by idle pruning.

Under hard quota pressure, Winx may reclaim only the oldest inactive guardian that has never run a command. Used or active
shells are not sacrificed to admit a new session. `prune --idle-seconds 0` is the explicit operator override for removing
all idle sessions while still preserving active commands.

## Dependency and Release Security

Dependency and workflow changes should pass:

```bash
cargo fmt --all -- --check
cargo check --all-features --locked
cargo clippy --all-targets --all-features --locked -- -D warnings
cargo test --all-features --locked
cargo deny --all-features check
cargo audit --deny warnings
cargo package --locked
```

CI additionally checks the declared MSRV, real PTY/TUI behavior, fuzz-target compilation, pinned GitHub Actions, and the
release workflow contract. Releases include SHA-256 manifests, a CycloneDX SBOM, and GitHub artifact attestations.

## Disclosure

We follow coordinated disclosure. Public details should be shared after a fix or mitigation is available, unless immediate disclosure is necessary to protect users.

Last updated: August 2026