T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:183
- Finding
- Automatic Transmission of Potentially Sensitive Organizational Data Without Human Approval<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 183–198, 242–255, and 270–285 **Vulnerability Type**: Unsafe approval-gate and outbound-message configuration **Risk Level**: Medium ### Vulnerable Code Snippets ```text **Gate:** Auto-send (low risk, read-only) **Output:** Slack message in #standup LOOP CONFIG: ───────────────────────────────────── Name: Weekly Standup Digest Trigger: cron("0 9 * * MON") Agent prompt: | Read all open Linear issues assigned to each team member. Read all open GitHub PRs by author. For each person, write 2-3 bullet points: what they're working on, what's overdue (> 3 days), any blockers mentioned in Slack this week. Format as a Slack message with @mentions. Gate: None (auto-send) Output: POST to #standup ``` ```text **Gate:** Auto-send if PR age > 48hr, Slack preview if 24-48hr **Output:** Slack message @mentioning overdue reviewers LOOP CONFIG: ───────────────────────────────────── Name: PR Review Reminder Trigger: cron("0 15 * * MON-FRI") Agent prompt: | Fetch all open PRs across [repos]. Find PRs with requested reviewers but no review in > 24 hours. Group by reviewer. For each reviewer, list their overdue PRs. Draft a friendly Slack message with PR links and ages. Gate: If any PR > 48hr → auto-send. If 24-48hr → preview + 30min timeout Output: #engineering Slack channel ``` ```text **Gate:** Auto-send (read-only financial data) **Output:** Slack message in #founders with sparkline context LOOP CONFIG: ───────────────────────────────────── Name: Weekly Revenue Snapshot Trigger: cron("0 17 * * FRI") Agent prompt: | Pull current MRR from Stripe. Compare to snapshot from 7 days ago (stored in memory). Calculate: MRR change ($, %), new customers, churned customers. Write 3-sentence narrative: what changed, why (if obvious), what to watch. Format for Slack with clear numbers. Gate: Auto-send Output: #founders Slack channel + update Notion metrics DB ``` ### Technical Analysis ...[truncated 2712 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require explicit human approval before sending any output containing personnel, customer, engineering, or financial information. 2. Classify the entire workflow rather than only source access. Any Slack post, email, webhook request, or database update must be treated as a write operation. 3. Replace automatic timeout approval with a fail-closed default such as `Skip` or `Hold for review`. 4. Display the complete payload and exact destination workspace, channel, database, or recipient during approval. 5. Enforce allowlists for Slack workspace IDs, channel IDs, Notion database IDs, repositories, and other destinations. 6. Verify that destination channels do not include external guests or unauthorized groups before sending. 7. Minimize and redact sensitive fields, particularly customer identities, revenue values, personnel details, private links, and quoted internal messages. 8. Treat source content as untrusted input. Delimit it from agent instructions and prevent issue titles, messages, or pull-request text from changing the workflow's actions or recipients. 9. Use least-privilege credentials with access only to required repositories, channels, Stripe fields, and Notion databases. 10. Add audit logging for source records, generated output, approver identity, destination, transmission time, and delivery result. 11. Permit unattended sending only after explicit data classification, destination validation, and successful manual trial runs with non-sensitive output. 12. Revise the affected templates so their gates are consistent with the document's stated requirement that sensitive data and external messages receive human review. ]]>
