Back to skill

Security audit

Novel Character Profile Builder

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Chinese fiction-character profile tool, but its bundled workflow code contains unsafe configuration-driven execution and file-move/delete risks that warrant review before installation.

Install only if you are comfortable giving the skill read/write access to a dedicated LoreBible writing workspace. Avoid running it on broad project or home directories, avoid --no-confirm and quick_creation on important existing work, and treat workflow/session JSON files as trusted local state because tampering could lead to code execution or unintended file moves/deletions.

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
scripts/subagent_orchestrator.py:247
Finding
Arbitrary Python Code Execution Through Untrusted Workflow Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/subagent_orchestrator.py`, lines 117-122 and 247-260 **Vulnerability Type**: Configuration-driven dynamic import and unsafe expression evaluation **Risk Level**: High ### Vulnerable Code ```python module_name = agent_config["module"] class_name = agent_config["class"] # Dynamic module import module = importlib.import_module(module_name.replace('/', '.')) agent_class = getattr(module, class_name) ``` ```python def _evaluate_condition(self, condition: str) -> bool: """Evaluate a condition expression.""" try: if condition == "user_confirmed == true": return self.context.get("user_confirmed", False) is True elif condition == "is_valid == true": return self.context.get("is_valid", False) is True else: local_vars = {**self.context} for task_id, result in self.results.items(): local_vars.update(result.outputs) return eval(condition, {}, local_vars) except Exception as e: logger.warning(f"Failed to evaluate condition '{condition}': {e}") return False ``` ### Technical Analysis `SubagentOrchestrator` accepts a configurable workflow file and uses values from that file to control two executable Python mechanisms: 1. Agent module and class names are passed to `importlib.import_module()` and `getattr()`. 2. Workflow condition strings are passed directly to Python's `eval()`. Passing an empty dictionary as the globals argument to `eval()` does not reliably create a secure sandbox. Python can populate built-ins, allowing a malicious expression to access functions such as `__import__` and then invoke operating-system or file APIs. Context objects and task outputs also become available as local variables, increasing the available attack surface. The dynamic import path independently permits execution of module-level code when a configuration identifies an attacker-controlled impo ...[truncated 1563 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `eval()` entirely and implement a strict condition parser. - Permit only predefined predicates such as `user_confirmed` and `is_valid`. - Permit only explicitly supported equality or Boolean operations. - Reject unknown identifiers, function calls, attribute access, indexing, and imports. 2. Replace configuration-controlled imports with an in-code allowlist: ```python AGENT_CLASSES = { "lore_bible_manager": LoreBibleManager, "conflict_detector": ConflictDetector, "profile_generator": CharacterProfileGenerator, } ``` 3. Do not accept arbitrary module or class names from workflow JSON. 4. Validate workflow files against a restrictive JSON schema before loading them. 5. Require workflow configuration files to be stored in a trusted directory with appropriate ownership and permissions. 6. If custom workflows are required, parse expressions with `ast.parse()` and allow only a minimal set of safe AST nodes; do not compile or evaluate arbitrary syntax. 7. Add regression tests using malicious conditions and module names to verify that configuration cannot invoke imports, functions, attributes, or system commands. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/profile_session.py:272
Finding
Tampered Session State Can Move or Delete Arbitrary Accessible Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/profile_session.py`, lines 272-286, 311-316, and 421-449; `scripts/lore_bible_manager.py`, lines 297-328 **Vulnerability Type**: Missing path-containment validation for persisted temporary-file paths **Risk Level**: Medium ### Vulnerable Code ```python def confirm_and_move(self) -> Optional[Path]: """Move the profile after user confirmation.""" try: if not self.session_data.temp_file_path: logger.error("Temporary file path does not exist") return None temp_path = Path(self.session_data.temp_file_path) if not temp_path.exists(): logger.error(f"Temporary file does not exist: {temp_path}") return None from lore_bible_manager import LoreBibleManager manager = LoreBibleManager(self.config.workspace) final_path = manager.move_to_characters( temp_path, self.config.character_name ) ``` ```python def cancel(self) -> bool: """Cancel the session and clean up the temporary file.""" try: if self.session_data.temp_file_path: temp_path = Path(self.session_data.temp_file_path) if temp_path.exists(): temp_path.unlink() logger.info(f"Deleted temporary file: {temp_path}") ``` ```python with open(session_file, 'r', encoding='utf-8') as f: data = json.load(f) session.session_data = SessionData( session_id=session_id, config=config, status=SessionStatus(data.get("status", "created")), created_at=data.get("created_at", time.time()), updated_at=data.get("updated_at", time.time()), temp_file_path=data.get("temp_file_path"), final_file_path=data.get("final_file_path"), conflicts=data.get("conflicts", []), validation_results=data.get("validation_results", []), user_notes=data.get("user_notes", ""), metadata=data.get("metadata", {}) ) ``` The destination manager ultimately perf ...[truncated 2787 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve and validate the temporary path before every move or deletion: ```python prepare_dir = (Path(self.config.workspace).resolve() / "00_Prepare").resolve() temp_path = Path(self.session_data.temp_file_path).resolve(strict=True) if not temp_path.is_relative_to(prepare_dir): raise ValueError("Temporary file is outside the workspace preparation directory") ``` 2. Perform the same containment validation inside `LoreBibleManager.move_to_characters()` so callers cannot bypass the session-layer check. 3. Reject symbolic links and require the source to be a regular file: ```python if temp_path.is_symlink() or not temp_path.is_file(): raise ValueError("Invalid temporary profile") ``` 4. Require the `.md` extension and enforce the expected `temp_<safe-name>_<session-id>.md` naming format. 5. Do not persist or trust arbitrary absolute paths. Reconstruct the temporary path from the trusted workspace and validated session identifier. 6. Validate session identifiers against a strict format, such as eight hexadecimal characters, before constructing session filenames. 7. Use defensive file operations that avoid race conditions where possible, and recheck containment immediately before mutation. 8. Restrict `.sessions` directory permissions to the owning user. 9. Add tests for absolute paths, `..` traversal, symbolic links, malformed session identifiers, and modified session JSON referencing files outside `00_Prepare`. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (49)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented behavior includes directory creation, markdown scanning/parsing, temporary persistence, cleanup, and file moves, which materially exceed a simple profile-builder description. When a skill understates these actions, users and policy systems may authorize it under false assumptions, enabling unintended file operations in sensitive workspaces.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The documented behavior includes directory creation, markdown scanning/parsing, temporary persistence, cleanup, and file moves, which materially exceed a simple profile-builder description. When a skill understates these actions, users and policy systems may authorize it under false assumptions, enabling unintended file operations in sensitive workspaces.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented behavior includes directory creation, markdown scanning/parsing, temporary persistence, cleanup, and file moves, which materially exceed a simple profile-builder description. When a skill understates these actions, users and policy systems may authorize it under false assumptions, enabling unintended file operations in sensitive workspaces.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented behavior includes directory creation, markdown scanning/parsing, temporary persistence, cleanup, and file moves, which materially exceed a simple profile-builder description. When a skill understates these actions, users and policy systems may authorize it under false assumptions, enabling unintended file operations in sensitive workspaces.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented behavior includes directory creation, markdown scanning/parsing, temporary persistence, cleanup, and file moves, which materially exceed a simple profile-builder description. When a skill understates these actions, users and policy systems may authorize it under false assumptions, enabling unintended file operations in sensitive workspaces.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
python scripts/generate_profile.py --name "李四" --age "30" --workspace "/path/to/lorebible"

# 跳过用户确认
python scripts/generate_profile.py --name "王五" --workspace "/path/to/lorebible" --no-confirm

# 指定模板类型
python scripts/generate_profile.py --name "赵六" --type "protagonist" --workspace "/path/to/lorebible"
Confidence
91% confidence
Finding
The --no-confirm parameter explicitly suppresses a user-review control before files are moved into the final workspace, creating a straightforward path for unsafe file operations. In a skill that can create directories, persist temporary artifacts, scan workspaces, and manage final output locations, such a flag can be abused to cause unauthorized or unnoticed changes to project data.

Ae1

High
Category
analysis-evasion
Content
1. **`lore_bible_manager.py`** - LoreBible目录管理和角色扫描
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
except Exception as e:
                logger.error(f"加载规则文件失败: {e}")

        return rules

    def set_character_index(self, character_index: Dict):
        """设置角色信息索引
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
parser.add_argument('--role', help='故事中的角色')
        parser.add_argument('--output', '-o', help='输出文件路径')
        parser.add_argument('--workspace', '-w', help='工作目录路径,启用LoreBible管理功能')
        parser.add_argument('--no-confirm', action='store_true', help='跳过用户确认(仅增强模式)')
        parser.add_argument('--interactive', '-i', action='store_true', help='交互模式')

        args = parser.parse_args()
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
parser.add_argument('--role', help='故事中的角色')
        parser.add_argument('--output', '-o', help='输出文件路径')
        parser.add_argument('--workspace', '-w', help='工作目录路径,启用LoreBible管理功能')
        parser.add_argument('--no-confirm', action='store_true', help='跳过用户确认(仅增强模式)')
        parser.add_argument('--interactive', '-i', action='store_true', help='交互模式')

        args = parser.parse_args()
Confidence
85% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
if sys.argv[i] == "--template" and i + 1 < len(sys.argv):
            template_type = sys.argv[i + 1]
            i += 2
        elif sys.argv[i] == "--no-confirm":
            require_confirmation = False
            i += 1
        else:
Confidence
85% confidence
Finding
Accepting a user-controlled --no-confirm parameter lets callers suppress an explicit confirmation control designed to prevent accidental or unauthorized finalization of content. In this skill context, the tool manages workspace files and can save/move character profiles, so bypassing confirmation increases the chance of unreviewed writes in automated runs.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
Agent module and class loading is delegated to configuration, so the orchestration layer can be repurposed to import unintended components and execute their initialization code. Because Python imports execute top-level module code, this creates an arbitrary code-loading surface that is broader than necessary for a character-profile builder.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
Workflow conditions are treated as executable Python instead of declarative data, allowing arbitrary code execution from configuration. In a writing-assistant skill, there is no legitimate need for conditions to have full interpreter access, so the feature sharply increases risk without matching the product scope.

eval() call detected

High
Category
Dangerous Code Execution
Content
for task_id, result in self.results.items():
                    local_vars.update(result.outputs)

                return eval(condition, {}, local_vars)
        except Exception as e:
            logger.warning(f"评估条件失败 '{condition}': {e}")
            return False
Confidence
99% confidence
Finding
Using eval() on workflow condition strings executes arbitrary Python expressions in the current process. Any attacker who can influence workflow definitions or condition text can run code, access files, or manipulate process state, making this a direct code-execution risk.

Missing User Warnings

High
Confidence
95% confidence
Finding
The generate_and_save path explicitly disables confirmation and writes final output through enhanced generation logic, enabling silent file creation or overwrite if downstream components do so. In an agentic workflow, non-interactive persistence increases the risk of unintended file modification, especially when combined with configurable workspace inputs and autonomous task execution.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill explicitly instructs filesystem interaction such as accessing the user's working directory, saving markdown files, creating directories, and scanning existing files, but it declares no corresponding tool scope or permissions. This creates a transparency and least-privilege failure: an agent could perform file reads/writes the user was not clearly told to expect, increasing risk of unintended data exposure or modification.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The workflow tells the agent to access and switch into the user's working directory without any prominent warning, consent gate, or path limitation. In a writing-assistant context, users may reasonably expect text generation, not immediate filesystem access, so this can lead to accidental exposure of unrelated project files or unintended modification of local content.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The enhanced mode documents automatic directory creation and scanning of existing character files, but does not clearly warn users that preexisting workspace contents may be enumerated and processed. This increases privacy and integrity risk because the skill can inspect or alter an existing lore repository under the guise of routine character-profile generation.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
A documented mode that skips user confirmation before moving generated profiles into final directories removes an important review checkpoint, especially where files may overwrite, rename, or pollute existing project structure. In a workspace-management context, bypassing review increases the chance of silent bad writes and makes accidental misuse easier.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
python scripts/generate_profile.py --name "李四" --age "30" --workspace "/path/to/lorebible"

# 跳过用户确认
python scripts/generate_profile.py --name "王五" --workspace "/path/to/lorebible" --no-confirm

# 指定模板类型
python scripts/generate_profile.py --name "赵六" --type "protagonist" --workspace "/path/to/lorebible"
Confidence
65% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
python scripts/generate_profile.py --name "李四" --age "30" --workspace "/path/to/lorebible"

# 跳过用户确认
python scripts/generate_profile.py --name "王五" --workspace "/path/to/lorebible" --no-confirm

# 指定模板类型
python scripts/generate_profile.py --name "赵六" --type "protagonist" --workspace "/path/to/lorebible"
Confidence
65% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
python scripts/generate_profile.py --name "李四" --age "30" --workspace "/path/to/lorebible"

# 跳过用户确认
python scripts/generate_profile.py --name "王五" --workspace "/path/to/lorebible" --no-confirm

# 指定模板类型
python scripts/generate_profile.py --name "赵六" --type "protagonist" --workspace "/path/to/lorebible"
Confidence
65% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This JSON manifest uses Chinese-only natural-language values for rule names and descriptions throughout the file, including metadata, which indicates a fixed language/locale assumption. The file does not offer any user language choice or explain that the skill is intentionally region-specific, so it may violate organizational language/locale policy.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
Natural-language fields throughout the file, including workflow names, task names, and descriptions, are entirely in Chinese, with no indication that the skill offers a language choice or is intentionally restricted to a Chinese-language audience. That creates a locale policy concern because the configuration appears to enforce a specific language by default.

Vague Triggers

Medium
Confidence
85% confidence
Finding
The quick_creation workflow explicitly skips validation steps present in the safer path, yet the trigger context and guardrails for when this shortcut is allowed are not defined in this file. In a content-generation workflow that writes files into a workspace, this increases the chance of inconsistent, conflicting, or improperly placed output being saved without review, especially if untrusted or malformed character data is supplied.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/subagent_orchestrator.py:260