Back to skill

Security audit

OpenTIL

Security checks for vulnerabilities and agentic risk

Overview

This OpenTIL skill is coherent, but it needs review because it can proactively turn conversation content into published entries after a broad yes and uses persistent account tokens with write/delete authority.

Install only if you are comfortable giving the skill an OpenTIL token that can publish, edit, and delete your entries. Review generated content before agreeing to capture, avoid storing broad tokens in a shell profile when possible, and be cautious with the proactive TIL suggestion flow because a generic yes can send conversation-derived content to OpenTIL.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:237
Finding

Proactive Output Injection Funnels Conversation Content into an External Publishing Workflow

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:237-273
Vulnerability Type: Proactive instruction hijacking and service funnel
Risk Level: High

Vulnerable Code

markdown
## Auto-Detection

When working alongside a user, proactively detect moments worth capturing as TIL entries.

### When to Suggest

Suggest when the conversation produces a genuine "aha" moment — something surprising, non-obvious, or worth remembering.

### Rate Limiting

1. **Once per session** — after suggesting once (accepted or declined), never suggest again
2. **Natural pauses only** — suggest at resolution points or task boundaries, never mid-problem-solving
3. **Respect rejection** — if declined, move on without persuasion

### Suggestion Format

Append at the end of your normal response. Never interrupt workflow.

**Template:**

💡 TIL: [concise title of the insight] Tags: [tag1, tag2] · Capture? (yes/no)

text

### Capture Flow

Auto-detected TILs bypass the extract flow. The suggestion itself is the candidate.

1. User replies `yes` / `y` / `ok` / `sure` → agent generates full entry (title, body, tags, lang) from the suggested insight → follows Execution Flow (POST or save locally)
2. User replies `no` / ignores / continues other topic → move on, do not ask again

The same behavior is reinforced in references/auto-detection.md:95-145:

markdown
## Suggestion Format

Append the suggestion at the end of your normal response. Never interrupt the workflow with a standalone suggestion message.

**Template:**

💡 TIL: [concise title of the insight] Tags: [tag1, tag2] · Capture? (yes/no)

text

## Single Confirmation Flow

Agent: [normal response content]

text
   💡 TIL: [concise title]
      Tags: [tags] · Capture? (yes/no)

User: yes / y / ok / sure

Agent: [Generates full entry: title, body, tags, lang] [POST to API or save locally] [Show result message]

text

