T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/siyuan.py:58
- Finding
- SQL Injection in Search and Notebook Filtering Commands## Vulnerability Details **File Location**: `scripts/siyuan.py`, lines 58-79 **Vulnerability Type**: SQL injection through unescaped CLI-controlled values **Risk Level**: Medium ### Vulnerable Code ```python def search(keyword, limit=20): results = post("/api/query/sql", { "stmt": f"SELECT id, hpath, content FROM blocks WHERE content LIKE '%{keyword}%' LIMIT {limit}" }) print(json.dumps(results, indent=2, ensure_ascii=False)) return results def search_titles(keyword, limit=20): results = post("/api/query/sql", { "stmt": f"SELECT id, hpath, title FROM blocks WHERE type = 'd' AND title LIKE '%{keyword}%' LIMIT {limit}" }) print(json.dumps(results, indent=2, ensure_ascii=False)) return results def list_docs(notebook): results = post("/api/query/sql", { "stmt": f"SELECT id, title, hpath FROM blocks WHERE notebook = '{notebook}' AND type = 'd'" }) print(json.dumps(results, indent=2, ensure_ascii=False)) return results ``` ### Technical Analysis The `keyword` and `notebook` values originate from command-line arguments and are inserted directly into SQL string literals through Python f-strings. The implementation performs no parameter binding, escaping, format validation, or rejection of SQL control characters. Although the Skill intentionally offers a separate raw `sql` command, these three commands are presented as constrained search and listing operations. Injection allows an argument supplied to a constrained command to change the structure and semantics of the generated SQL statement. For example, a crafted keyword containing a quote, a condition such as `OR 1=1`, a SQL comment marker, and a newline can terminate the intended `LIKE` expression and neutralize the remaining query text. A compatible `UNION SELECT` expression could potentially retrieve fields outside the columns ordinarily exposed by a given command. ### Attack P ...[truncated 1319 chars]
- Remediation
- ## Remediation Suggestions 1. Use parameterized SQL statements if the SiYuan API supports query parameters. 2. If binding is unavailable, avoid dynamically generated SQL and use a dedicated SiYuan search endpoint where possible. 3. Otherwise, escape SQL string literals using a well-tested implementation rather than ad hoc replacement. 4. Validate notebook identifiers against SiYuan's documented identifier format and reject all nonconforming values. 5. Validate `limit` as an integer and enforce a conservative range before incorporating it into a query. 6. Reject unexpected control characters, statement delimiters, and comment syntax as defense in depth. 7. Keep intentionally unrestricted SQL execution isolated in the explicitly named `sql` command and require clear user confirmation before running statements that can expose broad note data. 8. Add tests using quotes, comment markers, newlines, Boolean conditions, and `UNION` expressions to verify that user input cannot alter query structure.
