Back to skill

Security audit

blender-add-on-development

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for Blender add-on development, but its scaffolding script can turn untrusted add-on metadata into executable Python in generated add-ons.

Install only if you trust the workflow and avoid feeding untrusted project metadata or copied commands into the scaffolder. Before enabling any generated Blender add-on, review the generated Python files, especially __init__.py and ui.py, and prefer a fixed version that serializes metadata with safe Python literals such as repr().

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scaffold_addon.py:38
Finding

Unescaped Add-on Metadata Allows Python Source Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/scaffold_addon.py:38-71 and scripts/scaffold_addon.py:139-163
Vulnerability Type: Generated-code injection through unsafe string interpolation
Risk Level: Medium

Vulnerable Code

python
def build_init_py(
    addon_name: str,
    module_name: str,
    author: str,
    description: str,
    category: str,
    addon_version: tuple[int, int, int],
    blender_min_version: tuple[int, int, int],
) -> str:
    return dedent(
        f'''\
        bl_info = {{
            "name": "{addon_name}",
            "author": "{author}",
            "version": {tuple_literal(addon_version)},
            "blender": {tuple_literal(blender_min_version)},
            "location": "View3D > Sidebar",
            "description": "{description}",
            "warning": "",
            "doc_url": "",
            "category": "{category}",
        }}

        import bpy

        from .operators import classes as operator_classes
        from .ui import classes as ui_classes

        classes = (*operator_classes, *ui_classes)


        def register():
            for cls in classes:
                bpy.utils.register_class(cls)


        def unregister():
            for cls in reversed(classes):
                bpy.utils.unregister_class(cls)


        if __name__ == "__main__":
            register()
        '''
    )

The same unsafe interpolation pattern is used when generating the user-interface module:

python
def build_ui_py(module_name: str, addon_name: str) -> str:
    class_prefix = "".join(part.capitalize() for part in module_name.split("_"))
    return dedent(
        f'''\
        import bpy


        class {class_prefix}_PT_panel(bpy.types.Panel):
            bl_label = "{addon_name}"
            bl_idname = "VIEW3D_PT_{module_name}_panel"
            bl_space_type = "VIEW_3D"
            bl_region_type = "UI"
            bl_category = "Tool"

            def draw(self, context):
                
...[truncated 3843 chars]
Remediation
View remediation

Remediation Suggestions

  1. Generate safe Python literals. Use repr() for every string embedded in generated Python rather than manually surrounding values with quotation marks:
python
def python_string_literal(value: str) -> str:
    return repr(value)

Then construct metadata entries without hard-coded surrounding quotes:

python
bl_info = {{
    "name": {addon_name!r},
    "author": {author!r},
    "version": {tuple_literal(addon_version)},
    "blender": {tuple_literal(blender_min_version)},
    "location": "View3D > Sidebar",
    "description": {description!r},
    "warning": "",
    "doc_url": "",
    "category": {category!r},
}}

Apply the same protection to the generated panel label:

python
bl_label = {addon_name!r}
  1. Validate metadata separately from serialization. Define reasonable maximum lengths and reject NUL bytes and disallowed control characters. Serialization with repr() remains necessary even after validation.

  2. Compile all generated modules before reporting success. After writing the files, invoke Python's compile() function on their contents or run py_compile through its Python API. Avoid relying solely on external post-generation validation.

  3. Fail safely. If validation or compilation fails, remove incomplete generated files or generate into a temporary directory and move the package into place only after every file passes validation.

  4. Add regression tests. Test all metadata parameters with:

    • Double and single quotes.
    • Backslashes.
    • Newline and carriage-return characters.
    • Unicode characters.
    • Strings resembling Python expressions or dictionary terminators.
    • Extremely long input.
  5. Verify behavior, not only syntax. Tests should assert that hostile-looking input appears only as inert string data in the generated abstract syntax tree and never creates additional top-level statements.

Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/scaffold_addon.py (reported line 197)May include surrounding context.

python
parser.add_argument(
        "--force",
        action="store_true",
        help="Overwrite existing files in an existing add-on directory.",
    )
    return parser.parse_args()

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · scripts/scaffold_addon.py (reported line 225)May include surrounding context.

python
if existing:
            names = ", ".join(path.name for path in existing)
            raise FileExistsError(
                f"Refusing to overwrite existing files: {names}. Use --force to overwrite."
            )

    write_text(

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to run local commands that create and modify files, such as scaffolding an add-on package and compiling changed Python files, but it does not declare any explicit tool restrictions or permissions. This creates an authorization gap: in environments that rely on skill metadata for enforcement or review, the agent may perform file-writing actions broader than a user or platform expects.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.