T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:14
- Finding
- SQL Injection Through Unsafe Interpolation of Meeting Data## Vulnerability Details **File Location**: `SKILL.md`, lines 14–27 **Vulnerability Type**: SQL injection caused by direct interpolation of user-controlled data **Risk Level**: High ### Vulnerable Code ```bash psql "$DATABASE_URL" -c " INSERT INTO team_meetings (title, summary, attendees, meeting_date, created_at) VALUES ('TOPIC', 'SUMMARY', ARRAY['ATTENDEE1','ATTENDEE2'], NOW(), NOW()) RETURNING id;" ``` ```bash psql "$DATABASE_URL" -c " INSERT INTO meeting_action_items (meeting_id, assignee, description, due_date, status, created_at) VALUES (MEETING_ID, 'ASSIGNEE', 'TASK DESCRIPTION', 'DUE_DATE', 'pending', NOW());" ``` ### Technical Analysis The skill instructs the agent to extract the meeting topic, summary, attendees, action-item assignees, descriptions, and due dates from user-supplied text and place them directly into SQL statements passed to `psql -c`. No parameter binding, type enforcement, or SQL-literal escaping is specified. A malicious value containing a single quote and additional SQL syntax could terminate its intended literal and alter the command. The same weakness affects several fields, including `TOPIC`, `SUMMARY`, attendees, `ASSIGNEE`, `TASK DESCRIPTION`, and `DUE_DATE`. Improper handling of `MEETING_ID` could also permit SQL manipulation because it is inserted as an unquoted expression. Although the SQL is enclosed in a shell string, the primary confirmed issue is SQL injection into PostgreSQL rather than shell command injection. The achievable result depends on the privileges of the database role referenced by `DATABASE_URL`. ### Attack Path 1. An attacker submits meeting content containing a crafted value in a parsed field, such as the title, summary, attendee name, assignee, task description, or due date. 2. The agent extracts the malicious content and substitutes it into one of the documented SQL templates. 3. The agent invokes `psql "$DATABASE_URL" -c` with the resulting SQL text. 4. PostgreSQL interprets the injected syntax ...[truncated 1102 chars]
- Remediation
- ## Remediation Suggestions - Replace generated SQL strings with a trusted PostgreSQL client that supports prepared statements and bound parameters. - Bind every user-derived value, including titles, summaries, attendee names, assignees, descriptions, and due dates. - Treat `meeting_id` as a typed integer obtained directly from the preceding insert result; do not accept or interpolate it from user input. - Parse and validate due dates against an explicit date format before database insertion. - Pass attendees as a properly typed PostgreSQL array parameter rather than constructing an array literal manually. - If `psql` is unavoidable, use PostgreSQL-safe variable mechanisms with explicit literal handling instead of concatenating content into SQL. Prepared statements in an application client remain preferable. - Execute the skill under a dedicated least-privilege database role restricted to the required `INSERT` and necessary `SELECT` operations on `team_meetings` and `meeting_action_items`. - Deny schema modification, role administration, extension installation, and access to unrelated tables. - Add adversarial tests covering quotes, semicolons, SQL comments, Unicode edge cases, malformed dates, and oversized input. - Use transactions so that meeting and action-item creation succeeds or fails atomically, reducing inconsistent records when validation or insertion fails.
