Files
rtk-ai__rtk/SECURITY.md
Florian BRUNIAUX f447a3d5b1 feat: rtk rewrite — single source of truth for LLM hook rewrites (#241)
* feat: add `rtk rewrite` command — single source of truth for hook rewrites

Implements `rtk rewrite <cmd>` as the canonical rewrite engine for all
LLM hook integrations (Claude Code, Gemini CLI, future tools).

- Add `rewrite_prefixes` field to `RtkRule` in discover/registry.rs
- Add public `rewrite_command()` with compound command support (&&, ||, ;, |)
- Add `rewrite_segment()`, `rewrite_compound()`, `strip_word_prefix()` helpers
- Handle already-rtk commands (exit 0, identical output)
- Handle unsupported/ignored commands (exit 1, no output)
- Add 20 unit tests covering all branches and edge cases
- Create `src/rewrite_cmd.rs` thin CLI wrapper
- Register `Commands::Rewrite` in main.rs
- Simplify `.claude/hooks/rtk-rewrite.sh` from 357 → 60 lines

Hooks no longer need duplicate mapping logic — a single
`REWRITTEN=$(rtk rewrite "$CMD") || exit 0` handles everything.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix version references and module count for 0.22.2

- README.md, CLAUDE.md, ARCHITECTURE.md: 0.20.1 → 0.22.2
- ARCHITECTURE.md: module count 48 → 51 (added rewrite_cmd + 2 from master)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* ci: update hook coverage check to verify registry (not hook script)

Since PR #241, the hook delegates to `rtk rewrite` — command mappings
live in src/discover/registry.rs, not the bash hook script.

Update the "Verify hook coverage" CI step to:
- Check that the hook calls `rtk rewrite` (new architecture)
- Check that registry.rs has rewrite_prefixes for all Python/Go commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: support single `&` background operator in compound rewrites

Per feedback from @xDelph: AI agents increasingly use `cmd1 & cmd2`
for parallel execution. This commit adds support alongside existing
`&&`, `||`, `;`, and `|` operators.

Changes:
- rewrite_compound: add match arm for single `&` (after `&&` check)
- rewrite_command: add `" & "` to has_compound detection
- init: show "installed/updated" vs "already up to date" so users
  know whether rtk init changed the hook on re-run

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: add Python/Go commands to rewrite registry

Add `ruff`, `pytest`, `pip`, `go`, and `golangci-lint` to both
PATTERNS and RULES in registry.rs so the CI coverage check passes
and `rtk rewrite` correctly identifies these commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update version reference to 0.23.0 in README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update version reference to 0.23.0 in CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update version and module count to 0.23.0/52 in ARCHITECTURE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: address P0 review feedback on rtk-rewrite PR

P0.1 - Replace 218-line bash hook with 58-line thin delegating hook.
  All rewrite logic now lives exclusively in `rtk rewrite` (Rust registry).
  `rtk init` installs the thin hook via include_str!.

P0.2 - Fix `head -20 file` crash at runtime.
  Generic prefix replacement produced `rtk read -20 file` (invalid clap args).
  Now translates `head -N file` → `rtk read file --max-lines N` and skips
  unsupported head flags (e.g. -c) by returning exit 1.

P0.3 - Add version guard in hook for rtk < 0.23.0.
  Prints a warning to stderr instead of silently doing nothing.

Also adds missing registry entries vs old hook:
  - gh release, cargo install
  - docker run/exec/build, kubectl describe/apply
  - tree, diff

474 tests pass, 0 clippy warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* style: cargo fmt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(discover): extract rules/patterns into rules.rs

Per aeppling review: registry.rs was too large (~1500 lines).
Extract all static data into src/discover/rules.rs:
- RtkRule struct (with pub fields)
- PATTERNS const array
- RULES const array
- IGNORED_PREFIXES and IGNORED_EXACT const arrays

registry.rs now contains only logic + tests.
rules.rs is the single place to add a new command mapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update version reference to 0.24.0 in README

* docs: update version references to 0.24.0 in CLAUDE.md and ARCHITECTURE.md

* fix(discover): add aws and psql to rewrite registry

rtk aws and rtk psql modules exist since PR #216 but were missing
from the registry rules — rewrite was silently skipping them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(discover): exhaustive regression tests for rewrite registry

Cover all command categories added in PR #241 and missing from
the previous test suite:
- aws / psql (PR #216 modules, gap detected during non-reg run)
- Python: ruff, pytest, python -m pytest, pip, uv pip
- Go: go test/build/vet, golangci-lint
- JS/TS: vitest, pnpm vitest, prisma, prettier, pnpm list
- Compound operators: || and ; rewrites, 4-segment chains,
  mixed supported/unsupported segments, all-unsupported → None
- sudo prefix rewrite, env var prefix rewrite
- find with native flags
- Registry invariants: PATTERNS/RULES aligned, all rules valid,
  all patterns are valid regex

Before: 559 tests. After: 607 tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(migration): document breaking change + detect outdated hook in rtk config

CHANGELOG [Unreleased]:
- Migration required: rtk init --global needed after upgrade
- Documents upgrade path and explains no immediate breakage

rtk init --show / rtk config now detects old hook (inline if-else)
vs new thin delegator (rtk rewrite) and prints actionable warning:

  ⚠️  Hook: ~/.claude/hooks/rtk-rewrite.sh (outdated — inline logic, not thin delegator)
     → Run `rtk init --global` to upgrade to the single source of truth hook

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update hook references for thin delegator (0.24.0)

- ARCHITECTURE.md: fix hook description (shell script → thin delegator)
- INSTALL.md: add upgrade path for old hook users (pre-0.24 breaking change)
- SECURITY.md: add registry.rs + hook files to Tier 1 critical files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(arch): fix module count 52→55, add aws/psql/rewrite to module map

Adds aws_cmd, psql_cmd (PR #216) and rewrite_cmd (this PR) to the
Complete Module Map table. Updates total from 52 to 55 to match main.rs.

Fixes CI validate-docs.sh module count mismatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* ci: fix hook coverage check to search rules.rs instead of registry.rs

After the PR #241 refactor, rewrite_prefixes constants moved from
registry.rs to rules.rs. Update grep to search the whole discover/
directory so it finds them in the right file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:20:01 +01:00

218 lines
7.3 KiB
Markdown

# Security Policy
## Reporting a Vulnerability
If you discover a security vulnerability in RTK, please report it to the maintainers privately:
- **Email**: security@rtk-ai.dev (or create a private security advisory on GitHub)
- **Response time**: We aim to acknowledge reports within 48 hours
- **Disclosure**: We follow responsible disclosure practices (90-day embargo)
**Please do NOT:**
- Open public GitHub issues for security vulnerabilities
- Disclose vulnerabilities on social media or forums before we've had a chance to address them
---
## Security Review Process for Pull Requests
RTK is a CLI tool that executes shell commands and handles user input. PRs from external contributors undergo enhanced security review to protect against:
- **Shell injection** (command execution vulnerabilities)
- **Supply chain attacks** (malicious dependencies)
- **Backdoors** (logic bombs, exfiltration code)
- **Data leaks** (tracking.db exposure, telemetry abuse)
---
## Automated Security Checks
Every PR triggers our [`security-check.yml`](.github/workflows/security-check.yml) workflow:
1. **Dependency audit** (`cargo audit`) - Detects known CVEs
2. **Critical files alert** - Flags modifications to high-risk files
3. **Dangerous pattern scan** - Regex-based detection of:
- Shell execution (`Command::new("sh")`)
- Environment manipulation (`.env("LD_PRELOAD")`)
- Network operations (`reqwest::`, `std::net::`)
- Unsafe code blocks
- Panic-inducing patterns (`.unwrap()` in production)
4. **Clippy security lints** - Enforces Rust best practices
Results are posted in the PR's GitHub Actions summary.
---
## Critical Files Requiring Enhanced Review
The following files are considered **high-risk** and trigger mandatory 2-reviewer approval:
### Tier 1: Shell Execution & System Interaction
- **`src/runner.rs`** - Shell command execution engine (primary injection vector)
- **`src/summary.rs`** - Command output aggregation (data exfiltration risk)
- **`src/tracking.rs`** - SQLite database operations (privacy/telemetry concerns)
- **`src/discover/registry.rs`** - Rewrite logic for all commands (command injection risk via rewrite rules)
- **`hooks/rtk-rewrite.sh`** / **`.claude/hooks/rtk-rewrite.sh`** - Thin delegator hook (executes in Claude Code context, intercepts all commands)
### Tier 2: Input Validation
- **`src/pnpm_cmd.rs`** - Package name validation (prevents injection via malicious names)
- **`src/container.rs`** - Docker/container operations (privilege escalation risk)
### Tier 3: Supply Chain & CI/CD
- **`Cargo.toml`** - Dependency manifest (typosquatting, backdoored crates)
- **`.github/workflows/*.yml`** - CI/CD pipelines (release tampering, secret exfiltration)
**If your PR modifies ANY of these files**, expect:
- Detailed manual security review
- Request for clarification on design choices
- Potentially slower merge timeline
---
## Review Workflow
### For External Contributors
1. **Submit PR** → Automated `security-check.yml` runs
2. **Review automated results** → Fix any flagged issues
3. **Manual review** → Maintainer performs comprehensive security audit
4. **Approval** → Merge (or request for changes)
### For Maintainers
Use the comprehensive security review process:
```bash
# If Claude Code available, run the dedicated skill:
/rtk-pr-security <PR_NUMBER>
# Manual review (without Claude):
gh pr view <PR_NUMBER>
gh pr diff <PR_NUMBER> > /tmp/pr.diff
bash scripts/detect-dangerous-patterns.sh /tmp/pr.diff
```
**Review checklist:**
- [ ] No critical files modified OR changes justified + reviewed by 2 maintainers
- [ ] No dangerous patterns OR patterns explained + safe
- [ ] No new dependencies OR deps audited on crates.io (downloads, maintainer, license)
- [ ] PR description matches actual code changes (intent vs reality)
- [ ] No logic bombs (time-based triggers, conditional backdoors)
- [ ] Code quality acceptable (no unexplained complexity spikes)
---
## Dangerous Patterns We Check For
| Pattern | Risk | Example |
|---------|------|---------|
| `Command::new("sh")` | Shell injection | Spawns shell with user input |
| `.env("LD_PRELOAD")` | Library hijacking | Preloads malicious shared libraries |
| `reqwest::`, `std::net::` | Data exfiltration | Unexpected network operations |
| `unsafe {` | Memory safety | Bypasses Rust's guarantees |
| `.unwrap()` in `src/` | DoS via panic | Crashes on invalid input |
| `SystemTime::now() > ...` | Logic bombs | Delayed malicious behavior |
| Base64/hex strings | Obfuscation | Hides malicious URLs/commands |
See [Dangerous Patterns Reference](https://github.com/rtk-ai/rtk/wiki/Dangerous-Patterns) for exploitation examples.
---
## Dependency Security
New dependencies added to `Cargo.toml` must meet these criteria:
- **Downloads**: >10,000 on crates.io (or strong justification if lower)
- **Maintainer**: Verified GitHub profile + track record of other crates
- **License**: MIT or Apache-2.0 compatible
- **Activity**: Recent commits (within 6 months)
- **No typosquatting**: Manual verification against similar crate names
**Red flags:**
- Brand new crate (<1 month old) with low downloads
- Anonymous maintainer with no GitHub history
- Crate name suspiciously similar to popular crate (e.g., `serid` vs `serde`)
- License change in recent versions
---
## Security Best Practices for Contributors
### Avoid These Anti-Patterns
**❌ DON'T:**
```rust
// Shell injection risk
let user_input = get_arg();
Command::new("sh").arg("-c").arg(format!("echo {}", user_input)).output();
// Panic on invalid input
let path = std::env::args().nth(1).unwrap();
// Hardcoded secrets
const API_KEY: &str = "sk_live_1234567890abcdef";
```
**✅ DO:**
```rust
// No shell, direct binary execution
let user_input = get_arg();
Command::new("echo").arg(user_input).output();
// Graceful error handling
let path = std::env::args().nth(1).context("Missing path argument")?;
// Env vars or config files for secrets
let api_key = std::env::var("API_KEY").context("API_KEY not set")?;
```
### Error Handling Guidelines
- Use `anyhow::Result<T>` with `.context()` for all error propagation
- NEVER use `.unwrap()` in `src/` (tests are OK)
- Prefer `.expect("descriptive message")` over `.unwrap()` if unavoidable
- Use `?` operator instead of `unwrap()` for propagation
### Input Validation
- Validate all user input before passing to `Command`
- Use allowlists for command flags (not denylists)
- Canonicalize file paths to prevent traversal attacks
- Sanitize package names with strict regex patterns
---
## Disclosure Timeline
When vulnerabilities are reported:
1. **Day 0**: Acknowledgment sent to reporter
2. **Day 7**: Maintainers assess severity and impact
3. **Day 14**: Patch development begins
4. **Day 30**: Patch released + CVE filed (if applicable)
5. **Day 90**: Public disclosure (or earlier if patch is deployed)
Critical vulnerabilities (remote code execution, data exfiltration) may be fast-tracked.
---
## Security Tooling
- **`cargo audit`** - Automated CVE scanning (runs in CI)
- **`cargo deny`** - License compliance + banned dependencies
- **`cargo clippy`** - Lints for unsafe patterns
- **GitHub Dependabot** - Automated dependency updates
- **GitHub Code Scanning** - Static analysis via CodeQL (planned)
---
## Contact
- **Security issues**: security@rtk-ai.dev
- **General questions**: https://github.com/rtk-ai/rtk/discussions
- **Maintainers**: @FlorianBruniaux (active fork maintainer)
---
**Last updated**: 2026-03-05