The suggestion itself is the candidate. When the user says yes, the a
...[truncated 2995 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove default proactive conversation monitoring and the instruction to append capture prompts to normal responses.
  2. Restrict all capture behavior to explicit user invocations such as /til, /til <content>, or a dedicated command that clearly names the material to capture.
  3. If proactive detection is retained, make it a separately enabled, informed opt-in setting that is disabled by default and clearly indicates that accepted material may be uploaded externally.
  4. Require an unambiguous confirmation phrase such as publish this TIL to OpenTIL; do not interpret generic replies such as yes, ok, or sure as publication consent.
  5. Show the complete generated title, body, summary, tags, visibility, destination host, and account identity before any network transmission.
  6. Default conversation-derived entries to local or remote drafts rather than immediate public publication.
  7. Require a second explicit confirmation before publishing publicly, distinct from consent to generate or save a draft.
  8. Preserve the existing desensitization rules, but add a mandatory sensitive-data review for secrets, internal URLs, personal data, proprietary identifiers, and private conversation context before upload.
  9. Provide a clear configuration control to disable auto-detection permanently and document its state in the Skill's setup section.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (24)

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The skill requires access to a personal access token with read, write, and delete scopes and directs the agent to resolve and use that credential automatically. Any skill that reads and uses bearer tokens for account actions materially expands the blast radius of prompt injection, accidental misuse, or compromise because the token enables publishing and deletion of user content.

Content

Scanner excerpt · SKILL.md (reported line 22)May include surrounding context.

md
## Setup

1. Go to https://opentil.ai/dashboard/settings/tokens and create a Personal Access Token with `read:entries`, `write:entries`, and `delete:entries` scopes
2. Copy the token (starts with `til_`)
3. Set the environment variable:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

The skill exposes a destructive DELETE /entries/:id capability backed by a token that may have delete scope. Although it includes a typed confirmation, this still creates a real risk surface for prompt injection, user confusion, or suffix-based ID resolution mistakes leading to irreversible deletion of entries.

Content

Scanner excerpt · SKILL.md (reported line 337)May include surrounding context.

md
- Fetch the entry, show title and status
- Double-confirm: "This cannot be undone. Type 'delete' to confirm."
- On confirmation, `DELETE /entries/:id`

### `/til status`

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

The skill exposes a permanently destructive DELETE /entries/:id capability with no documented safety interlocks such as confirmation, dry-run preview, recycle bin behavior, or stronger verification of target selection. In an agent-driven CLI, parameter mistakes, prompt injection from surrounding content, or ambiguous entry resolution could trigger irreversible deletion of user content.

Content

Scanner excerpt · references/api.md (reported line 158)May include surrounding context.

md
Returns the full EntrySerializer response with updated fields.

## DELETE /entries/:id -- Delete Entry

Permanently delete an entry. Requires `delete:entries` scope.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/api.md (reported line 375)May include surrounding context.

POST /oauth/device/token

Poll for an access token after the user authorizes.

text
POST /api/v1/oauth/device/token

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/management.md (reported line 37)May include surrounding context.

md
| `publish` | `write:entries` | `POST /entries/:id/publish` |
| `unpublish` | `write:entries` | `POST /entries/:id/unpublish` |
| `edit` | `read:entries` + `write:entries` | `GET /entries/:id` + `PATCH /entries/:id` |
| `delete` | `delete:entries` | `DELETE /entries/:id` |
| `status` | `read:entries` (optional) | `GET /site` |
| `sync` | `write:entries` | `POST /entries` (per draft) |
| `tags` | `read:entries` | `GET /tags?sort=popular` |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/management.md (reported line 264)May include surrounding context.

md
| `publish` | `write:entries` | `POST /entries/:id/publish` |
| `unpublish` | `write:entries` | `POST /entries/:id/unpublish` |
| `edit` | `read:entries` + `write:entries` | `GET /entries/:id` + `PATCH /entries/:id` |
| `delete` | `delete:entries` | `DELETE /entries/:id` |
| `status` | `read:entries` (optional) | `GET /site` |
| `sync` | `write:entries` | `POST /entries` (per draft) |
| `tags` | `read:entries` | `GET /tags?sort=popular` |

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The instructions tell users to persist OPENTIL_TOKEN in their shell environment, which commonly causes long-lived credential exposure through shell profiles, process environments, crash dumps, and inherited subprocess environments. Persistent bearer tokens increase the chance of reuse by unrelated tools or accidental disclosure.

Content

Scanner excerpt · SKILL.md (reported line 22)May include surrounding context.

md
## Setup

1. Go to https://opentil.ai/dashboard/settings/tokens and create a Personal Access Token with `read:entries`, `write:entries`, and `delete:entries` scopes
2. Copy the token (starts with `til_`)
3. Set the environment variable:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill instructs the agent to read and silently migrate credentials from ~/.til/credentials, including legacy plaintext tokens, without any explicit warning about secret handling, file permissions, or the sensitivity of writing tokens back to disk. This increases the risk of insecure local secret storage and accidental exposure if the file is world-readable, synced, or logged.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The skill is explicitly designed to transmit user-generated content and bearer tokens to an external service at opentil.ai. Even though this is expected functionality, it is still a real data exfiltration boundary: conversation-derived content, metadata, and authentication material leave the local environment and may expose sensitive information if desensitization fails or the user misunderstands the publish behavior.

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

Create and publish an entry:

bash
curl -X POST "https://opentil.ai/api/v1/entries" \
  -H "Authorization: Bearer $OPENTIL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
92% confidence
Finding

The skill states 'No confirmation needed' for /til <content> and the execution flow defaults to immediate publishing when a token is present. This enables autonomous external publication based on a single command invocation, which is risky because the agent reformulates raw input into a fuller post and may publish sensitive or inaccurate content without a final review step.

Content

Scanner excerpt · SKILL.md (reported line 196)May include surrounding context.

md
6. Detect language -> set `lang` (`en`, `zh-CN`, `zh-TW`, `ja`, `ko`, `es`, `fr`, `de`, `pt-BR`, `pt`, `ru`, `ar`, `bs`, `da`, `nb`, `pl`, `th`, `tr`, `it`)
7. Follow Execution Flow above (check token -> POST or save locally)

No confirmation needed -- the user explicitly asked to capture. Execute directly.

## `/til` -- Extract from Conversation

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 442)May include surrounding context.

md
Every TIL entry must follow these rules:

- **Self-contained**: The reader must understand the entry without any conversation context. Never write "as we discussed", "the above error", "this project's config", etc.
- **Desensitized**: Remove project names, company details, colleague names, internal URLs, and proprietary business logic. Generalize specifics: "our User model" -> "a model", "the production server" -> "a production environment", "the Acme payment service" -> "a payment gateway".
- **Universally valuable**: Write to StackOverflow-answer standards. A stranger searching for this topic should find the entry immediately useful. Content only useful to the author belongs in private notes, not TIL.
- **Factual tone**: State facts, show examples, explain why. Avoid first-person narrative ("I was debugging...", "I discovered..."). Exception: brief situational context is fine ("When upgrading Rails from 7.2 to 8.0...").

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The manual setup section again instructs users to add OPENTIL_TOKEN to their shell profile, reinforcing insecure long-term secret persistence. Recommending profile-based storage normalizes broad credential exposure across future sessions and subprocesses.

Content

