Back to skill

Security audit

Andara Meeting Minutes

Security checks for vulnerabilities and agentic risk

Overview

This meeting-minutes skill has a clear purpose, but it automatically writes potentially sensitive meeting content to PostgreSQL using unsafe SQL templates and limited user control.

Review this skill before installing. It should only be used with a dedicated least-privilege PostgreSQL account, parameterized or safely escaped inserts, and an explicit confirmation step before saving meeting content. Avoid using it for confidential meetings until storage, retention, and review controls are clear.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

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.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill stores meeting summaries, attendees, decisions, and action items in PostgreSQL but does not warn users that their input will be persisted. Meeting notes often contain sensitive internal or personal information, so silent storage creates privacy, consent, and data-governance risk, especially if activation is accidental.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger conditions are broad enough that ordinary conversation containing phrases like 'Meeting Notes' or 'save meeting' could activate the skill unintentionally. Because the skill performs persistent database writes, accidental activation could store sensitive meeting content without clear user intent or confirmation.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The instruction "Reply in German" imposes a specific language on all responses with no opt-in or alternative language option. This is a natural-language policy concern because it restricts output locale regardless of user preference or context.

Static analysis

No suspicious patterns detected.