Back to skill

Security audit

Shortcut

Security checks for vulnerabilities and agentic risk

Overview

This Shortcut skill mostly matches its stated purpose, but it has an unsafe setup path that can turn Shortcut workspace data into shell code sourced on the user's machine.

Review before installing. The normal Shortcut API access is expected, but do not source the generated workflow-states file from .bashrc unless the skill is fixed to store passive data instead of shell code. Treat delete commands carefully, verify IDs before use, and prefer a token with the minimum Shortcut permissions needed.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/shortcut-init-workflow.sh:19
Finding

API-Controlled Workflow Names Are Converted into Persistent Shell Code

Content
View full analysis
"$CONFIG_DIR/workflow-states" << 'EOF' # Shortcut workflow state IDs for your workspace # Generated by shortcut-init-workflow.sh # Edit these to match your workspace's actual state IDs EOF echo "$STATES" | jq -r '.[] | .states[] | "export SHORTCUT_STATE_\(.name | ascii_upcase | gsub(" "; "_"))=\(.id)"' >> "$CONFIG_DIR/workflow-states" ``` The generated file is subsequently executed: ```bash if [ -f ~/.config/shortcut/workflow-states ]; then source ~/.config/shortcut/workflow-states ``` The documentation also recommends persistent execution from shell startup: ```bash export SHORTCUT_API_TOKEN=$(cat ~/.config/shortcut/api-token 2>/dev/null | tr -d '\n') source ~/.config/shortcut/workflow-states ``` ### Technical Analysis The initialization script retrieves workflow objects from the Shortcut API and embeds each remote workflow state name directly into a shell variable declaration. The only transformation applied to the name is uppercasing and replacement of spaces with underscores. This does not reject shell metacharacters, command substitutions, quotes, line breaks, or other characters that can change the meaning of the generated shell file. The resulting file is not treated as passive configuration: `shortcut-update-story.sh` executes it with `source`, and the documentation recommends sourcing it from `.bashrc`. Consequently, a party capable of controlling a workflow state name in the associated Shortcut workspace may be able to place shell syntax in `~/.config/ ...[truncated 1759 chars]
Remediation
View remediation
"$CONFIG_FILE" chmod 600 "$CONFIG_FILE" ``` 2. Read the required ID with `jq` rather than `source`: ```bash STATE_DONE=$(jq -er ' .[] | select(.name == "Done") | .id ' "$HOME/.config/shortcut/workflow-states.json") ``` 3. Validate every retrieved ID as an integer before using it: ```bash [[ "$STATE_DONE" =~ ^[0-9]+$ ]] || { echo "Invalid workflow state ID" >&2 exit 1 } ``` 4. Remove all instructions recommending that API-derived files be sourced from `.bashrc`. 5. If shell-format configuration must be retained, use fixed local variable names rather than names derived from remote state names, strictly validate values, shell-escape them with `printf '%q'`, reject unexpected input, and create the file with mode `0600`. Passive JSON remains the safer design. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/shortcut-delete-comment.sh:19
Finding

Predictable Shared Temporary Files Permit Symlink Overwrites and Response Disclosure

Content
View full analysis
/dev/null || cat /tmp/shortcut-delete-comment-response.json exit 1 fi ``` From `scripts/shortcut-delete-task.sh`: ```bash HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/shortcut-delete-response.json \ -X DELETE \ -H "Shortcut-Token: $TOKEN" \ "$BASE_URL/stories/$STORY_ID/tasks/$TASK_ID") if [ "$HTTP_CODE" = "204" ]; then echo "✅ Deleted task #$TASK_ID" else echo "❌ Failed to delete task (HTTP $HTTP_CODE)" cat /tmp/shortcut-delete-response.json | jq . 2>/dev/null || cat /tmp/shortcut-delete-response.json exit 1 fi ``` ### Technical Analysis Both deletion scripts write API responses to fixed, globally predictable paths under `/tmp`. They do not securely create these files, verify ownership, prevent symbolic-link traversal, apply explicit restrictive permissions, or delete the files afterward. On a multi-user system, another local user can create one of these paths as a symbolic link before the victim invokes the script. Depending on the behavior and permissions of the target platform and `curl`, the response write may follow the link and truncate or overwrite a file writable by the victim. Concurrent invocations also share the same path, creating race conditions and causing one process to read another process's response. Failed API responses may remain on disk after execution and may be ...[truncated 1417 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/shortcut-update-story.sh:37
Finding

Unescaped Story Description Allows JSON Property Injection

