Back to skill

Security audit

Virse Design

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a Virse design-platform integration, but it handles credentials and includes a silent update/self-update path with too much trust and too little containment.

Install only if you trust the Virse service and this skill's GitHub update source. Before use, avoid setting VIRSE_BASE_URL to any untrusted host, understand that the skill can read and change Virse workspaces/canvases using your token, and review any proposed update before approving it.

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
scripts/virse_call.py:25
Finding

Bearer Token Disclosure Through an Unrestricted Configurable API Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/virse_call.py:25-38, 116-124
Vulnerability Type: Credential disclosure through an untrusted network destination
Risk Level: High

Vulnerable Code

python
def _read_token():
    """Read token: VIRSE_API_KEY env > ~/.virse/token file."""
    token = os.environ.get("VIRSE_API_KEY", "").strip()
    if token:
        return token
    try:
        with open(TOKEN_PATH, "r") as f:
            return f.read().strip()
    except FileNotFoundError:
        return ""


def _base_url():
    return os.environ.get("VIRSE_BASE_URL", DEFAULT_BASE_URL).rstrip("/")
python
def call_tool(name, args_json):
    base = _base_url()
    token = _read_token()
    endpoint = f"{base}/mcp"

    headers = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream;q=0.9"}
    if token:
        headers["Authorization"] = f"Bearer {token}"

The same credential-forwarding behavior appears in batch_call at lines 169-177 and list_tools at lines 233-241.

Technical Analysis

The script reads a sensitive Virse bearer token from either VIRSE_API_KEY or ~/.virse/token. Independently, it accepts the API destination from the unrestricted VIRSE_BASE_URL environment variable. It then attaches the token as an Authorization header to requests sent to that destination.

The destination is not validated against an approved hostname, HTTPS is not enforced, and no restriction prevents an attacker-controlled origin from being selected. Consequently, any process, wrapper, CI configuration, or execution environment capable of influencing VIRSE_BASE_URL can redirect authenticated requests and capture the bearer token.

Network transmission of a token to the default Virse endpoint is necessary for the Skill's declared cloud functionality. Allowing that credential to be forwarded to an arbitrary endpoint is not necessary and exceeds minimum privilege. No hardcoded malicious endpoint was identi ...[truncated 1487 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict authenticated destinations

    • Parse the configured URL with urllib.parse.urlsplit.
    • Require the https scheme.
    • Permit bearer-token transmission only to an explicit hostname allowlist, such as dev.virse.ai.
    • Reject embedded credentials, fragments, unexpected ports, malformed hosts, and ambiguous URLs.
  2. Separate production and development credentials

    • If custom endpoints are required, require a separate development credential.
    • Never forward a production Virse token to a custom endpoint.
    • Require an explicit, clearly named opt-in for custom endpoints.
  3. Harden redirect handling

    • Disable redirects for authenticated API requests or validate every redirect target.
    • Strip the Authorization header whenever the destination origin changes.
    • Reject HTTPS-to-HTTP redirects.
  4. Fail closed

    • Abort before reading or attaching the token when endpoint validation fails.
    • Emit a clear error without printing the credential.
    • Apply the same centralized validation to call_tool, batch_call, list_tools, and OAuth endpoints.
  5. Update documentation

    • Clearly warn that VIRSE_BASE_URL must not designate an untrusted service.
    • Prefer removing the override from ordinary user-facing authentication instructions unless it is operationally required.
  6. Add security tests

    • Verify that HTTP endpoints are rejected.
    • Verify that non-allowlisted hosts do not receive authorization headers.
    • Verify that cross-origin redirects cannot receive credentials.
    • Verify that the default approved endpoint continues to work.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as a Virse design-platform integration, but it also contains update-check and self-update behavior that reaches out to external resources and can modify the local skill repository. That hidden extra capability expands the trust boundary and can surprise users or orchestrators that only expected design operations, increasing supply-chain and unintended-code-change risk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill is presented as a Virse design-platform integration, but it also contains update-check and self-update behavior that reaches out to external resources and can modify the local skill repository. That hidden extra capability expands the trust boundary and can surprise users or orchestrators that only expected design operations, increasing supply-chain and unintended-code-change risk.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The activation language is very broad ('any visual design task' even without naming Virse), which can cause the skill to be invoked for generic requests outside the user's intent. Over-broad routing is dangerous because it can expose external-tool actions, authentication flows, and remote operations in contexts where a simpler or safer capability should have been used.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% 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 · auth-guide.md (reported line 34)May include surrounding context.

Logout

bash
rm ~/.virse/token

Device Flow — Raw HTTP (for CI / scripts)

Lp1

