mirror of
https://github.com/rtk-ai/rtk.git
synced 2026-09-19 07:33:17 +08:00
f447a3d5b1
* 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>
218 lines
7.3 KiB
Markdown
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
|