Scanner excerpt · SKILL.md (reported line 600)May include surrounding context.

text
Or set up manually:
  1. Visit https://opentil.ai/dashboard/settings/tokens
  2. Create a token (select read + write + delete scopes)
  3. Add to shell profile:
     export OPENTIL_TOKEN="til_..."

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The API reference explicitly directs the skill to persist bearer tokens in a local credentials file, but it does not include any user-facing warning about storing a reusable secret on disk or guidance on risks such as local compromise, backups, or multi-user systems. While file permissions are addressed, silent persistence of long-lived tokens still expands the attack surface and can expose the account if the host is compromised.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

Persisting the selected profile and associated bearer token creates session persistence on disk, which can outlive the immediate task and be abused by anyone who gains access to the local account, filesystem, backups, or developer tooling. In a CLI skill context, this is more sensitive because the automation may run unattended and repeatedly reuse the token without renewed user awareness.

Content

Scanner excerpt · references/api.md (reported line 460)May include surrounding context.

md
2. `GET /site` with the token to fetch `username`
   - On success: use `username` as profile name, populate `nickname` and `site_url`
   - On failure (401/network): use `default` as profile name, leave `nickname` and `site_url` empty
3. Write back as YAML with the single profile set as `active`
4. Preserve file permissions (`chmod 600`)

### File Permissions

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/api.md (reported line 465)May include surrounding context.

md
### File Permissions

Always set `~/.til/credentials` to `chmod 600` (owner read/write only) after any write operation. Create `~/.til/` directory with `chmod 700` if it doesn't exist.

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · references/local-drafts.md (reported line 63)May include surrounding context.

Step 1: Detect Pending Drafts

text
List files in ~/.til/drafts/ matching *.md

If no files exist, skip sync entirely.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The reference explicitly instructs the skill to display the last 4 characters of the resolved token in /til status. Although partial masking is common, this still discloses credential-derived information to the terminal/logs and can aid token fingerprinting, screenshot leakage, or correlation across sessions, especially in shared terminals or recorded CLI output.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/management.md (reported line 366)May include surrounding context.

md
- Invalid (401) → continue to new authorization
   - If no token → continue to new authorization

2. **Create device code**
   - `POST /api/v1/oauth/device/code` with `{ "scopes": ["read", "write"] }`
   - Response: `{ device_code, user_code, verification_uri, expires_in, interval }`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/api.md (reported line 461)May include surrounding context.

md
- Determine profile name: use the API-returned `username` as the default profile name
     - If a profile with the same name already exists and its token differs, append a numeric suffix (`hong-2`, `hong-3`, etc.)
     - If re-authorizing the current active profile (same nickname), update the existing profile's token in-place
   - Write `~/.til/credentials` in YAML format (`chmod 600`):
     - Set `active` to the new profile name
     - Add/update the profile under `profiles` with `token`, `nickname`, `site_url`, `host`
   - Display:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/api.md (reported line 465)May include surrounding context.

md
- Determine profile name: use the API-returned `username` as the default profile name
     - If a profile with the same name already exists and its token differs, append a numeric suffix (`hong-2`, `hong-3`, etc.)
     - If re-authorizing the current active profile (same nickname), update the existing profile's token in-place
   - Write `~/.til/credentials` in YAML format (`chmod 600`):
     - Set `active` to the new profile name
     - Add/update the profile under `profiles` with `token`, `nickname`, `site_url`, `host`
   - Display:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/management.md (reported line 399)May include surrounding context.

md
- Determine profile name: use the API-returned `username` as the default profile name
     - If a profile with the same name already exists and its token differs, append a numeric suffix (`hong-2`, `hong-3`, etc.)
     - If re-authorizing the current active profile (same nickname), update the existing profile's token in-place
   - Write `~/.til/credentials` in YAML format (`chmod 600`):
     - Set `active` to the new profile name
     - Add/update the profile under `profiles` with `token`, `nickname`, `site_url`, `host`
   - Display:

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/management.md (reported line 434)May include surrounding context.

md
| Scenario | Handling |
|----------|----------|
| Already has valid token | Confirm before re-authorizing |
| Token expired/invalid | Proceed directly to new authorization, no confirmation |
| `~/.til/` directory doesn't exist | Create automatically |
| Browser didn't open | Display fallback URL + manual code entry |
| User cancels in browser | Polling times out, show timeout message |

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/management.md (reported line 541)May include surrounding context.

Remove profile "work" (@hong-corp)? (y/n)

text

- `y` → remove from `profiles` map, write back `~/.til/credentials`
- `n` → cancel

When the last profile is removed, `~/.til/credentials` is cleared (empty `profiles` map, no `active` field).

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
77% confidence
Finding

The /til batch flow says the system will generate each entry with title, body, tags, lang, but the reference does not indicate that language is user-selectable or inferred with opt-in. Because locale/language choice is not surfaced to the user anywhere in this behavior, it risks imposing a language setting without explicit user choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.