Back to skill

Security audit

obsidian-memory-system

Security checks for vulnerabilities and agentic risk

Overview

This skill does not show malware or exfiltration, but it needs review because it requests broad file and credential access while storing user questions locally and relying on weak payment-verification helpers.

Review before installing. Do not put secrets, vault excerpts, API keys, or private project details in the question because it is saved locally. Treat the filesystem and credential permissions as broad, and run the optional npx sandbox payment command only in a constrained environment if you choose to use it. The weak local payment check mainly affects payment integrity, not your system privileges.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/service.py:51
Finding

Forgeable Local Payment Authorization

Content
View full analysis

Vulnerability Details

File Location: scripts/service.py, lines 51-59 and 76-91
Vulnerability Type: Payment verification bypass caused by fail-open credential validation
Risk Level: Medium

Complete Code Snippet

python
def is_credential_valid(order_data: dict) -> bool:
    credential = order_data.get("payCredential")
    if not credential:
        return False
    credential_ts = order_data.get("credentialTimestamp")
    if credential_ts and time.time() - credential_ts > CREDENTIAL_TTL:
        return False
    return True
python
if not is_credential_valid(order_data):
    print("PAY_STATUS: ERROR")
    print("ERROR_INFO: No valid payment credential found. Complete payment via clawtip first.")
    sys.exit(1)

pay_status = order_data.get("payStatus", "SUCCESS")
print(f"PAY_STATUS: {pay_status}")

if pay_status != "SUCCESS":
    print(f"ERROR_INFO: Payment status is '{pay_status}', cannot proceed")
    sys.exit(1)

print("AUTHORIZATION_RESULT=verified")

Technical Analysis

The payment credential is not cryptographically authenticated. The validation routine only confirms that payCredential is non-empty. It does not verify a digital signature or message authentication code, nor does it bind the credential to the expected order number, amount, recipient, indicator, or payment transaction.

The expiration check also fails open:

  • A missing credentialTimestamp is accepted indefinitely.
  • A future timestamp is accepted because the calculated age is negative.
  • Timestamp type and allowable clock skew are not validated.
  • No replay protection or transaction identifier is checked.
  • A missing payStatus defaults to SUCCESS.

Because the order file is stored in the invoking user's home directory and is intentionally writable by that user, its fields cannot serve as a trusted payment-verification boundary.

Attack Path

  1. Run `scripts/create_order ...[truncated 1030 chars]
Remediation
View remediation

Remediation Suggestions

  • Verify payCredential cryptographically through an authenticated clawtip verification API or with a trusted, pinned clawtip public key.
  • Bind the verified credential to the exact orderNo, amount, recipient address, indicator, and service slug.
  • Require payStatus to be explicitly present and equal to SUCCESS; never supply a successful default.
  • Require a numeric credentialTimestamp and reject missing, malformed, expired, or unreasonably future timestamps.
  • Enforce a small, documented clock-skew allowance.
  • Validate a unique transaction identifier and maintain replay protection so that one credential cannot authorize multiple orders.
  • Treat all values loaded from the local order JSON as untrusted.
  • Fail closed on missing fields, parsing errors, unsupported credential versions, and verification-service failures.
  • Add negative tests covering forged credentials, absent timestamps, future timestamps, mismatched amounts, mismatched order numbers, missing status fields, and replayed transactions.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:82
Finding

Non-Interactive Download and Execution of Third-Party npm Package

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 82
Vulnerability Type: Third-party supply-chain code execution
Risk Level: Medium

Complete Code Snippet

bash
npx --yes @clawtip/clawtip-sandbox-cli@1.0.0 pay -o <ORDER_NO> -i <INDICATOR> -v 1.0.12

Technical Analysis

The documented sandbox payment workflow uses npx --yes, which can retrieve an npm package from the configured registry and execute it without interactive confirmation. Pinning the package to version 1.0.0 limits ordinary version drift, but the command does not pin or verify package integrity, registry origin, or a trusted artifact hash.

npm package installation can execute package lifecycle scripts in addition to the requested command. Consequently, the effective code executed by this workflow is not fully contained in the audited project. Its behavior depends on the external registry, package artifact, npm configuration, and dependency graph available at execution time.

This dependency is relevant to sandbox payment testing but is not necessary for the Skill's core conversational memory-management functionality. Running it with all privileges and data available to the Agent user therefore exceeds the minimum execution scope needed for a sandbox payment helper.

Attack Path

  1. A threat actor compromises the named npm package, one of its transitive dependencies, the registry account, the registry infrastructure, or the user's configured npm registry.
  2. The user or Agent follows the documented sandbox workflow.
  3. npx --yes retrieves the affected package or dependency without requesting confirmation.
  4. npm executes package installation hooks or the package CLI under the invoking user's account.
  5. Malicious dependency code accesses resources available to that account or modifies user-owned files.

Exploitation is conditional on supply-chain or package-resolution compromise; the audited project does not i ...[truncated 562 chars]

Remediation
View remediation

Remediation Suggestions

  • Keep the sandbox CLI optional and clearly separate it from the core Skill workflow.
  • Install dependencies from a lockfile that records integrity hashes rather than downloading them ad hoc with npx.
  • Verify the package's publisher, provenance, registry origin, signature where available, and expected integrity hash before execution.
  • Use a trusted registry configuration and reject unexpected registry overrides.
  • Disable npm lifecycle scripts when they are not required.
  • Execute the CLI in a restricted container or sandbox with a minimal filesystem view, no unrelated credentials, and only required environment variables.
  • Avoid exposing Obsidian vaults, Agent memory, SSH material, API tokens, or unrelated home-directory content to the process.
  • Review and pin the complete transitive dependency graph.
  • Document that this command retrieves and executes external code so users can make an informed decision before running it.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill makes strong safety and privacy claims about providing an Obsidian memory system without collecting vault content, note files, or credentials, yet the described implementation only handles payment/order flow and stores user-supplied question content locally. This mismatch is dangerous because users and platforms may grant filesystem and credential access based on misleading expectations, enabling unnecessary data exposure and trust abuse even if no obvious exfiltration is described in this file.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The docstring states that only standard payment fields are stored, but the implementation also persists the arbitrary user-provided question in the local order JSON. This is dangerous because users may include sensitive prompts, project details, or credentials despite the warning, and the misleading documentation reduces informed consent and increases accidental exposure.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script accepts arbitrary question content from the command line and writes it to a persistent file under the user's home directory, contradicting claims that no sensitive content is collected. In the context of a memory-system skill, users are especially likely to paste operational context, vault excerpts, tokens, or private notes, so this local persistence meaningfully increases confidentiality risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/create_order.py (reported line 182)May include surrounding context.

python
if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Create obsidian-memory-system order for clawtip payment"
    )
    parser.add_argument("question", help="User question / consultation content")
    args = parser.parse_args()

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

On order file read failure, the script prints the full local path in ERROR_INFO, disclosing the user's home-directory-based storage layout. While low severity, this leaks filesystem structure and confirms the existence and naming convention of local payment/order data, which can aid reconnaissance or expose private environment details in logs or chat transcripts.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.