Back to skill

Security audit

Xcode Build Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a read-only Xcode build-log helper, but two documented command recipes can execute attacker-controlled Python if a crafted DerivedData directory exists.

Review before installing or using the all-project summary commands. Avoid granting Full Disk Access unless needed, and do not run the affected recipes on systems where other users or untrusted tools can create entries under Xcode DerivedData. The safer fix is to pass directory names to Python as data, such as through an environment variable or argv, rather than embedding them in Python source.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:91
Finding

Python Code Injection Through a DerivedData Directory Name in Latest Build Summary

Content
View full analysis
/dev/null | python3 -c " import json, sys from datetime import datetime, timezone, timedelta data = json.load(sys.stdin) EPOCH = datetime(2001, 1, 1, tzinfo=timezone.utc) name = '$NAME' latest = None ``` ### Technical Analysis The DerivedData directory basename is assigned to the shell variable `NAME` and then directly interpolated into the source passed to `python3 -c`: ```python name = '$NAME' ``` Shell quoting does not escape the value for use inside a Python string literal. If the directory name contains a single quote followed by valid Python statements, the value can terminate the intended string literal and inject additional Python code. The loop processes every matching `*-*` directory and only requires the directory to contain `Logs/Build/LogStoreManifest.plist`. An attacker with write access to the current user's DerivedData directory can therefore create a specially named directory and a valid manifest that passes these checks. For example, a basename shaped like the following can become executable Python after the trailing suffix is removed by `sed`: ```text x';__import__("os").system("id");#-a ``` The `sed 's/-[a-z]*$//'` operation removes `-a`, leaving attacker-controlled Python syntax. A valid plist is also needed because `json.load(sys.stdin)` executes before the vulnerable assignment. ### Attack Path 1. An attacker obtains the ability to create files and directories under the victim's `~/Library/Developer/Xcode/DerivedData/` directory. 2. The attacker ...[truncated 1214 chars]
Remediation
View remediation
/dev/null | python3 -c ' import json import os import sys from datetime import datetime, timezone, timedelta data = json.load(sys.stdin) EPOCH = datetime(2001, 1, 1, tzinfo=timezone.utc) name = os.environ["NAME"] latest = None ' ``` Alternatively, use a standalone Python script and pass `NAME` through `sys.argv`. Python source should remain constant regardless of directory names. Additional hardening should include: - Treating every filename and plist field as untrusted input. - Validating manifest structure and expected field types before processing. - Avoiding broad permissions such as Full Disk Access unless a specific operation demonstrably requires them. - Adding tests with directory names containing quotes, semicolons, newlines, backslashes, and Unicode characters. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:315
Finding

Python Code Injection Through a DerivedData Directory Name in Combined Build History

Content
View full analysis
/dev/null | python3 -c " import json, sys from datetime import datetime, timezone, timedelta data = json.load(sys.stdin) EPOCH = datetime(2001, 1, 1, tzinfo=timezone.utc) name = '$NAME' ``` ### Technical Analysis This recipe repeats the same unsafe data-to-code conversion. A basename read from the local filesystem is interpolated directly into a single-quoted Python literal within the source supplied to `python3 -c`. A single quote in `NAME` can close the intended Python string. Subsequent characters can introduce arbitrary Python expressions or statements, and a comment marker can suppress the remaining generated source on that line. Shell quoting around the overall command does not provide Python-language escaping. The preceding checks only verify that a matching directory and manifest file exist. They do not constrain the directory basename to a safe character set or prevent Python metacharacters from entering the generated source. ### Attack Path 1. An attacker creates a maliciously named `*-*` directory under `~/Library/Developer/Xcode/DerivedData/`. 2. The basename is constructed so that, after the trailing lowercase suffix is removed by `sed`, it closes the Python string and adds executable Python statements. 3. The attacker places a valid `Logs/Build/LogStoreManifest.plist` in the crafted directory so the file check and JSON parsing succeed. 4. The victim or agent runs the documented “Combined build history” comman ...[truncated 763 chars]
Remediation
View remediation
/dev/null | python3 -c ' import json import os import sys from datetime import datetime, timezone, timedelta data = json.load(sys.stdin) EPOCH = datetime(2001, 1, 1, tzinfo=timezone.utc) name = os.environ["NAME"] for uid, log in sorted( data.get("logs", {}).items(), key=lambda item: item[1].get("timeStartedRecording", 0), reverse=True, ): pass ' ``` A standalone Python file with an explicit positional argument is also appropriate: ```bash python3 analyzer.py "$NAME" ``` Further hardening should: - Validate external plist data before use. - Avoid generating programs through shell interpolation. - Exercise the recipes against hostile filenames in automated tests. - Apply least privilege and avoid advising Full Disk Access unless essential. - Review every other `python3 -c` recipe for similar interpolation of shell or filesystem data. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (19)

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 26)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 27)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 38)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 39)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 46)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 52)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 95)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 214)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 262)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 270)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 291)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 319)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 359)May include surrounding context.

text

Each project has a folder named `<ProjectName>-<hash>` containing:
- `info.plist` — project workspace path and last accessed date
- `Logs/Build/LogStoreManifest.plist` — structured index of all builds (timing, status, warnings, errors)
- `Logs/Build/*.xcactivitylog` — gzip-compressed SLF build logs with per-step timing and full compiler output

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill’s stated purpose is analyzing Xcode build logs from DerivedData, but this section expands into inspecting git repository state, workspace paths, worktree locations, branch names, and built app metadata. That broadens access from build-log analysis into source-location and repository-enumeration, which can expose sensitive filesystem paths and development context unrelated to the advertised functionality.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The git inspection logic is not necessary to analyze build logs and causes the skill to enumerate repository state such as branch names and worktree paths. In environments where the skill has broad filesystem access, this creates unnecessary data exposure about local projects, temporary worktrees, and developer workflow that exceeds user expectations for a build-log analyzer.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 291)May include surrounding context.

md
if [ -n "$APP" ]; then
    MTIME="$(stat -f '%Sm' -t '%Y-%m-%d %H:%M' "$APP" 2>/dev/null)"
    VERSION=""
    PLIST="$APP/Info.plist"
    if [ -f "$PLIST" ]; then
      SHORT="$(plutil -extract CFBundleShortVersionString raw "$PLIST" 2>/dev/null)"
      BUILD="$(plutil -extract CFBundleVersion raw "$PLIST" 2>/dev/null)"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 292)May include surrounding context.

md
if [ -n "$APP" ]; then
    MTIME="$(stat -f '%Sm' -t '%Y-%m-%d %H:%M' "$APP" 2>/dev/null)"
    VERSION=""
    PLIST="$APP/Info.plist"
    if [ -f "$PLIST" ]; then
      SHORT="$(plutil -extract CFBundleShortVersionString raw "$PLIST" 2>/dev/null)"
      BUILD="$(plutil -extract CFBundleVersion raw "$PLIST" 2>/dev/null)"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 293)May include surrounding context.

md
if [ -n "$APP" ]; then
    MTIME="$(stat -f '%Sm' -t '%Y-%m-%d %H:%M' "$APP" 2>/dev/null)"
    VERSION=""
    PLIST="$APP/Info.plist"
    if [ -f "$PLIST" ]; then
      SHORT="$(plutil -extract CFBundleShortVersionString raw "$PLIST" 2>/dev/null)"
      BUILD="$(plutil -extract CFBundleVersion raw "$PLIST" 2>/dev/null)"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% 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 · SKILL.md (reported line 294)May include surrounding context.

md
if [ -n "$APP" ]; then
    MTIME="$(stat -f '%Sm' -t '%Y-%m-%d %H:%M' "$APP" 2>/dev/null)"
    VERSION=""
    PLIST="$APP/Info.plist"
    if [ -f "$PLIST" ]; then
      SHORT="$(plutil -extract CFBundleShortVersionString raw "$PLIST" 2>/dev/null)"
      BUILD="$(plutil -extract CFBundleVersion raw "$PLIST" 2>/dev/null)"

Static analysis

No suspicious patterns detected.