Back to skill

Security audit

Craft API Skill and Obsidian Migration Tool

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-built for Craft.do automation, but it uses a powerful API token for bulk uploads and destructive changes while trusting any configured endpoint URL.

Install only if you trust the publisher and will use a narrowly scoped, revocable Craft API key. Verify CRAFT_ENDPOINT is the official HTTPS Craft endpoint before every run, back up/export important Craft and Obsidian data first, and avoid running the migration or cleanup scripts unattended.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
craft-api.sh:8
Finding

Bearer Token Can Be Sent to an Untrusted Configurable Endpoint

Content
View full analysis
` to the attacker-controlled server. 4. The attacker records the token. 5. The attacker uses the stolen token against the legitimate C ...[truncated 524 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
craft-api.sh:64
Finding

Command-Line and Filesystem Values Are Interpolated Directly into JSON Payloads

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
migrate-obsidian-nested.sh:75
Finding

Obsidian Folder Names Are Evaluated as jq Program Text

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
migrate-obsidian.sh:50
Finding

Migration Scripts Use Predictable Non-Atomic Files in Shared Temporary Storage

Content
View full analysis
> "$FOLDER_MAP" } ``` The nested migration uses the equivalent pattern: ```bash FOLDER_MAP="/tmp/craft-folders-$$.txt" trap "rm -f $FOLDER_MAP" EXIT touch "$FOLDER_MAP" ``` ### Technical Analysis The temporary filename is based only on the process ID and is created in the shared `/tmp` directory with `touch`. Creation is not atomic and does not reject symbolic links. On a multi-user system, a local attacker can pre-create or race a symbolic link at the predicted path. The victim's script then follows that link when touching and appending to the folder map. The attacker may redirect writes to another file writable by the victim, manipulate the mapping read by the migration, or observe folder identifiers if the redirected location is attacker-readable. Existing mapping content can also influence folder selection because the script trusts values read from the file. The PID must be predicted or raced, which limits practical exploitability but does not remove the unsafe-file primitive. ### Attack Path 1. A local attacker predicts likely process IDs or repeatedly creates candidate `/tmp/craft-folders-.txt` symbolic links. 2. The victim starts a migration under one of those process IDs. 3. `touch` follows the attacker-created symbolic link instead of securely creating a new regular file. 4. The script appends folder paths and Craft folder IDs through that link. 5. Depending on the lin ...[truncated 640 chars]
Remediation
View remediation
&2 exit 1 } trap 'rm -f -- "$FOLDER_MAP"' EXIT HUP INT TERM ``` Additional hardening should include: 1. Verify that the created path is a regular file owned by the current user. 2. Never reuse an existing predictable temporary path. 3. Use `printf '%s:%s\n' "$folder_path" "$folder_id"` rather than `echo`. 4. Consider avoiding a temporary file entirely by using an in-memory Bash associative array. 5. Apply the correction to both migration scripts. 6. If a file is required across subprocess boundaries, store it in a securely created temporary directory generated by `mktemp -d`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (18)

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · README.md (reported line 165)May include surrounding context.

md
Tested: 2026-01-31
Last Updated: 2026-01-31

Found a new capability or limitation? Update SKILL.md and document your findings.

---

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 · README.md (reported line 18)May include surrounding context.

md
This skill provides **complete Craft.do API integration** for agents and automation:

- **One-time migration:** Move your entire Obsidian vault to Craft with full hierarchy
- **Ongoing automation:** Create tasks, organize documents, manage content programmatically
- **Helper utilities:** Ready-to-use scripts for common Craft operations
- **Safe & tested:** Production-ready with duplicate prevention and cleanup tools

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README instructs users to run a destructive cleanup command that 'Deletes everything' without clearly stating scope, recovery limits, or whether the script prompts for confirmation. In an automation skill, users may copy-paste commands directly, so understated destructive operations materially increase the risk of accidental mass deletion of Craft content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill prominently advertises create, update, move, and migration capabilities against user documents, folders, and tasks, but it does not provide an upfront warning that executing these commands will modify remote user data. In an agent setting, this increases the risk of unintended destructive or irreversible changes because users may invoke examples without clear awareness of write-side effects.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

List Folders

bash
curl -H "Authorization: Bearer $CRAFT_API_KEY" \
  "$CRAFT_ENDPOINT/folders"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
# Push each to Craft
echo "$COMPLETED_TASKS" | while read -r task; do
  curl -X POST \
    -H "Authorization: Bearer $CRAFT_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
"$CRAFT_ENDPOINT/folders" | jq -r '.id')

# 2. Create a project document
DOC_ID=$(curl -X POST \
  -H "Authorization: Bearer $CRAFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
"$CRAFT_ENDPOINT/folders" | jq -r '.id')

# 2. Create a project document
DOC_ID=$(curl -X POST \
  -H "Authorization: Bearer $CRAFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

md
TASK_ID=$(curl -H "Authorization: Bearer $CRAFT_API_KEY" \
  "$CRAFT_ENDPOINT/tasks?scope=active" | jq -r '.items[0].id')

curl -X PUT \
  -H "Authorization: Bearer $CRAFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · cleanup-craft.sh (reported line 32)May include surrounding context.

sh
local data="$3"
  
  if [ -n "$data" ]; then
    curl -s -X "$method" \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "$data" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · craft-api.sh (reported line 26)May include surrounding context.

sh
local data="$3"
  
  if [ -n "$data" ]; then
    curl -s -X "$method" \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "$data" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The move command performs a state-changing operation on user documents by relocating them, but the script provides no confirmation prompt and no explicit warning that it will alter document organization. While the command name hints at its purpose, there is no user disclosure beyond terse usage text about the impact of the action.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This helper wraps curl calls to an externally supplied endpoint using a bearer token and is later used to transmit folder metadata and document contents off-host. External transmission is expected for a migration script, but it still represents a real data-exfiltration boundary, especially because the endpoint is configurable via environment variable and there is no validation or allowlist to ensure data only goes to the legitimate Craft service.

Content

Scanner excerpt · migrate-obsidian-nested.sh (reported line 40)May include surrounding context.

sh
local data="$3"
  
  if [ -n "$data" ]; then
    curl -s -X "$method" \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "$data" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script reads each markdown file and sends its full contents to the remote Craft API, but it does not present an explicit warning, confirmation, or scoping control before transmitting potentially sensitive vault data. Because Obsidian vaults often contain private notes, credentials, or personal records, silent bulk upload creates a real confidentiality risk if the user does not fully understand the disclosure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This helper centralizes authenticated outbound HTTP requests using curl with a bearer token, enabling transmission of vault metadata and document contents to whatever URL is placed in CRAFT_ENDPOINT. While external transmission is expected for a migration tool, the implementation does not constrain or validate the destination, so a mis-set or malicious endpoint can exfiltrate all migrated content and the API token to an attacker-controlled service.

Content

Scanner excerpt · migrate-obsidian.sh (reported line 39)May include surrounding context.

sh
local data="$3"
  
  if [ -n "$data" ]; then
    curl -s -X "$method" \
      -H "Authorization: Bearer $CRAFT_API_KEY" \
      -H "Content-Type: application/json" \
      -d "$data" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script reads each markdown file from the local Obsidian vault and uploads its full contents to a remote Craft API, but it provides only generic migration messaging and no explicit, prominent warning that potentially sensitive notes will be transmitted off-host. In a note-taking vault, content commonly includes private personal, business, or credential-adjacent information, so silent bulk export materially increases the risk of unintended data disclosure if the endpoint is misconfigured, untrusted, or broader than the user expects.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

Earlier documentation states that documents are created without content initially and that content must be added via the /blocks endpoint (L091-L109). The 'Create Daily Note' example instead creates a document with inline content and location fields in the document payload, which conflicts with the described API usage and intent of the skill documentation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The main API documentation says documents are created without content initially and content should be added later through /blocks (L075-L109, especially L091). In the workflow example, the document creation request includes content and a direct location field, which actively conflicts with the earlier guidance about how document creation works.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.