Back to skill

Security audit

Forge 🔨 Repair-Inspect Loop

Security checks for vulnerabilities and agentic risk

Overview

Forge is a coherent repair-automation skill, but users should review it carefully because it persists model-generated repair patterns across projects and can automatically run a repository-provided Python checker.

Install only if you are comfortable with an automated repair workflow that writes project state, creates task/result files, may direct agents to edit and test code, and advertises auto-commit behavior. Avoid using it on untrusted repositories unless you disable or remove automatic doc-sync checker execution and isolate or review cross-project reflections before they are reused.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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)

T02 · Agent Memory Poisoning

Error
Location
scripts/forge.py:535
Finding
Untrusted Repair Reports Can Poison Cross-Project Agent Memory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/forge.py:535-560` **Vulnerability Type**: Persistent cross-project prompt and memory poisoning **Risk Level**: High ### Vulnerable Code ```python # Save repair pattern to reflections (two-layer) pattern = report.get("repair_pattern", {}) if pattern and pattern.get("pattern_name"): # Project layer: full detail (file names, paths, project-specific context) project_reflections = Path(state["workdir"]) / "forge-reflections.jsonl" with open(project_reflections, "a") as f: f.write(json.dumps(pattern, ensure_ascii=False) + "\n") # Universal layer: extract abstract pattern (no project-specific paths/filenames) universal_pattern = extract_universal_pattern(pattern) if universal_pattern: universal_dir = FORGE_DIR / "reflections" universal_dir.mkdir(parents=True, exist_ok=True) universal_file = universal_dir / "patterns.jsonl" # Dedup: skip if pattern_name already exists existing_names = set() if universal_file.exists(): try: for line in universal_file.read_text().strip().split("\n"): if line.strip(): existing_names.add(json.loads(line).get("pattern_name", "")) except Exception: pass if universal_pattern["pattern_name"] not in existing_names: with open(universal_file, "a") as f: f.write(json.dumps(universal_pattern, ensure_ascii=False) + "\n") ``` The persistent records are subsequently read at `scripts/forge.py:256-284`, and fields such as `pattern_name` and `solution_template` are inserted into prompts generated for future repair agents. ### Technical Analysis Forge treats the repair report as trusted even though it is generated by an LLM operating on potentially attacker-controlled project fi ...[truncated 2599 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable cross-project promotion of model-generated reflections by default. 2. Keep reflections isolated per project or per explicitly defined trust domain. 3. Require explicit human approval before adding any record to universal storage. 4. Replace free-form reflection fields with a strict schema containing short, declarative, allowlisted values. 5. Reject content containing prompt delimiters, role declarations, tool instructions, shell commands, paths, URLs, or imperative agent directives. 6. Treat all reflection text as untrusted data in generated prompts. Clearly delimit and label it as non-authoritative reference material that must never override system, user, or safety instructions. 7. Store provenance metadata, including the source project, task, report hash, creation time, and approval identity. 8. Apply length limits and canonicalization before validation and persistence. 9. Protect the universal reflection file from writes by ordinary repair workflows. 10. Review and purge existing universal patterns before deploying the corrected implementation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/forge.py:836
Finding
Summary Generation Automatically Executes Repository-Controlled Python Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/forge.py:836-854` **Vulnerability Type**: Arbitrary local code execution from an untrusted project **Risk Level**: High ### Vulnerable Code ```python # Method 1: Run doc-sync-checker.py if it exists checker = workdir / "scripts" / "tools" / "doc-sync-checker.py" if checker.exists(): try: result = subprocess.run( [sys.executable, str(checker), "--json"], capture_output=True, text=True, cwd=str(workdir), timeout=30 ) if result.returncode == 0 and result.stdout.strip(): try: report = json.loads(result.stdout.strip()) stale = report.get("stale", []) for item in stale: doc = item.get("doc", "?") authority = item.get("authority", "?") warnings.append(f"{doc} 可能落后于 {authority}") except json.JSONDecodeError: pass except (subprocess.TimeoutExpired, Exception): pass ``` ### Technical Analysis The `check_doc_sync()` function searches the target repository for `scripts/tools/doc-sync-checker.py` and executes it with the same Python interpreter and operating-system privileges as Forge. File existence is the only prerequisite. The target project is not necessarily trusted. A repository author can place arbitrary Python code at the expected path. Calling `summary`, or reaching the completion path that invokes `generate_summary()`, causes this code to execute without confirmation, integrity verification, or sandboxing. Using an argument list rather than `shell=True` prevents shell metacharacter injection, but it does not address the central issue: the selected Python script itself is attacker-controlled. The 30-second timeout limits duration only. It does not prevent the child process from accessing files, environment varia ...[truncated 1650 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove automatic execution of project-provided checker scripts. 2. Prefer the existing declarative manifest approach and parse data without executing repository code. 3. If custom checker execution is necessary, make it explicitly opt-in and disabled by default. 4. Display the exact script path and command, then require informed user confirmation before execution. 5. Maintain an allowlist of approved checker implementations or verify the checker against a trusted cryptographic hash. 6. Execute approved checkers in a hardened sandbox with: - Network access disabled. - A read-only project filesystem. - No access to home directories, SSH agents, or credential stores. - A sanitized environment with secrets removed. - Restricted process creation and system calls. - CPU, memory, output-size, and time limits. 7. Do not rely on a timeout as a security boundary. 8. Report checker execution and failures clearly instead of silently suppressing exceptions. 9. Document the trust implications of any optional repository-code execution. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Memory Manipulation

