T09 · Insecure Skill Coding Practices
- Location
scripts/package_cached_electron_macos.sh:28- Finding
Overly Broad Project Copy Can Expose Sensitive Files in Packaged Applications
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly coherent for packaging local web apps, but its macOS fallback packager can bundle too much project data and trusts a supplied Electron archive without enforcing integrity checks.
Review this skill before installing if you may package projects containing secrets. Prefer the normal electron-builder path with an explicit files allowlist, inspect the final bundle contents before distribution, and only use the cached macOS fallback with a verified Electron archive that exactly matches the intended version and architecture.
scripts/package_cached_electron_macos.sh:28Overly Broad Project Copy Can Expose Sensitive Files in Packaged Applications
scripts/package_cached_electron_macos.sh:9Cached Electron Runtime Is Not Verified for Integrity, Version, or Architecture
The supplied code chunk is a shell test script, not packaging logic. It creates temporary sample projects, writes HTML/CSS/JS and Electron-related files, calls inspect_web_app.sh on them, and asserts expected analysis results with grep. It does not package an existing site into an Electron application, build installers, or emit macOS/Windows app artifacts. Its primary purpose is validating inspection behavior, including identifying static multi-page apps, local storage usage, and remote backend references. That is materially different from the declared packaging purpose.
The skill description and usage examples are entirely in Chinese, including the invocation phrasing, with no indication that other languages are supported or that Chinese is required for a justified regional purpose. This can violate language/locale policy because it implicitly constrains users to a specific language without opt-in.
Without declared permissions the skill's intent is opaque and cannot be validated.
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.
cp "$project_dir/build/icon.icns" "$output_app/Contents/Resources/electron.icns"
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
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.
cp "$project_dir/build/icon.icns" "$output_app/Contents/Resources/electron.icns"
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
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.
cp "$project_dir/build/icon.icns" "$output_app/Contents/Resources/electron.icns"
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
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.
cp "$project_dir/build/icon.icns" "$output_app/Contents/Resources/electron.icns"
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
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.
cp "$project_dir/build/icon.icns" "$output_app/Contents/Resources/electron.icns"
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
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.
cp "$project_dir/build/icon.icns" "$output_app/Contents/Resources/electron.icns"
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
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.
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $app_version" "$plist"
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.
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $app_version" "$plist"
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.
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $app_version" "$plist"
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.
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $app_version" "$plist"
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.
fi
plist="$output_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $app_name" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $app_id" "$plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $app_version" "$plist"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
printf '%s\n' "const { app } = require('electron'); const db = app.getPath('userData') + '/notes.json';" > "$storage_dir/main.cjs"
printf '%s\n' "contextBridge.exposeInMainWorld('notes', { list: () => ipcRenderer.invoke('notes:list') });" > "$storage_dir/preload.cjs"
printf '%s\n' '<script>fetch("https://api.example.test/notes")</script>' > "$remote_dir/index.html"
static_out="$($skill_dir/scripts/inspect_web_app.sh "$static_dir")"
storage_out="$($skill_dir/scripts/inspect_web_app.sh "$storage_dir")"
The manifest presents the skill name and description in Chinese while the default prompt is hard-coded in English. This creates a locale/language policy concern because the skill appears to force an English interaction path without explicit user opt-in or a documented language choice.
No suspicious patterns detected.