T09 · Insecure Skill Coding Practices
- Location
amber_hunter.py:3368- Finding
Master Password Is Unconditionally Duplicated into a Plaintext Configuration File
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent local memory service, but it has serious review-worthy risks around plaintext secret storage, unauthenticated local access to private session data, and persistent background capture.
Review before installing. Use only if you are comfortable with a local service that reads agent sessions and workspace metadata, may use configured LLM/cloud credentials, and attempts background persistence. The plaintext master password and DID key storage plus unauthenticated local endpoints should be fixed before trusting it with sensitive memories.
amber_hunter.py:3368Master Password Is Unconditionally Duplicated into a Plaintext Configuration File
amber_hunter.py:3987DID Mnemonic and Device Private Key Are Persisted in Plaintext
amber_hunter.py:914Session Summaries and Recent Workspace Files Are Exposed without Authentication
amber_hunter.py:895Optional Authentication on the LLM Extraction Endpoint Permits Unauthorized Quota Use
install.sh:76Installer Enables Persistent Background Session Monitoring without a Separate Opt-In
requirements.txt:6Installation and Release Workflows Execute Unpinned Third-Party Dependencies
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
<!-- gitnexus:start -->
# GitNexus — Code Intelligence
This project is indexed by GitNexus as **amber-hunter** (930 symbols, 7750 relationships, 80 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
The README explicitly describes silent, automatic capture of AI session content and related files, which can collect sensitive user data without meaningful real-time consent or prominent privacy notice. In a skill context that monitors collaboration sessions, this creates substantial risk of overcollection and unexpected retention of private conversations, source code, and workspace artifacts.
The /master-password endpoint stores the master password in macOS Keychain and also writes it in plaintext to config.json as a fallback. Plaintext storage of the password undermines the whole local encryption model because any local process or backup that can read the config file can recover the key protecting user memories.
@app.post("/master-password")
def set_master_password_handler(password_in: MasterPasswordIn, request: Request):
"""设置 master_password(存 macOS Keychain + config.json 双备份)"""
client = request.client
if client and client.host not in ("127.0.0.1", "::1", "localhost"):
return JSONResponse({"error": "forbidden"}, status_code=403)
This specific code path writes cfg["master_password"] = password_in.password to config.json, creating a plaintext credential at rest. Because the same password is later used to derive encryption keys, compromise of this file leads directly to decryption of protected content and cloud-imported data.
if client and client.host not in ("127.0.0.1", "::1", "localhost"):
return JSONResponse({"error": "forbidden"}, status_code=403)
ok1 = set_master_password(password_in.password)
# 同时写到 config.json 作为 fallback(Keychain 访问可能受限)
try:
import json as _json
cfg = {}
The benchmark deletes all existing capsules on the configured service as part of setup, with no confirmation and no scoping to benchmark-owned data. In a real environment this can cause irreversible loss of unrelated data if the token has broad access or if the service is shared.
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).
def download_dataset():
"""Download LongMemEval dataset if not present. Uses curl for reliability."""
DATA_PATH.parent.mkdir(parents=True, exist_ok=True)
if DATA_PATH.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""
core/keychain.py — 跨平台密钥管理
支持:macOS / Windows / Linux
存储策略:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
支持:macOS / Windows / Linux
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
支持:macOS / Windows / Linux
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
支持:macOS / Windows / Linux
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
支持:macOS / Windows / Linux
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
支持:macOS / Windows / Linux
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
"""
from __future__ import annotations
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
"""
from __future__ import annotations
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
存储策略:
- macOS: security 命令(Keychain)
- Windows: cmdkey(凭据管理器)
- Linux: secret-tool(libsecret/GNOME Keyring)
- Fallback: config.json(仅限 api_token,master_password 必须用系统密钥链)
"""
from __future__ import annotations
The module documentation states that master_password must be stored only in the system keychain, but Linux headless and Windows fallback logic allow reading or writing it from config.json in plaintext. This contract mismatch is dangerous because callers and users may rely on stronger storage guarantees than the code actually provides, leading to silent plaintext secret exposure on disk.
set_master_password() is documented as storing to the system keychain, but on Linux headless it routes through _credential_set() to _linux_config_set(), which writes plaintext to config.json. This creates a direct confidentiality risk for the application's most sensitive credential and violates the API's security expectations.
Referencing ~/.claude/settings.json in auto-detection logic shows this module is designed to inspect another agent/tool's private configuration area. In a skill context, cross-tool config access is sensitive because those files may contain environment settings or identifiers the user did not intend to expose to this skill.
Priority:
1. ANTHROPIC_MODEL env var (Claude Code explicit override)
2. ~/.openclaw/openclaw.json → agents.defaults.model.primary
3. ~/.claude/settings.json → env.ANTHROPIC_MODEL
Returns ("", "", "") if no detection possible.
"""
This code path actively constructs a path to ~/.claude/settings.json for inspection during runtime. Access to another tool's config directory increases the risk of unauthorized collection of model settings and associated secrets in environments where skills should be sandboxed.
except:
pass
# 3. Claude Code settings: ~/.claude/settings.json → env.ANTHROPIC_MODEL
claude_settings = os.path.expanduser("~/.claude/settings.json")
if os.path.exists(claude_settings):
try:
Detected: suspicious.dynamic_code_execution, suspicious.env_credential_access, suspicious.exposed_secret_literal (+1 more)