Back to skill

Security audit

Taskqueue

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent local task-queue skill, but its API can read and change all queued task data without authentication and keeps arbitrary task contents in memory without limits.

Use this only as a local, trusted development queue unless you add authentication, authorization, request-size limits, retention/deletion controls, and valid state-transition checks. Do not expose the server to a network or put secrets in task payloads without those controls.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
taskqueue/app.py:34
Finding

Unauthenticated Access to Task Data and State-Changing Operations

Content
View full analysis

Vulnerability Details

File Location: taskqueue/app.py:34-90
Vulnerability Type: Missing authentication and authorization
Risk Level: High

Vulnerable Code

python
@app.post("/v1/tasks", response_model=TaskResponse)
async def create(request: CreateTaskRequest) -> TaskResponse:
    task = create_task(request.title, request.payload, request.priority, request.tags)
    return _task_to_response(task)


@app.get("/v1/tasks", response_model=TaskListResponse)
async def list_all(
    status: str | None = Query(default=None),
    tag: str | None = Query(default=None),
) -> TaskListResponse:
    tasks = list_tasks(status, tag)
    return TaskListResponse(tasks=[_task_to_response(t) for t in tasks], total=len(tasks))


@app.get("/v1/tasks/{task_id}", response_model=TaskResponse)
async def get_by_id(task_id: str) -> TaskResponse:
    task = get_task(task_id)
    if task is None:
        raise HTTPException(status_code=404, detail=f"Task not found: {task_id}")
    return _task_to_response(task)


@app.post("/v1/claim", response_model=TaskResponse)
async def claim() -> TaskResponse:
    task = claim_next()
    if task is None:
        raise HTTPException(status_code=404, detail="No pending tasks to claim")
    return _task_to_response(task)


@app.post("/v1/tasks/{task_id}/complete", response_model=TaskResponse)
async def complete(task_id: str, request: CompleteRequest) -> TaskResponse:
    task = complete_task(task_id, request.result)
    if task is None:
        raise HTTPException(status_code=404, detail=f"Task not found: {task_id}")
    return _task_to_response(task)


@app.post("/v1/tasks/{task_id}/fail", response_model=TaskResponse)
async def fail(task_id: str, request: FailRequest) -> TaskResponse:
    task = fail_task(task_id, request.error)
    if task is None:
        raise HTTPException(status_code=404, detail=f"Task not found: {task_id}")
    return _task_to_resp
...[truncated 1773 chars]
Remediation
View remediation

Remediation Suggestions

  • Require authentication on every API endpoint, using a suitably protected API token, mTLS, OAuth2, or another mechanism appropriate to the deployment.
  • Apply authorization checks based on queue, tenant, task ownership, and operation type.
  • Do not treat knowledge of a task identifier as authorization.
  • Return only the fields each caller is permitted to access.
  • Bind the service to 127.0.0.1 by default when it is intended only for local agent workflows.
  • Place remotely reachable deployments behind TLS and an authenticated reverse proxy.
  • Add audit logging for task creation, reads, claims, completion, and failure operations.
  • Document the service's trust boundary and secure deployment requirements.

T09 · Insecure Skill Coding Practices

Error
Location
taskqueue/models.py:10
Finding

Unbounded Retention of Arbitrarily Large Task Data Enables Memory Exhaustion

Content
View full analysis

Vulnerability Details

File Location: taskqueue/models.py:10-16, taskqueue/models.py:39-51, and taskqueue/state.py:23-29
Vulnerability Type: Uncontrolled resource consumption
Risk Level: High

Vulnerable Code

python
class CreateTaskRequest(BaseModel):
    model_config = ConfigDict(extra="forbid")

    title: str = Field(..., min_length=1, max_length=500)
    payload: Any = Field(...)
    priority: int = Field(default=0, ge=0, le=100)
    tags: list[str] = Field(default_factory=list, max_length=20)
python
class CompleteRequest(BaseModel):
    model_config = ConfigDict(extra="forbid")

    result: Any = Field(...)


class FailRequest(BaseModel):
    model_config = ConfigDict(extra="forbid")

    error: str = Field(..., min_length=1)
python
_tasks: dict[str, Task] = {}


def create_task(title: str, payload: Any, priority: int = 0, tags: list[str] | None = None) -> Task:
    task = Task(title=title, payload=payload, priority=priority, tags=tags or [])
    _tasks[task.id] = task
    return task

Technical Analysis

Task payloads and completion results use the unrestricted Any type and have no validated size or nesting-depth limit. Failure messages have a minimum length but no maximum length. The global _tasks dictionary retains every created task, including its payload, result, and error, for the lifetime of the process.

The implementation has no maximum queue size, per-client quota, task expiration, deletion mechanism, rate limit, or memory-pressure handling. Consequently, an API client can force persistent process-memory growth by submitting many tasks or a smaller number of tasks containing large JSON bodies.

