Security Audit
PabloLION/bmad-plugin:plugins/bmad/skills/bmad-module-builder
github.com/PabloLION/bmad-pluginTrust Assessment
PabloLION/bmad-plugin:plugins/bmad/skills/bmad-module-builder received a trust score of 10/100, placing it in the Untrusted category. This skill has significant security findings that require attention before use in production.
SkillShield's automated analysis identified 31 findings: 15 critical, 15 high, 1 medium, and 0 low severity. Key findings include Arbitrary command execution, Unsafe deserialization / dynamic eval, Dangerous call: subprocess.run().
The analysis covered 4 layers: Manifest Analysis, Static Code Analysis, Dependency Graph, LLM Behavioral Safety. The Manifest Analysis layer scored lowest at 0/100, indicating areas for improvement.
Last analyzed on April 11, 2026 (commit 17efb6ce). SkillShield performs automated 4-layer security analysis on AI skills and MCP servers.
Layer Breakdown
Behavioral Risk Signals
Security Findings31
| Severity | Finding | Layer | Location | |
|---|---|---|---|---|
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py:45 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py:166 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py:194 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:47 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:174 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:195 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:216 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-validate-module.py:45 | |
| CRITICAL | Arbitrary command execution Python shell execution (os.system, subprocess) Review all shell execution calls. Ensure commands are static (not built from user input), use absolute paths, and are strictly necessary. Prefer library APIs over shell commands. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-validate-module.py:274 | |
| CRITICAL | Arbitrary Directory Deletion via User-Controlled Path The `scripts/scaffold-setup-skill.py` script uses `shutil.rmtree(target)` where `target` is constructed from user-provided `--target-dir` and `--module-code`. An attacker could provide a malicious `target-dir` (e.g., `/`) and `module-code` (e.g., `etc`) to attempt to delete arbitrary directories on the system (e.g., `/bmad-etc-setup`). While `module-code` is typically short, the `target-dir` argument is directly used and validated only for existence, not safety. Implement strict validation for `--target-dir` to ensure it is within an allowed, non-sensitive directory (e.g., a temporary directory or a user-specific skill development folder). Use `Path.is_relative_to()` or similar checks against a known safe base path. Alternatively, if the intent is to only remove the *specific* directory created by the script, ensure the path is fully controlled by the script's internal logic and not directly influenced by user input in a way that allows path traversal or arbitrary targeting. | Static | scripts/scaffold-setup-skill.py:60 | |
| CRITICAL | Arbitrary Directory Deletion via User-Controlled Path The `assets/setup-skill-template/scripts/cleanup-legacy.py` script uses `shutil.rmtree(target)` where `target` is constructed from user-provided `--bmad-dir` and directory names from `--also-remove` or derived from `--module-code`. An attacker could provide a malicious `bmad-dir` (e.g., `/`) and `also-remove` (e.g., `etc`) to attempt to delete arbitrary directories (e.g., `/etc`). The `verify_skills_installed` function does not fully mitigate this, as it only checks for skill directories and non-skill directories can still be targeted for deletion. Implement strict validation for `--bmad-dir` and `--also-remove` to ensure paths are within an allowed, non-sensitive directory. Use `Path.is_relative_to()` or similar checks against a known safe base path. Avoid allowing user input to directly influence paths used in destructive operations like `shutil.rmtree`. | Static | assets/setup-skill-template/scripts/cleanup-legacy.py:176 | |
| CRITICAL | Arbitrary File Deletion via User-Controlled Path The `assets/setup-skill-template/scripts/merge-config.py` script's `cleanup_legacy_configs` function uses `legacy_path.unlink()` where `legacy_path` is constructed from user-provided `--legacy-dir` and `module_code`. An attacker could provide a malicious `legacy-dir` (e.g., `/`) and `module-code` (e.g., `etc`) to attempt to delete arbitrary files (e.g., `/etc/config.yaml`). Implement strict validation for `--legacy-dir` and `module_code` to ensure paths are within an allowed, non-sensitive directory. Use `Path.is_relative_to()` or similar checks against a known safe base path. Avoid allowing user input to directly influence paths used in destructive operations like `Path.unlink()`. | Static | assets/setup-skill-template/scripts/merge-config.py:197 | |
| CRITICAL | Arbitrary File Deletion via User-Controlled Path The `assets/setup-skill-template/scripts/merge-help-csv.py` script's `cleanup_legacy_csvs` function uses `legacy_path.unlink()` where `legacy_path` is constructed from user-provided `--legacy-dir` and `module_code`. An attacker could provide a malicious `legacy-dir` (e.g., `/`) and `module-code` (e.g., `etc`) to attempt to delete arbitrary files (e.g., `/etc/module-help.csv`). Implement strict validation for `--legacy-dir` and `module_code` to ensure paths are within an allowed, non-sensitive directory. Use `Path.is_relative_to()` or similar checks against a known safe base path. Avoid allowing user input to directly influence paths used in destructive operations like `Path.unlink()`. | Static | assets/setup-skill-template/scripts/merge-help-csv.py:190 | |
| CRITICAL | Arbitrary File Deletion via User-Controlled Path The `assets/standalone-module-template/merge-config.py` script's `cleanup_legacy_configs` function uses `legacy_path.unlink()` where `legacy_path` is constructed from user-provided `--legacy-dir` and `module_code`. An attacker could provide a malicious `legacy-dir` (e.g., `/`) and `module-code` (e.g., `etc`) to attempt to delete arbitrary files (e.g., `/etc/config.yaml`). This file is identical to the one in `setup-skill-template`. Implement strict validation for `--legacy-dir` and `module_code` to ensure paths are within an allowed, non-sensitive directory. Use `Path.is_relative_to()` or similar checks against a known safe base path. Avoid allowing user input to directly influence paths used in destructive operations like `Path.unlink()`. | Static | assets/standalone-module-template/merge-config.py:197 | |
| CRITICAL | Arbitrary File Deletion via User-Controlled Path The `assets/standalone-module-template/merge-help-csv.py` script's `cleanup_legacy_csvs` function uses `legacy_path.unlink()` where `legacy_path` is constructed from user-provided `--legacy-dir` and `module_code`. An attacker could provide a malicious `legacy-dir` (e.g., `/`) and `module-code` (e.g., `etc`) to attempt to delete arbitrary files (e.g., `/etc/module-help.csv`). This file is identical to the one in `setup-skill-template`. Implement strict validation for `--legacy-dir` and `module_code` to ensure paths are within an allowed, non-sensitive directory. Use `Path.is_relative_to()` or similar checks against a known safe base path. Avoid allowing user input to directly influence paths used in destructive operations like `Path.unlink()`. | Static | assets/standalone-module-template/merge-help-csv.py:190 | |
| HIGH | Unsafe deserialization / dynamic eval Decryption followed by code execution Remove obfuscated code execution patterns. Legitimate code does not need base64-encoded payloads executed via eval, encrypted-then-executed blobs, or dynamic attribute resolution to call system functions. | Manifest | plugins/bmad/skills/bmad-module-builder/assets/setup-skill-template/scripts/cleanup-legacy.py:18 | |
| HIGH | Unsafe deserialization / dynamic eval Decryption followed by code execution Remove obfuscated code execution patterns. Legitimate code does not need base64-encoded payloads executed via eval, encrypted-then-executed blobs, or dynamic attribute resolution to call system functions. | Manifest | plugins/bmad/skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-config.py:19 | |
| HIGH | Unsafe deserialization / dynamic eval Decryption followed by code execution Remove obfuscated code execution patterns. Legitimate code does not need base64-encoded payloads executed via eval, encrypted-then-executed blobs, or dynamic attribute resolution to call system functions. | Manifest | plugins/bmad/skills/bmad-module-builder/assets/setup-skill-template/scripts/merge-help-csv.py:16 | |
| HIGH | Unsafe deserialization / dynamic eval Decryption followed by code execution Remove obfuscated code execution patterns. Legitimate code does not need base64-encoded payloads executed via eval, encrypted-then-executed blobs, or dynamic attribute resolution to call system functions. | Manifest | plugins/bmad/skills/bmad-module-builder/assets/standalone-module-template/merge-config.py:19 | |
| HIGH | Unsafe deserialization / dynamic eval Decryption followed by code execution Remove obfuscated code execution patterns. Legitimate code does not need base64-encoded payloads executed via eval, encrypted-then-executed blobs, or dynamic attribute resolution to call system functions. | Manifest | plugins/bmad/skills/bmad-module-builder/assets/standalone-module-template/merge-help-csv.py:16 | |
| HIGH | Unsafe deserialization / dynamic eval Decryption followed by code execution Remove obfuscated code execution patterns. Legitimate code does not need base64-encoded payloads executed via eval, encrypted-then-executed blobs, or dynamic attribute resolution to call system functions. | Manifest | plugins/bmad/skills/bmad-module-builder/scripts/validate-module.py:15 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'run_scaffold'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py:45 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'test_missing_target_dir'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py:166 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'test_missing_source_file'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-setup-skill.py:194 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'run_scaffold'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:47 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'test_missing_skill_dir'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:174 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'test_missing_skill_md'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:195 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'test_missing_module_yaml'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-scaffold-standalone-module.py:216 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'run_validate'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-validate-module.py:45 | |
| HIGH | Dangerous call: subprocess.run() Call to 'subprocess.run()' detected in function 'test_nonexistent_directory'. This can execute arbitrary code. Avoid using dangerous functions like exec/eval/os.system. Use safer alternatives. | Static | plugins/bmad/skills/bmad-module-builder/scripts/tests/test-validate-module.py:274 | |
| MEDIUM | Untrusted Content in Generated marketplace.json The `scripts/scaffold-standalone-module.py` script generates a `marketplace.json` file using `module_description` and `module_version` extracted from the user's `module.yaml` file. While `json.dumps` escapes the content, if this `marketplace.json` is later consumed by a system (e.g., a UI, a build script, or another LLM) that does not properly sanitize or escape these fields, it could lead to prompt injection, cross-site scripting (if rendered in a web context), or other data manipulation. The extraction of `module_description` and `module_version` is done via basic string parsing, which could also be brittle. Ensure that any system consuming the generated `marketplace.json` properly sanitizes and escapes all fields derived from untrusted input before display or execution. Consider adding more robust validation or sanitization to the `module_description` and `module_version` during extraction or before writing to `marketplace.json` if the downstream consumption cannot be guaranteed to be safe. | LLM | scripts/scaffold-standalone-module.py:146 |
Scan History
Embed Code
[](https://skillshield.io/report/11a9a2deadae7d96)
Powered by SkillShield