Back to skill

Security audit

EVC Team Relay

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it gives an agent powerful read, write, and delete access to shared Obsidian notes with weak safeguards around credentials and destructive actions.

Install only for a trusted agent account with the minimum Relay permissions needed. Prefer a dedicated least-privilege account, use HTTPS-only RELAY_CP_URL values, avoid passing tokens as script arguments, keep backups/versioning for shared vaults, and require human approval before write or delete operations.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/write.sh:35
Finding

Bearer Token Disclosed in Error Output

Content
View full analysis
/dev/null || echo "") if [ -n "$FILES_CHECK" ]; then FILE_COUNT=$(echo "$FILES_CHECK" | jq '.files | length' 2>/dev/null || echo "0") if [ "$FILE_COUNT" -gt "0" ] || echo "$FILES_CHECK" | jq -e '.files' >/dev/null 2>&1; then echo "Error: this looks like a folder share (has file metadata)." >&2 echo "write.sh does NOT work for folder shares — files won't appear in Obsidian." >&2 echo "" >&2 echo "Use upsert-file.sh instead:" >&2 echo " scripts/upsert-file.sh \"$TOKEN\" \"$SHARE_ID\" \"filename.md\" \"content\"" >&2 exit 1 ``` ### Technical Analysis When `write.sh` determines that the supplied identifier appears to represent a folder share, it constructs a usage example containing the complete value of `$TOKEN` and writes it to standard error. Standard error is not a secure secret channel. It may be retained in AI agent transcripts, CI/CD logs, centralized logging systems, terminal recordings, support bundles, or command-execution audit trails. The exposed value is a bearer credential, so possession of it is sufficient to authenticate as the corresponding Relay user until the token expires or is revoked. ### Attack Path 1. A user or agent invokes `write.sh` with identical folder share and document identifiers. 2. The script successfully queries the folder’s file metadata. 3. The folder-share detection branch is entered. 4. The script prints a command containing the complete bearer token to standard error. 5. A local user, log reader, monitoring service, or other party with ...[truncated 816 chars]
Remediation
View remediation
&2 echo " scripts/upsert-file.sh \"$SHARE_ID\" \"filename.md\" \"content\"" >&2 ``` Additional hardening measures: 1. Search all script output paths to ensure that `$TOKEN`, `$RELAY_PASSWORD`, and complete API responses containing credentials are never printed. 2. Add automated tests that invoke error branches using a sentinel token and fail if the sentinel appears in stdout or stderr. 3. Treat existing logs as potentially compromised and remove any retained output containing tokens. 4. Revoke exposed tokens where supported, or wait for expiration before considering affected sessions secure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
README.md:119
Finding

Bearer Tokens Passed Through Process Command-Line Arguments

Content
View full analysis
" # Read a note bash scripts/read.sh "$TOKEN" "" "" # Write a note echo "# Hello from my agent" | bash scripts/write.sh "$TOKEN" "" "" - ``` The operational scripts implement this fallback pattern. For example, `scripts/read.sh:14-19` contains: ```bash # Token: prefer RELAY_TOKEN env var, fall back to $1 (backward-compatible) if [ -n "${RELAY_TOKEN:-}" ]; then TOKEN="$RELAY_TOKEN" else TOKEN="${1:?Usage: read.sh [token] [doc_id] [key] (or set RELAY_TOKEN)}" shift fi ``` ### Technical Analysis The README explicitly recommends passing the bearer token as the first positional argument. Every operational script supports the same backward-compatible behavior. When the shell expands `"$TOKEN"`, the credential becomes part of the child process argument vector. Process arguments may be exposed through process inspection interfaces, command-execution telemetry, endpoint monitoring, audit systems, debugging tools, and process launch records. Quoting the token prevents shell word splitting but does not prevent argument-vector disclosure. This documentation also conflicts with the safer recommendation in `SKILL.md`, which advises using `RELAY_TOKEN` because command-line tokens can be visible in process listings. ### Attack Path 1. A user follows the README ...[truncated 1269 chars]
Remediation
View remediation
" bash scripts/read.sh "" "" echo "# Hello from my agent" | bash scripts/write.sh "" "" - ``` Update each affected script to reject a missing environment variable rather than interpreting `$1` as a token: ```bash : "${RELAY_TOKEN:?Set RELAY_TOKEN using scripts/auth.sh}" TOKEN="$RELAY_TOKEN" ``` Further hardening should include: 1. Remove all examples that place a real token in a command line. 2. If immediate removal would break compatibility, deprecate positional tokens, emit a warning that does not include the token, and remove support in the next major release. 3. Use a short-lived, least-privilege Relay account dedicated to the agent. 4. Avoid enabling shell tracing while handling credentials. 5. Add tests that verify documented invocations do not include tokens in positional arguments. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.sh:8
Finding

Authentication Credentials Can Be Sent Over Plaintext HTTP

