Back to skill

Security audit

looop

Security checks for vulnerabilities and agentic risk

Overview

This skill openly automates Claude to modify and commit code, but it gives that automation unusually broad authority without enough containment or review gates.

Install only for trusted, disposable or well-backed-up repositories. Do not run it with sensitive environment variables or credentials loaded, avoid --push, set --max-tasks, review tasks.json before execution, inspect every diff before sharing or pushing, and ensure .looop logs are ignored or cleaned because they may contain sensitive Claude output.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
run.py:109
Finding

Prompt Injection into a Permission-Bypassed Claude Agent

Content
View full analysis
50 else ''.join(lines) if recent_progress.strip(): completed_context = f'\n\n## Recent Progress (Last Completed Tasks)\n```\n{recent_progress.strip()}\n```' ``` Task-controlled fields are interpolated without validation or isolation: ```python # Build acceptance criteria section acceptance_section = "" if task.get('acceptance_criteria'): criteria_list = '\n'.join(f'- {c}' for c in task['acceptance_criteria']) acceptance_section = f'\n\n## Acceptance Criteria\nVerify these criteria before marking complete:\n{criteria_list}' # Build estimated files section files_section = "" if task.get('estimated_files'): files_list = '\n'.join(f'- {f}' for f in task['estimated_files']) files_section = f'\n\n## Expected Files\nFocus on these files:\n{files_list}' ``` ```python **Task #{task['id']}: {task['name']}** - **Type**: {task.get('task_type', 'feature')} - **Priority**: {ta ...[truncated 2563 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
run.py:729
Finding

Broad Automated Git Staging and Optional Push Can Expose Sensitive Files

Content
View full analysis
"' if args.push: git_cmds += "\n- git push" ``` These instructions are included in the privileged agent prompt: ```python ### 7. Git Operations (if completed successfully) {git_cmds} ``` The behavior is also declared in `skill.md:7-12`: ```yaml permissions: - dangerous: Uses --dangerously-skip-permissions to bypass permission prompts - write: Writes files to specified src directory - git-commit: Automatically commits task completions - git-push: Optional push with --push flag warning: This skill bypasses permission checks and automatically commits/pushes to git. Use with caution on trusted projects only. ``` ### Technical Analysis The agent is instructed to stage broadly, commit automatically, and optionally push to the configured remote. There is no file allowlist, staged-diff review, secret scan, repository-boundary validation, or separate approval before pushing. Although `git add all` is not the canonical Git command for staging all changes, it is a natural-language agent instruction. An AI coding agent can interpret or correct it to an equivalent operation such as `git add --all`. Therefore, it cannot be relied upon to limit staging. Generated files, pre-existing unrelated working-tree changes, `.looop` logs, environment files, private keys, credentials, or files deliberately created by injected instructions may consequently enter a commit. When `--push` is enabled, that commit may be transmitted to the configured remote. ### Attack Path 1. A task, prompt injection, or ordinary development operation creates or copies a sensitive file into the repository. 2. Alternatively, unrelated sensitive changes already exist in the working tree before the skill starts. 3. ...[truncated 1013 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
run.py:109
Finding

Verbose Claude Output Is Persisted Without Redaction or Access Hardening

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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).

Content

Scanner excerpt · run.py (reported line 42)May include surrounding context.