Attack Path

  1. An attacker reaches the task-creation endpoint.
  2. The attacker repeatedly submits POST /v1/tasks requests containing large or deeply nested JSON payloads.
  3. Each validated payload is retained in the global `_tas ...[truncated 630 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace unrestricted Any fields with explicit, bounded schemas wherever possible.
  • Enforce maximum serialized sizes and nesting depths for payloads and results.
  • Add a maximum length to FailRequest.error and limits for individual tag lengths.
  • Configure request-body size limits at the application server or reverse proxy.
  • Introduce a maximum queue length and reject new tasks with an appropriate status code when capacity is reached.
  • Add task deletion, retention periods, and automatic expiration for terminal tasks.
  • Apply per-client rate limits and storage quotas.
  • Use a production queue or datastore with capacity controls for deployments requiring persistent or high-volume workloads.
  • Run the service with operating-system or container memory limits as defense in depth.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:4
Finding

Unpinned Third-Party Dependencies Create Supply-Chain and Reproducibility Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:4
Vulnerability Type: Unconstrained dependency installation
Risk Level: Medium

Vulnerable Code

yaml
metadata: {"openclaw":{"emoji":"📋","requires":{"bins":["python"]},"install":[{"id":"pip","kind":"uv","packages":["fastapi","uvicorn","pydantic"]}]}}

Technical Analysis

The installation metadata specifies fastapi, uvicorn, and pydantic without exact versions or integrity hashes. Each installation can therefore resolve a different set of package and transitive-dependency versions.

Although the reviewed project does not reference an obviously malicious package or unsafe package source, unconstrained resolution makes builds non-reproducible and allows a future incompatible, vulnerable, or compromised release to be installed without a corresponding review of this Skill.

Attack Path

  1. A new affected or compromised version of a named package or transitive dependency becomes available from the configured package index.
  2. A user installs the Skill after that release is published.
  3. The dependency resolver selects the new version because no reviewed version is pinned.
  4. The affected package is installed and subsequently imported or executed by the service.
  5. The package's vulnerability or malicious behavior affects the TaskQueue environment.

Impact Assessment

Impact depends on the behavior and privileges of the installed dependency. A compromised dependency could execute code with the privileges of the account installing or running the service. An incompatible release could prevent startup or alter validation and API behavior. The repository itself contains no evidence that the currently named packages are malicious.

Remediation
View remediation

Remediation Suggestions

  • Pin all direct dependencies to reviewed versions.
  • Use a lockfile that records complete transitive dependency versions.
  • Require package hashes where supported to verify downloaded artifacts.
  • Install packages only from approved package indexes over authenticated TLS.
  • Automate vulnerability scanning while keeping dependency updates subject to review and testing.
  • Regenerate pins through a controlled update process rather than allowing unconstrained resolution during installation.

T09 · Insecure Skill Coding Practices

Warning
Location
taskqueue/state.py:52
Finding

Task State Transitions Are Not Validated

Content
View full analysis

Vulnerability Details

File Location: taskqueue/state.py:52-70
Vulnerability Type: Improper workflow state validation
Risk Level: Medium

Vulnerable Code

python
def complete_task(task_id: str, result: Any) -> Task | None:
    task = _tasks.get(task_id)
    if task is None:
        return None
    task.status = "completed"
    task.result = result
    return task


def fail_task(task_id: str, error: str) -> Task | None:
    task = _tasks.get(task_id)
    if task is None:
        return None
    task.status = "failed"
    task.error = error
    return task

Technical Analysis

The completion and failure functions update any existing task without checking its current status. A pending task can be completed without being claimed, a completed task can be changed to failed, and a failed task can be changed back to completed. Repeated requests can therefore rewrite terminal states and leave stale fields, such as an old error on a subsequently completed task.

This violates the expected queue lifecycle and permits integrity attacks even if authentication is added later without corresponding state-transition authorization and validation.

Attack Path

  1. A caller obtains or enumerates a valid task identifier.
  2. The caller sends a completion request for a pending task, bypassing the claim and execution stages.
  3. Alternatively, the caller targets an already completed task with the failure endpoint.
  4. The function overwrites the status without verifying the prior state.
  5. Queue consumers and statistics reflect an invalid or attacker-selected outcome.

Impact Assessment

A caller capable of invoking these endpoints can bypass the intended workflow and rewrite task outcomes. The impact is application-level integrity loss across affected tasks, including false completion, false failure, and unreliable queue statistics. This flaw does not itself grant operating-system permi ...[truncated 7 chars]

Remediation
View remediation

Remediation Suggestions

  • Define and enforce an explicit transition table, such as pending to running, followed by running to either completed or failed.
  • Reject invalid transitions with HTTP 409 Conflict.
  • Require a claim token, worker identity, or lease identifier before allowing a running task to be completed or failed.
  • Prevent modifications to terminal tasks unless a separate privileged retry or administrative operation is used.
  • Clear mutually exclusive fields during valid transitions, such as clearing error on completion and result on failure.
  • Add tests for attempts to complete pending tasks, rewrite terminal tasks, and update tasks claimed by another worker.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (3)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 20)May include surrounding context.

Create a task

bash
curl -s -X POST http://localhost:8014/v1/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "Scan skill", "payload": {"skill": "my-skill"}, "priority": 5, "tags": ["security"]}' | jq

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 36)May include surrounding context.

Complete or fail a task

bash
curl -s -X POST http://localhost:8014/v1/tasks/TASK_ID/complete \
  -H "Content-Type: application/json" \
  -d '{"result": {"output": "all clear"}}' | jq

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 40)May include surrounding context.

-H "Content-Type: application/json"
-d '{"result": {"output": "all clear"}}' | jq

curl -s -X POST http://localhost:8014/v1/tasks/TASK_ID/fail
-H "Content-Type: application/json"
-d '{"error": "scan timed out"}' | jq

text

Static analysis

No suspicious patterns detected.