diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 79ae60e..9f9d56d 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -14,3 +14,8 @@ **Vulnerability:** A script created temporary files at predictable paths (`/tmp/wiki_claude_{session_id}.txt`) allowing potential local attackers to execute a symlink attack or view sensitive session content. **Learning:** Hardcoded predictable temporary file paths, especially those derived from predictable elements like session_ids, expose local file operations to race conditions. **Prevention:** Always use secure temporary file creation APIs like Python's `tempfile.NamedTemporaryFile` or Bash's `mktemp`, and pass the dynamically generated file path between components rather than assuming predictable names. + +## 2025-02-27 - SQL Injection in Daily Digest script +**Vulnerability:** SQL injection vulnerabilities were present in `bin/wiki-daily-digest` where externally supplied variables (`$session_id` and `$date`) were directly interpolated into `sqlite3` string queries without proper sanitization. +**Learning:** Internal tools that process externally populated databases (like SQLite) are still susceptible to SQL injection if string interpolation is used instead of parameterization or strict sanitization. +**Prevention:** Always use safe parameter expansion (e.g. `${var//\'/\'\'}`) when interpolating Bash variables into SQLite queries to correctly escape single quotes, even in scripts not directly facing the public network. diff --git a/bin/wiki-daily-digest b/bin/wiki-daily-digest index 24fbb7d..aa149f9 100755 --- a/bin/wiki-daily-digest +++ b/bin/wiki-daily-digest @@ -139,7 +139,7 @@ _extract_session_content() { SELECT json_extract(p.data, '$.text') FROM part p JOIN message m ON p.message_id = m.id -WHERE m.session_id = '$session_id' +WHERE m.session_id = '${session_id//\'/\'\'}' AND json_extract(m.data, '$.role') = 'assistant' AND json_extract(p.data, '$.type') = 'text' AND length(json_extract(p.data, '$.text')) > 20 @@ -162,7 +162,7 @@ SELECT s.created_at, s.updated_at FROM sessions s -WHERE date(s.updated_at) = '$date' +WHERE date(s.updated_at) = '${date//\'/\'\'}' ORDER BY s.created_at ASC;" 2>/dev/null } @@ -175,7 +175,7 @@ _extract_goose_content() { content="$(sqlite3 "$GOOSE_DB" " SELECT substr(m.content_json, 1, 2000) FROM messages m -WHERE m.session_id = '$session_id' +WHERE m.session_id = '${session_id//\'/\'\'}' AND m.role = 'assistant' ORDER BY m.created_at ASC;" 2>/dev/null | python3 -c " import sys, json