python
def check_claude_installed() -> bool:
    """Check if Claude CLI is installed"""
    try:
        result = subprocess.run(
            'claude --version',
            capture_output=True,
            text=True,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This automatically runs an external tool that can modify the project directory, without a separate approval step. In the broader skill context, that contributes to unsafe autonomous behavior and can unexpectedly change repository state.

Content

Scanner excerpt · run.py (reported line 69)May include surrounding context.

python
print("[Warn] CLAUDE.md not found, initializing...")

    try:
        result = subprocess.run(
            'claude init',
            capture_output=True,
            text=True,

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The function presents itself as merely invoking Claude, but it actually prepares an execution environment for a model that is later launched with permission bypass. Combined with untrusted prompt inputs from docs and task context, this creates a high-risk prompt-injection-to-action path where repository content can steer unrestricted autonomous behavior.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · run.py (reported line 96)May include surrounding context.

python
logger = get_logger()
    logger.info("Claude executing...")

    env = os.environ.copy()
    if sys.platform == 'win32' and 'CLAUDE_CODE_GIT_BASH_PATH' not in env:
        try:
            result = subprocess.run('where bash', capture_output=True, text=True, shell=True, timeout=5)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% 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).

Content

Scanner excerpt · run.py (reported line 99)May include surrounding context.

python
env = os.environ.copy()
    if sys.platform == 'win32' and 'CLAUDE_CODE_GIT_BASH_PATH' not in env:
        try:
            result = subprocess.run('where bash', capture_output=True, text=True, shell=True, timeout=5)
            if result.returncode == 0:
                for line in result.stdout.strip().split('\n'):
                    path = line.strip()

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This duplicate finding points to the same privileged Popen invocation. Because the tool is launched with unrestricted permissions and trusted to act on untrusted repository-derived instructions, the context materially increases the severity from a generic subprocess issue to a critical agent-control vulnerability.

Content

Scanner excerpt · run.py (reported line 110)May include surrounding context.

python
pass

    cmd = 'claude -p --dangerously-skip-permissions --verbose --output-format stream-json'
    process = subprocess.Popen(
        cmd,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This duplicate finding points to the same privileged Popen invocation. Because the tool is launched with unrestricted permissions and trusted to act on untrusted repository-derived instructions, the context materially increases the severity from a generic subprocess issue to a critical agent-control vulnerability.

Content

Scanner excerpt · run.py (reported line 110)May include surrounding context.

python
pass

    cmd = 'claude -p --dangerously-skip-permissions --verbose --output-format stream-json'
    process = subprocess.Popen(
        cmd,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · run.py (reported line 42)May include surrounding context.

python
def check_claude_installed() -> bool:
    """Check if Claude CLI is installed"""
    try:
        result = subprocess.run(
            'claude --version',
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
81% confidence
Finding

This invokes 'claude init' automatically in the target source directory when CLAUDE.md is missing. The command string is fixed, but in this skill's context it causes an external tool to make filesystem changes without an explicit confirmation step, which is risky for a controller that later grants the tool broad autonomy.

Content

Scanner excerpt · run.py (reported line 69)May include surrounding context.

python
print("[Warn] CLAUDE.md not found, initializing...")

    try:
        result = subprocess.run(
            'claude init',
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · run.py (reported line 99)May include surrounding context.

python
env = os.environ.copy()
    if sys.platform == 'win32' and 'CLAUDE_CODE_GIT_BASH_PATH' not in env:
        try:
            result = subprocess.run('where bash', capture_output=True, text=True, shell=True, timeout=5)
            if result.returncode == 0:
                for line in result.stdout.strip().split('\n'):
                    path = line.strip()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code launches Claude with a dangerous permission-bypass mode but does not provide a clear, unavoidable user-facing warning at the point of execution. In an agent skill, hiding or downplaying that level of autonomy increases the chance that users will run a highly privileged automation path without understanding the risk.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

This subprocess call launches the Claude CLI with shell=True and the --dangerously-skip-permissions flag, then feeds it attacker-influenced prompt content derived from requirement docs, task files, and progress context. In this skill's context, that gives an LLM unrestricted ability to modify the target repository and potentially invoke tools or commands without normal safety gates, making prompt injection in project content especially dangerous.

Content

Scanner excerpt · run.py (reported line 110)May include surrounding context.

python
pass

    cmd = 'claude -p --dangerously-skip-permissions --verbose --output-format stream-json'
    process = subprocess.Popen(
        cmd,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · run.py (reported line 178)May include surrounding context.

python
init_logger(looop_dir, task_id=0, task_name="Decompose")
    logger = get_logger()

    today = str(__import__('datetime').datetime.now().date())

    # Handle single doc vs directory
    if is_single_doc:

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · run.py (reported line 370)May include surrounding context.

python
init_logger(looop_dir, task_id=0, task_name="Decompose")
    logger = get_logger()

    today = str(__import__('datetime').datetime.now().date())

    # Handle single doc vs directory
    if is_single_doc:

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · run.py (reported line 727)May include surrounding context.

python
files_list = '\n'.join(f'- {f}' for f in task['estimated_files'])
                files_section = f'\n\n## Expected Files\nFocus on these files:\n{files_list}'

            now = __import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')

            git_cmds = '- git add all\n- git commit -m "<decide commit message based on task content>"'
            if args.push:

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The prompt instructs Claude to skip tests for non-test tasks while the controller later trusts Claude's self-reported completion marker to update task status. That weakens verification and allows incomplete or policy-noncompliant changes to be marked complete, which is especially risky in an autonomous code-writing workflow.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

The skill is explicitly designed to decompose requirements and then automatically execute generated tasks until completion, which gives an LLM broad autonomous control over code changes and workflow decisions. In this context, the danger is amplified by the documented permission bypass, file writes, and automatic git commit/push behavior, creating a credible path to unintended or harmful repository modifications without meaningful human review.

Content

Scanner excerpt · skill.md (reported line 3)May include surrounding context.

md
---
name: looop
description: Claude Automated Development Toolkit - Decompose requirements documents, single files, or inline text into detailed task lists and automatically execute in loops until project completion
requires:
  - claude-cli: Requires local Claude CLI installation
  - git: Modifies git repository (commits changes)

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

This section confirms the tool will automatically execute tasks in a loop whenever a task file exists, turning prior planning output into unattended action. Because the same skill also writes code, updates task state, commits changes, and can push remotely, this autonomous loop materially increases the risk of cascading bad decisions, repository corruption, or exfiltration via code/config changes.

Content

Scanner excerpt · skill.md (reported line 94)May include surrounding context.

md
The script will first check if `<src_dir>/.looop/tasks.json` exists:

- Not exists → Prompt to run `--decompose` first
- Exists → Automatically execute tasks in loops

Execution process:

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code file creates a log file on disk and persists task-related messages, including task names and later log content, but there is no confirmation prompt. Although the module has docstrings describing logging behavior, they do not clearly disclose to an end user that task information will be written to persistent files in the specified directory.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.