oy-cli 0.10.3

Local AI coding CLI for inspecting, editing, running commands, and auditing repositories
Documentation
# Audit Issues

> Generated with [oy-cli]https://github.com/wagov-dtt/oy-cli: `OY_MODEL=opencode-go/deepseek-v4-pro oy audit` · 2026-05-09

## Findings summary

Current triage after review:

- **Fixed** `src/tools/network.rs::is_public_ip``webfetch` public-address classification now delegates to `ip_rfc` global-address semantics, with explicit denials for multicast and deprecated IPv6 site-local ranges.
- **Context / no active finding** `src/cli/ui/progress.rs`, `src/cli/ui/render.rs`, `src/tools/preview.rs::preview_bash` — output safety is split by sink: direct progress/error metadata escapes terminal controls, while raw content previews intentionally go through bat/terminal rendering to preserve ANSI output. Do not chase blanket escaping here unless a new direct, non-bat content sink is added.
- **Fixed** `src/tools/shell.rs::tool_bash` — shell child processes remove credential-like environment variables by default; remaining risk is the normal approved-shell trust boundary.

## Highest-ROI fix

The highest-ROI item from this review has been fixed. Next best follow-up is to keep the `webfetch` network boundary regression tests broad whenever URL resolution, redirects, or IP classification changes. The terminal/output item is mostly policy/tooling context now, and shell env filtering is already covered.

## Detailed findings

### Fixed: `webfetch` public-IP classification uses maintained global-address semantics

- **Status**: Fixed in `Unreleased``is_public_ip` now uses `ip_rfc::global` plus boundary-specific denials.
- **Category**: V5 Input Validation / SSRF boundary maintainability
- **Evidence**
  - `src/tools/network.rs::is_public_ip` delegates global-address classification to `ip_rfc::global`.
  - `src/tools/network.rs` keeps explicit public-fetch denials for multicast and deprecated IPv6 site-local ranges, because those are not valid public document-fetch targets for this boundary.
  - Regression tests cover private, shared, loopback, link-local, documentation, benchmarking, protocol-assignment, multicast, reserved, deprecated site-local, and representative public ranges.
- **Trust boundary / sink**
  Model-supplied `webfetch` URL / DNS result → public-only network policy → outbound HTTP request.
- **Residual risk**
  DNS rebinding and redirect behavior should remain covered when URL-fetch logic changes. The current client disables automatic redirects and validates all resolved addresses before the request.

---

### Context: Terminal/output escape safety is sink-specific, not a blanket finding

- **Status**: Context only — not tracked as an active finding unless a new direct terminal sink prints untrusted metadata/content without escaping or bat rendering.
- **Category**: V5 Validation (output encoding) / CWE-150
- **Current shape**
  - Direct progress/error metadata escapes ESC before writing to the terminal (`src/cli/ui/progress.rs:57-94`, `src/cli/ui.rs:157-160`). This covers model-supplied tool names, tool-call summaries, progress detail, and errors.
  - Content previews are intentionally different: markdown, diffs, code/text blocks, and verbose `bash` output are rendered through bat-backed paths where ANSI/terminal bytes are preserved for formatting (`src/cli/ui/render.rs:102-121`, `src/tools/preview.rs:505-559`, `src/tools/tests.rs:971-991`).
  - `docs/tool-safety.md` documents that `bash` stdout/stderr terminal/control sequences pass through raw for bat/terminal formatting.
- **Practical rule**
  Escape untrusted metadata immediately before direct `line`/`err_line` terminal sinks. Do not pre-escape raw content that is deliberately handed to bat/terminal rendering, or it will replace useful formatted output with visible escape glyphs.
- **When to reopen**
  Reopen only if untrusted content bypasses bat-backed rendering and is written directly to the terminal, or if a new metadata path reaches `line`/`err_line` without `escape_terminal_controls`.

---

### Fixed: Shell child processes remove credential-like environment variables

- **Status**: Fixed in `Unreleased``bash` child processes now remove credential-like environment variables before launch, with regression coverage and updated security docs.
- **Category**: V8 Data Protection / Configuration
- **Evidence**
  - `src/tools/shell.rs:48-57` calls `remove_sensitive_child_env` before spawning `bash`.
  - `src/tools/shell.rs:112-138` removes env vars whose names look credential-bearing (`API_KEY`, `SECRET`, `TOKEN`, `PASSWORD`, `AUTH`, etc.).
  - `src/tools/tests.rs:994` covers that secret-like env vars are removed while non-secret env vars remain visible.
- **Trust boundary / sink**
  Approved model/user shell command → child process environment → stdout/stderr/transcript.
- **Impact**
  The original easy leak path (`env` dumping provider tokens inherited from `oy`) is mitigated by default. Shell remains powerful and should stay ask/deny by mode; this is documented in `docs/tool-safety.md`.
- **Follow-up only if needed**
  Add an explicit allow/deny env configuration only if users need reproducible shell environments. Otherwise avoid adding another configuration surface.