High
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The script performs outbound network access to GitHub and git remotes, but the finding indicates this capability is not declared in permissions. Undeclared network behavior is dangerous because it bypasses least-privilege expectations, can surprise operators, and may allow unreviewed external communication during skill execution.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'file_write' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The playbook routing table includes Chinese trigger phrases alongside English ones, but the skill does not state that multilingual routing is optional or user-selected. This can create an implicit language/locale behavior without explicit opt-in or policy justification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Local repository maintenance and file modification are unrelated to normal Virse design tasks and broaden the skill's ability to alter its own environment. This increases risk because a skill expected to manipulate remote design assets can also modify local files, making abuse or accidental corruption more plausible.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill includes a self-update path using git pull and in-place manifest editing, which can change code and metadata after deployment. Even with user consent, embedding this in an operational skill creates a supply-chain risk: a compromised repository, branch, or remote origin could cause the assistant to fetch and run altered code outside the user's original review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file instructs users to save an API key to ~/.virse/token or export it as VIRSE_API_KEY, both of which affect credential storage and privacy. The section does not warn that the token will be stored locally or exposed to shell history/process environment depending on how the command is used.

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 · auth-guide.md (reported line 42)May include surrounding context.

Step 1 — Start device flow

bash
curl -s -X POST https://dev.virse.ai/device/code \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=virse-skill'

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The phrase "applicable to any multi-stage image generation pipeline" broadens the procedure beyond the clearly described product-listing use case, which can cause the agent to over-apply specialized workflow instructions in unrelated contexts. In a skill that is already activated for broad visual design tasks, this increases the chance of unintended execution, misuse of reference-chain cloning on the wrong canvas, or inappropriate manipulation of assets/workspaces.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The instruction "English only" hard-codes an output language without checking the user's language preference or the source material's language. This can override user intent, degrade accessibility/localization, and cause incorrect or non-compliant outputs for multilingual product workflows.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The trigger keyword "curate" is generic and commonly used in normal conversation, so this playbook may activate in contexts not specifically about asset-folder organization. In an agent environment, overly broad activation can cause the wrong skill to run, leading to unintended access to canvas and asset metadata and actions such as folder creation or asset linking without clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are overly broad and include common user language such as 'create a set of' and 'lay them out', which can cause the skill to activate in conversations that are not specifically about the Virse platform. In an agent setting, this increases the chance of unintended tool use, unexpected workspace or canvas actions, and confusing cross-domain behavior when the user meant a generic design request rather than invoking this skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad, generic terms like "clean up" and "organize," which can easily match ordinary user requests that are not specifically about canvas maintenance. In an agent-routing context, this can cause unintended invocation of the skill and lead to access to canvas state or destructive follow-on actions being proposed in the wrong context.

Content

No source excerpt is available for this finding.

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 · playbooks/canvas-cleanup.md (reported line 16)May include surrounding context.

md
- Overlapping elements (similar position ranges)
   - Empty/single-member groups
   - Outlier elements far from main content
3. **Report & ask** — Present audit findings and suggested actions to the user. **Get explicit confirmation before making any changes.** Never delete without confirmation.
4. **Apply** — Based on user choices:
   - Re-layout: `update_element` to reposition into clean grid
   - Group clusters: `create_group(element_ids=[...])`

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger keywords include very broad terms like "consolidate" and "gather images matching X," which can cause the skill to activate in contexts where the user did not explicitly intend a cross-workspace operation. In this skill, unintended invocation is more dangerous because the playbook performs multi-workspace enumeration and asset collection, potentially exposing or reorganizing data across broad scopes once triggered.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger list includes broad, everyday phrases like 'iterate', 'keep tweaking', and 'improve step by step' that can match many normal conversations unrelated to this specific Virse workflow. This can cause unintended skill activation, leading the agent to invoke design/image-generation actions in contexts where the user did not clearly request this capability.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are very broad and map to common design-related language such as 'find references' or 'organize', which can cause the skill to activate when a user did not explicitly intend to use Virse. In an agentic environment, overbroad invocation increases the chance of unintended external actions like workspace creation, image search, and canvas modification without sufficiently clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes the generic term "compare" without constraining it to Virse, images, canvases, models, or design workflows. In an agent environment, this can cause the skill to activate for unrelated user requests, leading to unintended tool use, context hijacking, or execution of design actions when the user did not intend to invoke this skill.

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 · scripts/check_update.py (reported line 47)May include surrounding context.

python
def get_remote_hash_github() -> str | None:
    """Get latest commit hash from GitHub API (no git required)."""
    url = f"https://api.github.com/repos/{GITHUB_REPO}/commits/{GITHUB_BRANCH}"
    req = urllib.request.Request(url, headers={
        "Accept": "application/vnd.github.v3+json",
        "User-Agent": "virse-skill-updater",

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/check_update.py (reported line 64)May include surrounding context.

python
"""Get latest remote hash via git (fetch then rev-parse, fallback to ls-remote)."""
    # Try fetch + rev-parse
    try:
        fetch = subprocess.run(
            ["git", "-C", skill_dir, "fetch", "origin", GITHUB_BRANCH, "--quiet"],
            capture_output=True, text=True, timeout=30,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/check_update.py (reported line 69)May include surrounding context.

python
capture_output=True, text=True, timeout=30,
        )
        if fetch.returncode == 0:
            rev = subprocess.run(
                ["git", "-C", skill_dir, "rev-parse", f"origin/{GITHUB_BRANCH}"],
                capture_output=True, text=True, timeout=5,
            )

Static analysis

No suspicious patterns detected.