High
Category
Memory Poisoning
Content
| `status` | Show current progress |
| `check` | Pre-commit safety check (protected files, deletions) |
| `summary` | Generate completion report |
| `reset` | Clear state |

## How It Works
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Missing User Warnings

High
Confidence
98% confidence
Finding
The protocol explicitly states that a PASS result leads to an automatic commit, but it does not require an explicit user-facing warning or consent before modifying repository history. In this context, the skill is designed to make autonomous code changes, so silent or insufficiently disclosed commit behavior can cause unauthorized state changes, hide risky edits behind automation, and increase operational and supply-chain risk.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill clearly instructs use of shell execution and project file creation/modification, but it does not declare an explicit tool scope such as allowed tools or permissions. That omission weakens containment and review because an agent may infer broad shell and filesystem authority without user-visible boundaries, which is especially risky in a skill that orchestrates automated repair loops and commits changes.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill advertises auto-commit behavior on success, but does not give a prominent warning or require explicit consent before creating git commits. In an automated multi-step repair workflow, this can cause repository state changes that users did not intend, potentially persisting faulty or policy-violating changes and complicating rollback or audit trails.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The template explicitly requires dynamic validation by actually running code and using real data, but it does not include any safety constraints, sandboxing requirements, or warnings about effects on production systems and sensitive data. In a repair-orchestration skill, this increases the chance that an inspector agent executes untrusted or recently modified code in a live or data-bearing environment, causing data corruption, leakage, or unintended side effects.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The skill instructions and operational text are entirely in Chinese, with no indication that users may choose another language or that the locale restriction is required for a region-specific purpose. This can violate language/locale policy when a skill imposes a language without opt-in.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger conditions include broad natural-language activations such as user requests to "fix X" / "resolve X", which can cause the skill to launch on ambiguous, everyday phrasing without explicit confirmation of scope. In a skill that performs automated repair loops and can proceed to commits, overbroad activation increases the chance of unintended code modification workflows being started from casual or underspecified requests.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains user-facing natural-language instructions and CLI messaging entirely in Chinese, including the top-level description and usage guidance. The skill does not indicate that language is configurable or that users may opt into another locale, which can violate a language/locale policy requiring user choice.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill persists model-generated repair patterns outside the target workdir into a shared cross-project store and later re-injects them into future repair prompts. That creates a cross-project prompt/data contamination channel where one malicious or sensitive project can influence later runs or leak project-specific knowledge despite the attempted heuristic generalization.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        # Get staged changes
        diff_result = subprocess.run(
            ["git", "diff", "--cached", "--name-only"],
            capture_output=True, text=True, cwd=str(workdir)
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not changed:
            # Check unstaged too
            diff_result = subprocess.run(
                ["git", "diff", "--name-only"],
                capture_output=True, text=True, cwd=str(workdir)
            )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
result["violations"] = [f"受保护文件被修改: {v}" for v in violations]

        # Check deletions
        del_result = subprocess.run(
            ["git", "diff", "--diff-filter=D", "--name-only"],
            capture_output=True, text=True, cwd=str(workdir)
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
result["violations"].append(f"文件被删除: {', '.join(deleted)}")

        # Check change size
        stat_result = subprocess.run(
            ["git", "diff", "--stat"],
            capture_output=True, text=True, cwd=str(workdir)
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
This logic discovers and runs a repository-local script unrelated to core repair orchestration, effectively granting arbitrary code execution to the analyzed project during a summary/doc-sync step. Because the tool is meant to operate on potentially untrusted codebases, automatically executing helper code from that codebase is especially dangerous in context.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
checker = workdir / "scripts" / "tools" / "doc-sync-checker.py"
    if checker.exists():
        try:
            result = subprocess.run(
                [sys.executable, str(checker), "--json"],
                capture_output=True, text=True, cwd=str(workdir), timeout=30
            )
Confidence
90% confidence
Finding
The script executes a project-local helper from the target workdir, which means untrusted repository contents can cause arbitrary code execution when summary/doc-sync checks are run. In a repair orchestrator that may be pointed at many external projects, treating repo-local Python as trusted materially expands the attack surface beyond simple file inspection.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The skill title and multiple operational examples are presented in Chinese, including task descriptions and workflow sections, but the document does not state that language is optional or user-selectable. This can violate language/locale policy when a skill effectively assumes a specific language without user opt-in.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
All user-facing instructions in the file are in Chinese, and there is no indication that the user can opt into another language or that the locale restriction is intentionally scoped. This can violate language/locale policy when a skill forces a specific language without user choice.

Static analysis

No suspicious patterns detected.