Content
View full analysis
Remediation
View remediation
&2 exit 1 ;; esac ``` Apply equivalent validation to every script, preferably through a shared helper to avoid inconsistent enforcement. Additional hardening measures: 1. Permit plaintext HTTP only through an explicit development override. 2. If a development override is required, restrict it to loopback destinations such as `127.0.0.1`, `localhost`, or `::1`. 3. Document HTTPS as mandatory rather than merely showing it in examples. 4. Use certificates issued by a trusted internal or public certificate authority. 5. Do not add `curl --insecure`, because disabling certificate verification would reintroduce interception risk. 6. Rotate the Relay password and revoke active sessions if credentials may previously have traversed plaintext HTTP. ]]>
Vulnerability Patterns
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
Findings (22)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
scripts/delete-file.sh <folder_share_id> "old-note.md"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
scripts/delete-file.sh <folder_share_id> "old-note.md"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
scripts/delete-file.sh <folder_share_id> "old-note.md"

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

POST /v1/auth/refresh

Refresh an expired access token.

Request:

json

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/api.md (reported line 249)May include surrounding context.

md
- `422` — missing required fields
- `502` — relay server unavailable

### DELETE /v1/documents/{doc_id}/files/{file_path}

Delete a file from a folder share. Removes the entry from `filemeta_v0` Y.Map.

Credential Access

High
Category
Privilege Escalation
Confidence
85% confidence
Finding

The script prints the access token in plain text to stdout for command substitution. In a collaborative agent skill context, this is sensitive because tokens can be captured by logs, error reporting, shell tracing, parent processes, or other tooling integrations, potentially granting access to shared Relay/Obsidian data.

Content

Scanner excerpt · scripts/auth.sh (reported line 2)May include surrounding context.

sh
#!/usr/bin/env bash
# Authenticate with Relay Control Plane and print the access token.
# Usage: scripts/auth.sh
# Env: RELAY_CP_URL, RELAY_EMAIL, RELAY_PASSWORD
# Output: access_token (plain text, no newline) — suitable for $()

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

md
[![OpenClaw](https://img.shields.io/badge/OpenClaw-skill-FF5A2D)](https://github.com/openclaw/openclaw)
[![Entire VC](https://img.shields.io/badge/Entire_VC-toolbox-525769)](https://entire.vc)

**Give your AI agent read/write access to your Obsidian vault.**

> Your agent reads your notes, creates new ones, and stays in sync — all through the Team Relay API.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly markets broad read/write/delete access to a shared Obsidian vault but does not warn users about the risk of unintended modification, deletion, or exposure of sensitive team notes. In an agent skill, this is materially dangerous because autonomous or mis-prompted agents can act on shared data at scale, so the missing warning increases the chance of unsafe deployment and misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation instructs users to place email and password credentials directly into configuration and shell environment examples without any warning about secret handling. That encourages insecure storage in plaintext config files, shell history, screenshots, or logs, which could expose credentials for the Relay control plane and all accessible shared vault data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill exposes shell-based capabilities and authenticated remote read/write/delete operations, but it declares no explicit tool scope such as permissions or allowed-tools. That omission increases the chance an agent can invoke shell broadly or use this skill in contexts where operators did not intend external networked file modification, which weakens containment and auditability.

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

All API calls require a Bearer JWT token. Get one via login:

bash
curl -s -X POST "$RELAY_CP_URL/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email": "'$RELAY_EMAIL'", "password": "'$RELAY_PASSWORD'"}' \
  | jq -r '.access_token'

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

When the token expires (1 hour), refresh it:

bash
curl -s -X POST "$RELAY_CP_URL/v1/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "'$REFRESH_TOKEN'"}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill documents a delete operation against shared collaborative content without any warning, confirmation step, or recovery guidance. In an agent context, this makes accidental or prompt-induced destructive actions more likely, potentially causing irreversible loss of shared notes or disruption for multiple users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown API reference documents file creation, file deletion, and full document replacement operations, including DELETE and PUT endpoints that can alter or remove user data. While the mechanics are described, there is no explicit warning calling out that these actions change shared content and may overwrite or delete data, which is the kind of user-impact warning required for markdown files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This shell script reads RELAY_EMAIL and RELAY_PASSWORD from the environment and sends them to a remote authentication endpoint via curl. Although the header comments describe usage, they do not clearly warn the user that credentials will be transmitted to a control-plane service, and there is no runtime confirmation or user-facing notice.

Content

No source excerpt is available for this finding.

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/auth.sh (reported line 12)May include surrounding context.

sh
: "${RELAY_EMAIL:?Set RELAY_EMAIL}"
: "${RELAY_PASSWORD:?Set RELAY_PASSWORD}"

resp=$(curl -sf -X POST "${RELAY_CP_URL}/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"email\": \"${RELAY_EMAIL}\", \"password\": \"${RELAY_PASSWORD}\"}")

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/create-file.sh (reported line 39)May include surrounding context.

sh
--arg content "$CONTENT" \
  '{share_id: $sid, path: $path, content: $content}')

curl -sf -X POST "${RELAY_CP_URL}/v1/documents/${FOLDER_SHARE_ID}/files" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" | jq '.'

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/upsert-file.sh (reported line 63)May include surrounding context.

sh
--arg content "$CONTENT" \
  '{share_id: $sid, path: $path, content: $content}')

curl -sf -X POST "${RELAY_CP_URL}/v1/documents/${FOLDER_SHARE_ID}/files" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" | jq '.'

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script implements a DELETE operation against shared vault content, while the stated skill scope describes read, create/update, list, and search capabilities but does not mention deletion. This creates a scope mismatch that can lead users or calling agents to invoke destructive behavior they did not explicitly authorize, increasing the risk of accidental or unauthorized data loss in a collaborative environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code performs a network call to retrieve document content and transmits sensitive values including a bearer token, document ID, share ID, and key. Although comments describe usage, there is no confirmation prompt or user-facing warning that the script will contact a remote Relay service and access protected document data.

Content

No source excerpt is available for this finding.

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/upsert-file.sh (reported line 49)May include surrounding context.

sh
--arg content "$CONTENT" \
    '{share_id: $sid, content: $content, key: "contents"}')

  RESULT=$(curl -sf -X PUT "${RELAY_CP_URL}/v1/documents/${EXISTING_DOC_ID}/content" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -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/write.sh (reported line 65)May include surrounding context.

sh
--arg key "$KEY" \
  '{share_id: $sid, content: $content, key: $key}')

curl -sf -X PUT "${RELAY_CP_URL}/v1/documents/${DOC_ID}/content" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" | jq '.'

Static analysis

No suspicious patterns detected.