Back to skill

Security audit

Kvstore

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed local key-value store, but it exposes unauthenticated read, write, list, delete, and full-flush operations over all stored data.

Install only if you are comfortable running a local, unauthenticated KV service. Keep it bound to localhost, do not store real secrets or sensitive personal data, avoid sharing the port with untrusted users/processes/containers, and treat /v1/flush as an admin-only destructive action.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
kvstore/app.py:29
Finding

Unauthenticated Access to Stored Data and Destructive Operations

Content
View full analysis

Vulnerability Details

File Location: kvstore/app.py:29-65
Vulnerability Type: Missing authentication and authorization
Risk Level: High

Vulnerable Code

python
@app.post("/v1/set", response_model=SetResponse)
async def set_value(request: SetRequest) -> SetResponse:
    set_key(request.key, request.value, request.ttl_seconds)
    return SetResponse(key=request.key, stored=True)


@app.get("/v1/get/{key}", response_model=GetResponse)
async def get_value(key: str) -> GetResponse:
    entry = get_key(key)
    if entry is None:
        raise HTTPException(status_code=404, detail=f"Key not found: {key}")
    return GetResponse(key=entry.key, value=entry.value, ttl_remaining=entry.ttl_remaining)


@app.delete("/v1/delete/{key}", response_model=DeleteResponse)
async def delete_value(key: str) -> DeleteResponse:
    deleted = delete_key(key)
    if not deleted:
        raise HTTPException(status_code=404, detail=f"Key not found: {key}")
    return DeleteResponse(key=key, deleted=True)


@app.get("/v1/keys", response_model=KeyListResponse)
async def get_keys(prefix: str | None = Query(default=None)) -> KeyListResponse:
    keys = list_keys(prefix)
    return KeyListResponse(keys=keys, total=len(keys))


@app.post("/v1/flush", response_model=FlushResponse)
async def flush() -> FlushResponse:
    count = flush_all()
    return FlushResponse(deleted=count)

Technical Analysis

All data-management routes are exposed without an authentication dependency, authorization check, API key, or client-specific namespace. A client that can reach the service can enumerate key names, retrieve arbitrary values, overwrite entries, delete selected entries, or erase the entire store.

This is especially relevant because the documented use case includes agent state, shared pipeline data, and token-like cached values. Although the documented Uvicorn command normally binds to the loopback interfac ...[truncated 1462 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require authentication on every endpoint using a centrally applied FastAPI dependency or authentication middleware.
  2. Enforce authorization separately for read, write, delete, enumeration, statistics, and global-flush operations.
  3. Assign each client or agent an isolated namespace and verify ownership before reading or modifying a key.
  4. Restrict /v1/flush to a dedicated administrative role and consider disabling it in production.
  5. Bind the service explicitly to a trusted interface and enforce host firewall or service-mesh access controls.
  6. Use TLS when requests can cross an untrusted network.
  7. Avoid storing credentials or tokens in plaintext. If sensitive values must be stored, encrypt them and tightly restrict decryption access.
  8. Add audit logging for reads, writes, deletes, failed authorization attempts, and global administrative actions.
  9. Return generic not-found responses where appropriate to reduce key-discovery signals.

T09 · Insecure Skill Coding Practices

Warning
Location
kvstore/models.py:10
Finding

Unbounded Value and Store Growth Enables Memory-Exhaustion Denial of Service

Content
View full analysis

Vulnerability Details

File Location: kvstore/models.py:10-15; kvstore/state.py:34-37
Vulnerability Type: Uncontrolled resource consumption
Risk Level: Medium

Vulnerable Code

kvstore/models.py:10-15:

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

    key: str = Field(..., min_length=1, max_length=500)
    value: Any = Field(...)
    ttl_seconds: int | None = Field(default=None, gt=0, le=86400, description="Time to live in seconds.")

kvstore/state.py:34-37:

python
def set_key(key: str, value: Any, ttl_seconds: float | None = None) -> Entry:
    entry = Entry(key=key, value=value, ttl_seconds=ttl_seconds)
    _store[key] = entry
    return entry

Technical Analysis

The key length and optional TTL are validated, but the application does not constrain:

  • The serialized or in-memory size of a value.
  • The HTTP request-body size.
  • The total number of keys.
  • The aggregate memory used by the store.
  • The request rate or per-client storage consumption.

Values are accepted as unrestricted JSON-compatible data through Any and retained in the process-level _store dictionary. TTL is optional, so entries can remain indefinitely. There is also no capacity-based eviction mechanism. Consequently, repeated writes using unique keys can continuously increase process memory consumption.

Attack Path

  1. The attacker obtains access to the /v1/set endpoint.
  2. The attacker constructs large JSON values, such as deeply nested structures or large arrays and strings.
  3. The attacker repeatedly submits these values using unique keys and omits ttl_seconds.
  4. Each request adds another permanent Entry to the global in-memory dictionary.
  5. Memory consumption grows until the process becomes unresponsive, is terminated by the operating system, or causes resource pressure for colocated services.

An attacker can also amplify ...[truncated 582 chars]

Remediation
View remediation

Remediation Suggestions

  1. Enforce a strict maximum HTTP request-body size at the reverse proxy, ASGI middleware, or server layer.
  2. Validate the serialized size of value before retaining it in memory.
  3. Set limits for the total number of keys and aggregate store memory.
  4. Apply per-client storage quotas after introducing client authentication.
  5. Add request rate limiting and concurrency limits to the write endpoint.
  6. Implement a defined eviction policy, such as least-recently-used or least-frequently-used eviction.
  7. Require or automatically assign a maximum TTL where permanent retention is unnecessary.
  8. Reject excessively deep or complex JSON structures to reduce parsing and memory-amplification risks.
  9. Monitor process memory, entry count, rejected writes, and eviction activity, with alerts before resource exhaustion occurs.
  10. Consider using a production datastore that natively supports quotas, eviction, authentication, and memory limits.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

The API exposes destructive operations (DELETE /v1/delete/{key} and especially /v1/flush) with no visible authentication, authorization, or safety controls in this file. In an agent-tool context, this enables parameter abuse where any caller able to invoke the skill can delete arbitrary keys or wipe all stored state, causing loss of data integrity and availability across agent workflows.

Content

Scanner excerpt · kvstore/app.py (reported line 7)May include surrounding context.

python
Endpoints:
  POST   /v1/set              — set a key-value pair (optional TTL)
  GET    /v1/get/{key}         — get a value by key
  DELETE /v1/delete/{key}      — delete a key
  GET    /v1/keys              — list all keys (optional prefix filter)
  POST   /v1/flush             — delete all keys
  GET    /v1/stats             — get store statistics

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.

Set a value

bash
curl -s -X POST http://localhost:8013/v1/set \
  -H "Content-Type: application/json" \
  -d '{"key": "user:1", "value": {"name": "Alice", "role": "admin"}}' | 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 28)May include surrounding context.

Set a value

bash
curl -s -X POST http://localhost:8013/v1/set \
  -H "Content-Type: application/json" \
  -d '{"key": "user:1", "value": {"name": "Alice", "role": "admin"}}' | jq

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation exposes a destructive /v1/flush operation that deletes all stored keys, but it provides no warning, confirmation guidance, or mention of access controls. In an agent-tooling context, this increases the chance of accidental or unauthorized mass data deletion, especially if other agents or automation invoke endpoints directly from the docs.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.