Content
View full analysis
Remediation
View remediation
&2 exit 1 } PAYLOAD=$(jq -n \ --argjson current "$PAYLOAD" \ --argjson state_id "$WORKFLOW_STATE_ID" \ '$current + {workflow_state_id: $state_id}') fi ``` Alternatively, build one `jq -n` expression after argument parsing. Also: - Check that every option requiring a value has a following argument before reading `$2`. - Validate workflow state IDs as decimal integers before passing them through `--argjson`. - Avoid assembling JSON through shell interpolation under all circumstances. - Add tests covering quotation marks, backslashes, newlines, Unicode text, and attempted property injection. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (43)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description claims a multi-function Shortcut board/story management skill covering story creation, status updates, listing active/completed stories, checklist task management, and comment support. The provided code chunk does only one operation: POST a comment to /stories/{id}/comments for a specified story. This is related to the declared domain and does not introduce suspicious undeclared access, but it materially under-delivers relative to the declared functionality. Therefore the description does not accurately represent what this specific code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk is narrowly focused on creating a Shortcut story. It parses a required story name and optional description/type, builds a JSON payload, and sends a POST request to the Shortcut stories endpoint. This matches only one part of the declared description: creating stories with descriptions and types. However, the declared purpose claims broader story management capabilities including updating status, listing stories, checklist management, and comments, none of which are present in this code. There is no evidence of unrelated or malicious behavior, but the description materially overstates the implemented functionality of the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description presents a broader Shortcut story management skill focused on creating, updating, listing stories, plus checklist and comment support. The actual code performs a specific destructive action: deleting a comment from a story. While 'comment support' could loosely imply comment operations, deletion is not explicitly stated, and this code does not implement the main declared capabilities such as story creation, status updates, listing stories, or checklist management. Therefore the supplied code chunk does not accurately represent the declared purpose and includes an undeclared destructive comment-deletion capability.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description focuses on story/task operations in Shortcut: creating stories, updating status, listing active/completed stories, and handling checklists/comments. The actual code does none of those operations. Its sole purpose is bootstrap/configuration: it retrieves workflow states from the Shortcut API and saves them locally as shell exports. While workflow state IDs could support later story-status updates, this script itself is not a story management tool and materially differs from the declared primary purpose. Therefore this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code’s behavior is substantially narrower than the declared description. It only reads/list stories from Shortcut and does not create stories, update stories, manage checklists, or handle comments. The listing functionality does align with part of the description, but the overall declared purpose materially overstates the implemented capabilities of this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description presents a broader story-management skill with create, update, list, checklist management, and comment support. The actual code chunk is a read-only viewer for one story: it calls the Shortcut API to fetch a specific story and prints details, tasks, and comments. There is no code for creating stories, modifying status, managing checklist items, adding/updating comments, or listing multiple stories. While the code does operate on Shortcut stories, its implemented behavior is materially narrower than the declared functionality, so this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The script's actual behavior is narrow and specific: it requires an existing story ID and performs a PUT request to update that story's workflow_state_id and/or description. This aligns with only a subset of the declared description: updating story status and description. It does not create stories, list stories, manage checklists, add comments, or handle story types. There are no unrelated external resources or suspicious extra capabilities beyond Shortcut story updates, but the declared description substantially overstates the implemented functionality, so this is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/shortcut-init-workflow.sh (reported line 51)May include surrounding context.

sh
t-init-workflow.sh
# Edit these to match your workspace's actual state IDs

EOF

echo "$STATES" | jq -r '.[] | .states[] | "export SHORTCUT_STATE_\(.name | ascii_upcase | gsub(" "; "_"))=\(.id)"' >> "$CONFIG_DIR/workflow-states"

echo "✅ Workflow states saved to: $CONFIG_DIR/workflow-states"
echo
echo "To use these states, either:"
echo "  1. Source the file: source $CONFIG_DIR/workflow-states"
echo "  2. Add to ~/.bashrc: echo 'source $CONFIG_DIR/workflow-states' >> ~/.bashrc"
echo "  3. The scripts will auto-load it from $CONFIG_DIR/workflow-states"
echo
echo "Current configuration:"
cat "$CONFIG_DIR/workflow-states"

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 8)May include surrounding context.

md
## Features

- **List stories** - View active, completed, or all stories on your board
- **Create stories** - Add new tasks with descriptions and types (feature/bug/chore)
- **Update stories** - Change story status and descriptions

## Installation

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents extensive shell-based capabilities but does not declare any explicit tool scope such as allowed-tools or permissions. In an agent environment, that weakens policy enforcement and can let the skill invoke broader shell access than a user or platform expects, increasing the chance of unintended command execution or local file access.

Content

No source excerpt is available for this finding.

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

  1. Get your API token from Shortcut.com (Settings → API Tokens)
  2. Store it either:
    • As environment variable: export SHORTCUT_API_TOKEN="your-token"
    • In a file: echo "your-token" > ~/.config/shortcut/api-token && chmod 600 ~/.config/shortcut/api-token
  3. Initialize workflow states for your workspace:
    bash
    scripts/shortcut-init-workflow.sh
    

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

  1. Get your API token from Shortcut.com (Settings → API Tokens)
  2. Store it either:
    • As environment variable: export SHORTCUT_API_TOKEN="your-token"
    • In a file: echo "your-token" > ~/.config/shortcut/api-token && chmod 600 ~/.config/shortcut/api-token
  3. Initialize workflow states for your workspace:
    bash
    scripts/shortcut-init-workflow.sh
    

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill documents destructive actions such as deleting tasks and comments without any warning, confirmation guidance, or note about irreversibility. In an agent-driven workflow, that raises the risk of accidental data loss because a model or user may invoke deletion commands without understanding their consequences.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
79% confidence
Finding

The setup instructions encourage loading persistent environment state from shell startup files, including exporting an API token and sourcing workflow-state variables. Persisting secrets and operational context across sessions increases the chance of accidental reuse, exposure through shell history or inherited environments, and unintended actions against the wrong workspace.

Content

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

md
## Workflow

1. List existing stories to understand current board state
2. Create new stories with descriptive names and appropriate types
3. Update story status as work progresses

## Notes

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 · scripts/shortcut-add-comment.sh (reported line 24)May include surrounding context.

sh
}')

# Create comment
RESPONSE=$(curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Shortcut-Token: $TOKEN" \
  -d "$PAYLOAD" \

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 · scripts/shortcut-create-story.sh (reported line 51)May include surrounding context.

sh
}')

# Create comment
RESPONSE=$(curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Shortcut-Token: $TOKEN" \
  -d "$PAYLOAD" \

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 · scripts/shortcut-create-task.sh (reported line 25)May include surrounding context.

sh
}')

# Create comment
RESPONSE=$(curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Shortcut-Token: $TOKEN" \
  -d "$PAYLOAD" \

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 · scripts/shortcut-list-stories.sh (reported line 52)May include surrounding context.

sh
}')

# Create comment
RESPONSE=$(curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Shortcut-Token: $TOKEN" \
  -d "$PAYLOAD" \

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 · scripts/shortcut-create-task.sh (reported line 2)May include surrounding context.

sh
#!/bin/bash
# Create a new checklist task in a Shortcut story
# Usage: ./shortcut-create-task.sh <story-id> "task description"

set -euo pipefail

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script silently loads a credential from SHORTCUT_API_TOKEN or ~/.config/shortcut/api-token and uses it in an authenticated POST request to the Shortcut API. While this is related to the script's purpose, there is no confirmation prompt, visible disclosure, or warning that local credentials will be accessed and transmitted over the network.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script implements destructive comment deletion, but the skill metadata only advertises creating, updating, and listing stories plus checklist/comment support, not deletion. Hidden destructive capability increases the chance an agent or user invokes behavior they did not authorize or expect, which can lead to integrity loss in project records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This script performs an irreversible DELETE request immediately from positional arguments with no interactive confirmation, dry-run mode, or secondary validation. In an agent context, argument mix-ups, prompt injection, or mistaken tool selection could silently remove comments and destroy audit/context data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% 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 · scripts/shortcut-init-workflow.sh (reported line 51)May include surrounding context.

sh
echo
echo "To use these states, either:"
echo "  1. Source the file: source $CONFIG_DIR/workflow-states"
echo "  2. Add to ~/.bashrc: echo 'source $CONFIG_DIR/workflow-states' >> ~/.bashrc"
echo "  3. The scripts will auto-load it from $CONFIG_DIR/workflow-states"
echo
echo "Current configuration:"

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 · scripts/shortcut-edit-task.sh (reported line 25)May include surrounding context.

sh
}')

# Update comment
RESPONSE=$(curl -s -X PUT \
  -H "Content-Type: application/json" \
  -H "Shortcut-Token: $TOKEN" \
  -d "$PAYLOAD" \

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 · scripts/shortcut-update-comment.sh (reported line 25)May include surrounding context.

sh
}')

# Update comment
RESPONSE=$(curl -s -X PUT \
  -H "Content-Type: application/json" \
  -H "Shortcut-Token: $TOKEN" \
  -d "$PAYLOAD" \

Static analysis

No suspicious patterns detected.