Back to skill

Security audit

Glasses to Social

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent, but it asks users to expose smart-glasses photos through public Google Drive link sharing and lacks clear privacy boundaries for sensitive images.

Review before installing. Use a private, dedicated Google Drive folder containing only photos intentionally submitted for social posting, avoid public link sharing, review images for bystanders and sensitive information before analysis or drafting, and keep posting credentials separate with explicit approval required for every post.

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
SKILL.md:25
Finding
Public Link Sharing Exposes Potentially Sensitive Wearable-Camera Photos<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 25-32 **Vulnerability Type**: Insecure access-control configuration **Risk Level**: Medium ### Vulnerable Code Snippet ```markdown ### 1. Configure Google Drive Folder Create a shared Google Drive folder for glasses photos: ```bash # User creates folder "Glasses-to-Social" in Google Drive # Share with "Anyone with link can view" # Copy the folder URL ``` ``` ### Technical Analysis The setup instructions explicitly direct users to configure the wearable-camera photo folder as accessible to anyone possessing its link. This removes identity-based access control and treats possession of the folder URL as sufficient authorization. Smart-glasses images may contain faces, physical locations, computer screens, documents, health information, or other sensitive first-person context. The exposure also applies to future images synchronized into the same folder. Although the URL is not necessarily indexed publicly, it may leak through configuration files, command output, logs, browser history, screenshots, chat messages, or accidental forwarding. No hidden exfiltration behavior was found in the scripts; this issue arises from the documented sharing configuration. ### Attack Path 1. A user follows the instructions and enables “Anyone with link can view.” 2. The folder URL is stored in `config.json` and passed to `gdown`. 3. The URL or folder identifier leaks through a readable configuration file, process output, logs, browser history, or a forwarded message. 4. An unauthenticated party opens the leaked URL. 5. The party reads or downloads the existing wearable-camera images and may continue accessing newly synchronized images while link sharing remains enabled. ### Impact Assessment An attacker gains unauthorized read access to the contents of the configured Google Drive folder. This does not provide operating-system privileges or permission to publish social-media posts, but it may expose a ...[truncated 173 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not instruct users to enable “Anyone with link can view.” - Keep the folder private and access it through authenticated Google OAuth or a dedicated service account. - Grant only read access to the specific folder required by the workflow. - Store OAuth tokens and configuration with restrictive filesystem permissions. - Avoid printing or recording the complete folder URL in logs. - Document image-retention, deletion, and privacy requirements. - Recommend a dedicated folder containing only photos intentionally submitted to this workflow. - Revoke existing public links and audit prior sharing activity when migrating an existing deployment. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mark-processed.sh:17
Finding
Predictable Temporary State File Allows Symlink Overwrite and Concurrent Update Races<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mark-processed.sh`, lines 17-18 **Vulnerability Type**: Unsafe temporary-file handling and missing state locking **Risk Level**: Medium ### Vulnerable Code Snippet ```bash jq --arg f "$FILENAME" '.processed += [$f]' "$PROCESSED_FILE" > "${PROCESSED_FILE}.tmp" mv "${PROCESSED_FILE}.tmp" "$PROCESSED_FILE" ``` ### Technical Analysis The script uses a predictable temporary filename derived directly from the state-file path. Shell redirection opens `${PROCESSED_FILE}.tmp` before `jq` executes and follows symbolic links by default. There is no exclusive file creation, symlink check, restrictive temporary-file permission, cleanup trap, or validation that the temporary path is a regular file owned by the expected user. If another local user can write to the state-file directory, that user can pre-create the predictable temporary path as a symbolic link to another file writable by the account running the script. The redirection can then truncate and replace the linked file's contents with JSON output. The implementation also lacks locking. Two simultaneous invocations can read the same original state, write to the same temporary path, and overwrite or move each other's output, causing lost updates or execution failures. ### Attack Path #### Symlink overwrite 1. An attacker obtains write access to the directory containing `processed.json`. 2. The attacker creates `processed.json.tmp` as a symbolic link to a target file writable by the script's execution account. 3. The victim or an automated process runs `mark-processed.sh`. 4. Shell redirection follows the symbolic link and truncates the target before writing the generated JSON. 5. The subsequent `mv` may replace the processing ledger with the attacker-selected link or fail after the target has already been modified. This path is conditional on the attacker having write access to the state directory and the target being writable by the script's ac ...[truncated 1004 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create the temporary file with `mktemp` inside a trusted, non-shared directory. - Set a restrictive `umask`, such as `umask 077`, before creating state files. - Use a cleanup trap to remove the unique temporary file on failure. - Verify that the state directory and state file are owned by the expected account and are not writable by untrusted users. - Serialize state updates using `flock` or an equivalent locking mechanism. - Write the updated JSON to the unique temporary file and atomically rename it only after `jq` succeeds. - Do not run the script with elevated privileges. Example hardened pattern: ```bash set -euo pipefail umask 077 LOCK_FILE="${PROCESSED_FILE}.lock" exec 9>"$LOCK_FILE" flock -x 9 STATE_DIR=$(dirname -- "$PROCESSED_FILE") TMP_FILE=$(mktemp "$STATE_DIR/.processed.XXXXXX") trap 'rm -f -- "$TMP_FILE"' EXIT jq --arg f "$FILENAME" \ 'if (.processed | index($f)) then . else .processed += [$f] end' \ "$PROCESSED_FILE" > "$TMP_FILE" mv -- "$TMP_FILE" "$PROCESSED_FILE" trap - EXIT ``` ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/check-new-photos.sh:39
Finding
Unsafe Filename Splitting and Substring Matching Break Photo-State Integrity<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check-new-photos.sh`, lines 39-54 **Vulnerability Type**: Unsafe shell pathname processing and inexact state comparison **Risk Level**: Low ### Vulnerable Code Snippet ```bash NEW_FILES=$(find "$TEMP_DIR" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.heic" -o -iname "*.webp" \) 2>/dev/null || true) if [ -z "$NEW_FILES" ]; then echo "No photos found in folder" exit 0 fi # Get list of already processed files PROCESSED=$(jq -r '.processed[]' "$PROCESSED_FILE" 2>/dev/null || echo "") FOUND_NEW=0 # Check each file for FILE in $NEW_FILES; do FILENAME=$(basename "$FILE") # Skip if already processed if echo "$PROCESSED" | grep -qF "$FILENAME"; then continue fi ``` ### Technical Analysis The result of `find` is stored in a shell variable and then expanded without quotes in `for FILE in $NEW_FILES`. Bash performs word splitting and pathname expansion on that value. Consequently, valid filenames containing spaces, tabs, newlines, or wildcard characters are not handled as single paths. The processed-state test also searches a newline-separated collection using `grep -qF`. This performs fixed-string substring matching rather than exact JSON-array membership. For example, a file named `photo.jpg` can be treated as processed when the ledger contains only `old-photo.jpg`. Conversely, malformed path splitting can result in the wrong basename being copied or emitted. The filenames originate from downloaded Google Drive content. Exploitation therefore requires the attacker or another participant to be able to place or rename a file in the monitored folder. The documented sharing setting grants view access rather than upload access, so public-link possession alone does not establish that capability. ### Attack Path 1. An attacker or untrusted collaborator with upload or rename permission places an image in the monitored folder with whitespa ...[truncated 976 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not store pathname lists in shell variables. - Use null-delimited `find` output and a read loop that preserves every filename byte other than null. - Query exact membership directly with `jq` instead of applying `grep` to serialized values. - Quote every pathname and use `--` before pathname arguments where supported. - Consider tracking immutable Google Drive file IDs or content hashes rather than basenames, because different files can share a basename. Example hardened pattern: ```bash FOUND_NEW=0 while IFS= read -r -d '' FILE; do FILENAME=$(basename -- "$FILE") if jq -e --arg f "$FILENAME" \ '.processed | index($f) != null' \ "$PROCESSED_FILE" >/dev/null; then continue fi echo "NEW PHOTO FOUND: $FILENAME" cp -- "$FILE" "$DOWNLOAD_DIR/" printf 'NEW_PHOTO_PATH:%s/%s\n' "$DOWNLOAD_DIR" "$FILENAME" FOUND_NEW=1 done < <( find "$TEMP_DIR" -type f \ \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \ -o -iname '*.heic' -o -iname '*.webp' \) -print0 ) ``` ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill description uses broad trigger language such as 'Use when setting up...' and 'creating hands-free content workflows,' which can cause the agent to invoke the skill in situations involving sensitive personal images without an explicit suitability check. Because this skill accesses smart-glasses photos and drafts public posts, ambiguous invocation increases the chance of unintended processing or disclosure of private visual data.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill handles photos captured by smart glasses, which may contain bystanders, private spaces, documents, screens, or other sensitive content, yet the description provides no clear privacy warning or consent boundary. This omission is dangerous because the workflow encourages automated download, AI analysis, and drafting for publication, creating a meaningful risk of privacy violations or accidental exposure.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This shell script performs a network operation by fetching folder contents from Google Drive, which can transfer remote data onto the local system. Although there is a status print at L34, it does not clearly warn the user about the download behavior or its implications; however, the script name and comments make the purpose fairly apparent, so this is low severity.

Static analysis

No suspicious patterns detected.