Back to skill

Security audit

luci-memory

Security checks for vulnerabilities and agentic risk

Overview

The skill appears designed for legitimate personal-memory search, but it exposes sensitive media through non-expiring unauthenticated image references and stores the API key in a plaintext local file.

Install only if you trust Memories.ai with your personal media and are comfortable managing the API key yourself. Prefer supplying MEMORIES_AI_KEY through a protected secret mechanism instead of a plaintext .env file, and avoid sharing logs or transcripts containing bucket/blob values until media URLs are authenticated, expiring, and revocable.

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
SKILL.md:81
Finding

Unauthenticated Proxy Access to Private Images and Keyframes

Content
View full analysis
&blob=" ``` 2. **Send** via OpenClaw message CLI: ```bash openclaw message send --channel --target --media /path/to/workspace/image.jpg --message "caption" ``` ``` `SKILL.md:176`: ```text Image and keyframe results return `bucket` and `blob` (no signed URLs). To get the actual image bytes, hit the proxy endpoint — see "Returning Images/Keyframes to User" above. The endpoint streams the JPEG bytes directly with no expiration or auth on the client side. ``` `scripts/run.py:159-163`: ```python if img.get("text"): lines.append(f" {img['text']}") lines.append(f" bucket: {img.get('bucket')}, blob: {img.get('blob')}") if img.get("location"): lines.append(f" Location: {img['location']}") ``` `scripts/run.py:196-200`: ```python sim_str = f" (similarity: {sim:.2f})" if sim < 1 else "" lines.append(f"- **{r.get('id', '?')}** frame #{r.get('frame_id')} @ {r.get('frame_time', 0):.1f}s{sim_str}") lines.append(f" bucket: {r.get('bucket')}, blob: {r.get('blob')}") return "\n".join(lines) ``` ### Technical Analysis The image proxy is explicitly documented as requiring no client-side authentication and issuing access with no expiration. At the same time, image and keyframe formatters expose the underlying `bucket` and `blob` identifiers in normal command output. These identifiers therefore operate as permanent bearer references. They can be retained in agent transcripts, command output, app ...[truncated 1843 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:11
Finding

API Key Persisted in an Unprotected Plaintext File

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (12)

Tainted flow: 'req' from os.environ.get (line 44, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/run.py (reported line 46)May include surrounding context.

python
sys.exit(1)
    req = urllib.request.Request(USERINFO_API, headers={"authorization": api_key, "User-Agent": "LuciMemory/1.0"})
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read())
    except Exception as e:
        print(f"Error: Failed to resolve user from API key: {e}", file=sys.stderr)

Tainted flow: 'req' from os.environ.get (line 44, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/run.py (reported line 112)May include surrounding context.

python
data = json.dumps(body).encode()
    req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json", "User-Agent": "LuciMemory/1.0"})
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as e:
        error_body = e.read().decode() if e.fp else ""

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Persisting a user-provided secret key to local storage for automatic reuse is a real secret-handling vulnerability because it converts a transient credential into a durable artifact in the workspace. In a multi-tool or agent environment, that materially raises the risk of credential theft, unintended cross-skill access, and long-term compromise of the user's external account.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

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

Content

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

text
3. **Cleanup** the file after sending:
   ```bash
   rm /path/to/workspace/image.jpg

⚠️ Always quote the URL — it contains & and the blob may have / characters.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/run.py (reported line 22)May include surrounding context.

python
API_PERSONAL = API_HOST + "/personal"
API_PORTRAIT = API_HOST + "/portrait"
USERINFO_API = "https://mavi-backend.memories.ai/serve/api/userinfo"
ENV_FILE = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")

def _load_env():
    """Load MEMORIES_AI_KEY from .env file next to the skill root."""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/run.py (reported line 25)May include surrounding context.

python
ENV_FILE = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")

def _load_env():
    """Load MEMORIES_AI_KEY from .env file next to the skill root."""
    if not os.path.exists(ENV_FILE):
        return None
    with open(ENV_FILE) as f:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill performs networked operations and uses environment-based credentials, but it does not declare an explicit tool scope such as permissions or allowed-tools. This weakens containment and reviewability because the runtime capabilities exceed what is documented, making it easier for the skill to invoke broader functionality than operators may expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The instructions tell the agent to save a user-provided API key into a local .env file without warning the user about persistence, reuse, or local exposure risk. Secrets written to workspace storage can be inadvertently read by other tools, leaked in logs, committed to files, or reused beyond the user's expectation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is described as a search/retrieval skill, but it also instructs the agent to send media to users through OpenClaw messaging. That expands the skill from read/search into outbound delivery, increasing the chance of unintended exfiltration, privacy leaks, or actions taken without sufficiently explicit user confirmation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This skill sends highly sensitive personal media and portrait lookups to remote APIs without any in-code notice, consent gate, or visibility to the user about what data leaves the local environment. In the context of a memory-search skill handling transcripts, relationships, traits, and events, undisclosed remote transmission materially increases privacy risk even if the backend is legitimate.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest frames the skill as searching Luci-memory data about personal videos and portrait information. The parameter documentation states that --location is geocoded via Google Maps, introducing third-party location resolution that is not mentioned in the manifest and is not obviously necessary from the user-facing description alone.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The skill loads MEMORIES_AI_KEY from either the environment or a local .env file and immediately uses it for authentication. While this is functionally expected, the code does not include a clear warning or disclosure to the user about reading local credentials, which falls under sensitive environment-variable access.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.