If you discover a security vulnerability in ICM, please report it to the maintainers privately:
- Email: security@rtk-ai.app (or open 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
ICM parses untrusted input (tool output and transcripts via hooks, MCP tool arguments), runs SQL against a local database, can spawn a configured LLM CLI, and ships pre-built binaries. PRs from external contributors undergo enhanced review to protect against:
- Injection — SQL injection, or command injection via a spawned CLI
- Untrusted-input handling — malformed hook payloads / MCP arguments causing crashes, path traversal, or store poisoning
- Supply chain attacks — malicious or backdoored dependencies
- Backdoors & data leaks — logic bombs, exfiltration of the local memory store
- Release tampering — CI/CD or installer changes that alter published artifacts
Every PR runs the security scan job in ci.yml:
- Dependency audit (
cargo audit) — detects known CVEs - New-dependency alert — flags any dependency added to a
Cargo.tomlfor supply-chain review - Lints as gates —
cargo clippy --workspace --all-targets -- -D warningsandcargo fmt --checkmust pass
Maintainers can additionally run the /security-review skill on a branch for a deeper audit.
The following are high-risk and warrant extra scrutiny (and ideally a second reviewer):
crates/icm-store/src/**— all SQL and the SQLite schema/migrations (injection, corruption, data loss)crates/icm-mcp/src/tools.rs— MCP tool argument parsing and validation (untrusted client input)crates/icm-cli/src/summarizer.rs— spawns the configured LLM CLI (e.g.claude -p); must stay isolated and never build a shell string from untrusted input- Hook entry points in
crates/icm-cli/src/main.rs— parse untrusted tool output / transcripts from stdin; must never crash the calling agent
install.sh/install.ps1— installer logic and checksum verification (tampering, downgrade)Cargo.toml/Cargo.lock— dependency manifests (typosquatting, backdoored crates).github/workflows/*.yml— CI/CD and release pipelines (artifact tampering, secret exfiltration)
If your PR modifies any of these, expect a detailed manual review and possibly a slower merge.
| Pattern | Risk |
|---|---|
| String-formatted SQL instead of bound parameters | SQL injection |
Command::new("sh"/"bash") or shell strings from input |
Command injection |
.unwrap() / .expect() / panic! in non-test code |
DoS via panic on malformed input |
unsafe { |
Memory safety |
Unexpected reqwest:: / std::net:: on a hot/hook path |
Data exfiltration |
| Un-canonicalized paths from input | Path traversal |
SystemTime::now() > … conditionals, base64/hex blobs |
Logic bombs / obfuscation |
❌ DON'T
// SQL injection
conn.execute(&format!("SELECT * FROM memories WHERE topic = '{topic}'"), [])?;
// Panic on invalid input
let topic = args.get("topic").unwrap();
// Shell string from untrusted input
Command::new("sh").arg("-c").arg(format!("claude -p {prompt}")).spawn()?;✅ DO
// Bound parameters
conn.execute("SELECT * FROM memories WHERE topic = ?1", params![topic])?;
// Graceful error handling
let topic = get_str(args, "topic").ok_or_else(|| /* typed error */)?;
// Argv, no shell; keep the child isolated
Command::new("claude").args(["-p", "--model", model]).spawn()?;- Use
thiserrorfor typed library errors andanyhowwith.context()at the CLI boundary. - Never
.unwrap()/.expect()/panic!incrates/*/src(tests are fine). - Propagate with
?.
- Treat hook stdin, transcripts, and MCP arguments as untrusted: validate lengths, reject empties, cap sizes.
- Always bind SQL parameters; never string-format values into SQL.
- Canonicalize file paths before use; validate topic/identifier shapes.
New dependencies should meet:
- Downloads: a healthy count on crates.io (or a strong justification if low)
- Maintainer: verifiable GitHub profile and track record
- License: MIT or Apache-2.0 compatible
- Activity: maintained (recent commits)
- No typosquatting: verified against similar crate names
Red flags: brand-new crate with low downloads, anonymous maintainer, name suspiciously close to a popular crate, or a recent license change.
- Day 0: acknowledgment sent to reporter
- Day 7: severity and impact assessed
- Day 14: patch development begins
- Day 30: patch released + CVE filed (if applicable)
- Day 90: public disclosure (or earlier if the patch is deployed)
Critical vulnerabilities (remote code execution, data exfiltration, store corruption) may be fast-tracked.
cargo audit— CVE scanning (runs in CI)cargo clippy -- -D warnings— lints for unsafe/panic-prone patterns- GitHub Code Scanning (CodeQL) — static analysis on PRs
- Security issues: security@rtk-ai.app
- General questions: GitHub Discussions