Back to skill

Security audit

Airfoil

Security checks for vulnerabilities and agentic risk

Overview

This Airfoil audio-control skill is coherent, but its bundled script handles speaker names unsafely enough that a crafted name could run local commands.

Review this skill before installing. It appears intended for local Airfoil speaker control and does not show hidden persistence or data exfiltration, but the bundled script should be fixed to pass speaker names and volume values as AppleScript arguments and validate volume ranges before use. Avoid using it with untrusted speaker names or agent-generated arguments until that is corrected.

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
airfoil.sh:23
Finding
AppleScript Injection Through Unescaped Speaker Names<![CDATA[ ## Vulnerability Details **File Location**: `airfoil.sh`, lines 23, 33, and 45 **Vulnerability Type**: AppleScript injection leading to arbitrary command execution **Risk Level**: High ### Vulnerable Code ```bash osascript -e "tell application \"Airfoil\" to connect to (first speaker whose name is \"$SPEAKER\")" ``` ```bash osascript -e "tell application \"Airfoil\" to disconnect from (first speaker whose name is \"$SPEAKER\")" ``` ```bash osascript -e "tell application \"Airfoil\" to set (volume of (first speaker whose name is \"$SPEAKER\")) to $VOL" ``` ### Technical Analysis The script reads the speaker name from its second command-line argument: ```bash SPEAKER="$2" ``` Although the shell variable is enclosed in shell double quotes, its contents are inserted directly into dynamically constructed AppleScript source. Shell quoting does not escape the value for the AppleScript language. A speaker name containing an AppleScript quotation mark and additional syntax can terminate the intended string literal and introduce new AppleScript statements. AppleScript supports security-sensitive operations such as `do shell script`, so successful injection can cross from speaker selection into arbitrary local command execution. The vulnerable pattern is present in the `connect`, `disconnect`, and `volume` commands. No allowlist, escaping routine, or positional AppleScript argument handling protects these execution paths. ### Attack Path 1. An attacker controls or influences the speaker-name argument supplied to `airfoil.sh`, including through an AI-generated tool invocation. 2. The attacker supplies a crafted value that closes the AppleScript string literal, adds an unintended AppleScript statement, and neutralizes or syntactically balances the remaining source. 3. Bash substitutes the crafted value into the string passed to `osascript -e`. 4. `osascript` parses the injected content as executable AppleScript rather than as speaker-name data. 5. The i ...[truncated 935 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not concatenate speaker names into AppleScript source. Pass untrusted values as positional arguments and read them through an `on run argv` handler. For example: ```bash osascript - "$SPEAKER" <<'APPLESCRIPT' on run argv set requestedSpeaker to item 1 of argv tell application "Airfoil" connect to (first speaker whose name is requestedSpeaker) end tell end run APPLESCRIPT ``` Apply the same pattern to `disconnect` and `volume`. For volume, pass both the speaker and validated numeric volume as arguments rather than inserting either value into source code. Additional hardening should include: 1. Reject speaker names containing control characters. 2. Optionally retrieve the names of known speakers and require an exact match before performing an action. 3. Keep executable AppleScript static; treat every command-line value strictly as data. 4. Return a nonzero status when a speaker does not exist. 5. Run the skill with only the minimum Automation and Accessibility permissions necessary. 6. Add regression tests using names containing quotation marks, backslashes, line breaks, and AppleScript metacharacters. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
airfoil.sh:38
Finding
Missing Numeric and Range Validation for Volume Input<![CDATA[ ## Vulnerability Details **File Location**: `airfoil.sh`, lines 38–46 **Vulnerability Type**: Improper input validation **Risk Level**: Low ### Vulnerable Code ```bash volume) if [[ -z "$SPEAKER" ]] || [[ -z "$VALUE" ]]; then echo "Usage: $0 volume <speaker> <0-100>" >&2 exit 1 fi # Convert 0-100 to 0.0-1.0 for Airfoil's internal scale VOL=$(echo "scale=2; $VALUE / 100" | bc) osascript -e "tell application \"Airfoil\" to set (volume of (first speaker whose name is \"$SPEAKER\")) to $VOL" echo "Volume $SPEAKER: $VALUE%" ;; ``` ### Technical Analysis The documented volume range is 0 through 100, but the implementation only checks whether a value was supplied. It does not verify that the input is an integer or that it falls within the permitted range. The unvalidated value is inserted into a `bc` expression. Malformed input can cause calculation errors, and negative or excessive numeric values can produce values outside Airfoil's expected 0.0–1.0 scale. The result is then inserted into AppleScript source. Because the script enables `set -e`, a failed `bc` operation or subsequent AppleScript error can terminate the command unexpectedly. The lack of validation also creates inconsistent behavior between the documented interface and the actual implementation. ### Attack Path 1. A user, attacker, or calling agent invokes `airfoil.sh volume` with a malformed, negative, or greater-than-100 value. 2. The script accepts the value because it checks only for an empty argument. 3. The value is processed by `bc`, potentially producing an error or an out-of-range result. 4. The result is passed to Airfoil through `osascript`. 5. The operation may terminate unexpectedly or attempt an unintended volume setting. ### Impact Assessment The primary impact is limited to application behavior and availability: - Unexpected termination of the requested operation. - Out-of-range or unintended speaker volume changes if accepte ...[truncated 239 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate the value before invoking `bc` or `osascript`: ```bash if [[ ! "$VALUE" =~ ^[0-9]+$ ]] || (( VALUE < 0 || VALUE > 100 )); then echo "Error: volume must be an integer from 0 to 100" >&2 exit 1 fi ``` Avoid constructing arithmetic language source from untrusted input. After strict integer validation, Bash arithmetic can perform the conversion, or the validated value can be passed as an AppleScript positional argument and divided inside a static script. Recommended hardening steps: 1. Require an integer matching `^[0-9]+$`. 2. Enforce the inclusive range `0–100`. 3. Pass the validated value to AppleScript through `argv`. 4. Check calculation and `osascript` failures explicitly. 5. Print a success message only after Airfoil confirms that the setting was applied. 6. Add tests for empty, nonnumeric, negative, decimal, and greater-than-100 inputs. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill description presents speaker control as convenient automation but does not warn users that commands can immediately reroute audio, disconnect active speakers, or alter volume on shared devices. Without an upfront warning, users may invoke the skill in inappropriate contexts and unexpectedly disrupt meetings, media playback, or other shared listening environments.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The invocation examples use broad natural-language phrases like 'Turn the music down' and 'Which speakers are on?' that can plausibly occur in ordinary conversation and be mapped to immediate device-control actions. In a voice- or chat-driven agent context, this increases the risk of accidental activation that changes audio routing or volume without explicit user confirmation.

Static analysis

No suspicious patterns detected.