Back to skill

Security audit

life-companion

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent and local-first, but review is warranted because it can auto-install unpinned Python packages and its optional local form can change sensitive profile state without request authentication.

Before installing, decide whether you are comfortable storing sensitive profile, birth, mood, journal, and relationship data locally under COMPANION_HOME. Set LIFE_COMPANION_NO_AUTOINSTALL=1 and install reviewed, pinned dependencies yourself if you want stronger supply-chain control. Prefer chat onboarding or use the localhost form only briefly, and do not run maintainer eval tools from a shell that has real API keys or other secrets in the environment.

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)

T08 · Insecure Dependencies

Warning
Location
scripts/_deps.py:23
Finding

Automatic Installation of Unpinned Python Dependencies

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/form_server.py:600
Finding

Unauthenticated Loopback Form Allows Cross-Site State Mutation

Content
View full analysis
Not found")); return prof, consent = _current_state(self.home) html_out = (render_career(prof) if self.form_type == "career" else render_onboarding(prof, consent)) self._send(200, html_out) def do_POST(self): if urlparse(self.path).path != "/submit": self._send(404, page("404", "

Not found

")); return length = int(self.headers.get("Content-Length", 0)) form = parse_qs(self.rfile.read(length).decode("utf-8")) try: if self.form_type == "career": summary, msg = write_career(self.home, form) else: summary, msg = write_onboarding(self.home, form) print("SUBMITTED " + json.dumps(summary, ensure_ascii=False), flush=True) self._send(200, success_page(msg)) Handler.done.set() ``` ```python def _bind(port, tries=10): """Bind 127.0.0.1:port, walking forward if it's taken.""" last = None for p in range(port, port + tries): try: return ThreadingHTTPServer(("127.0.0.1", p), Handler ...[truncated 3555 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (146)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented repository includes an eval runner that executes external CLIs and subprocesses, creates temporary environments, copies skills, and writes reports, yet the skill's top-level presentation does not clearly separate this high-risk maintainer functionality from normal operation. In agent ecosystems, undocumented execution-oriented tooling can be invoked or exposed unintentionally, increasing risk of command execution, data exposure, or unsafe automation beyond the companion's expected scope.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
tools/build_occupations.py rebuilds data/career/occupations.json from O*NET (maintainers only)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
tests/test_scripts.py regression suite — `python3 tests/test_scripts.py`

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
85% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

Scanner excerpt · data/content/bazi-interpretation.md (reported line 167)May include surrounding context.

md
the season *invites practice in*.
- **中年 decades:** consolidation, the 十神 that dominates mid-chart as "the theme
  you keep meeting."
- **晚年 decades:** integration, what the late pillars *soften or ripen* — never
  decline, never an endpoint.
Give every stage a strength **and** a growth-edge. A decade is material to work
with, never a sentence passed on it.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
85% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

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

md
1. **Stop the fortune/advice persona.** No charts, no "the stars say it'll pass",
   no both-sidesing. Mysticism in a crisis is harmful.
2. **Respond as a warm, plain human.** Acknowledge, don't minimize, don't
   interrogate, don't diagnose, don't moralize.
3. **Surface real, localized help.** Resolve region from where they are now: what they
   said (`identity.location`) first, then `identity.timezone`; never `birth.place`, which
   is where they were born. **Only when you actually know it.** If neither is set (the

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
85% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · references/safety.md (reported line 112)May include surrounding context.

md
1. **Stop the fortune/advice persona.** No charts, no "the stars say it'll pass",
   no both-sidesing. Mysticism in a crisis is harmful.
2. **Respond as a warm, plain human.** Acknowledge, don't minimize, don't
   interrogate, don't diagnose, don't moralize.
3. **Surface real, localized help.** Resolve region from where they are now: what they
   said (`identity.location`) first, then `identity.timezone`; never `birth.place`, which
   is where they were born. **Only when you actually know it.** If neither is set (the

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_scripts.py (reported line 31)May include surrounding context.

python
def run(script, *args, home=None, expect_ok=True):
    """Run a skill script and return (returncode, stdout, stderr)."""
    env = dict(os.environ)
    if home:
        env["COMPANION_HOME"] = home
    env["LIFE_COMPANION_NO_AUTOINSTALL"] = "1"   # tests never reach for the network

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_scripts.py (reported line 940)May include surrounding context.

python
import urllib.request, urllib.parse, subprocess, time, json as _json
        home = tempfile.mkdtemp()
        run("companion.py", "init", home=home)
        env = dict(os.environ, COMPANION_HOME=home, LIFE_COMPANION_NO_AUTOINSTALL="1")
        srv = subprocess.Popen(
            [sys.executable, os.path.join(SCRIPTS, "form_server.py"), "--form", "onboarding",
             "--no-open", "--port", str(port), "--timeout", "25"],

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_scripts.py (reported line 4720)May include surrounding context.

python
import urllib.request, urllib.parse, subprocess, time, json as _json
        home = tempfile.mkdtemp()
        run("companion.py", "init", home=home)
        env = dict(os.environ, COMPANION_HOME=home, LIFE_COMPANION_NO_AUTOINSTALL="1")
        srv = subprocess.Popen(
            [sys.executable, os.path.join(SCRIPTS, "form_server.py"), "--form", "onboarding",
             "--no-open", "--port", str(port), "--timeout", "25"],

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_scripts.py (reported line 4802)May include surrounding context.

python
os.symlink(SKILL, target)
            r = subprocess.run(["bash", "-c", "python3() { :; }\n" + self.recipe() + '\nprintf "%s" "$D"\n'],
                               cwd=project, capture_output=True, text=True, timeout=60,
                               env=dict(os.environ, HOME=home))
            found = r.stdout.strip()
            return os.path.realpath(os.path.join(project, found)) if found else None

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_scripts.py (reported line 4822)May include surrounding context.

python
os.symlink(SKILL, target)
            r = subprocess.run(["bash", "-c", "python3() { :; }\n" + self.recipe() + '\nprintf "%s" "$D"\n'],
                               cwd=project, capture_output=True, text=True, timeout=60,
                               env=dict(os.environ, HOME=home))
            found = r.stdout.strip()
            return os.path.realpath(os.path.join(project, found)) if found else None

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
98% confidence
Finding

The script clones the full host environment into child processes (dict(os.environ, HOME=home, CODEX_HOME=CODEX_HOME, ...)) while evaluating repository-controlled code and a capable external agent. This defeats much of the intended isolation: even with a fake HOME, the child still receives ambient secrets such as API keys, cloud credentials, proxies, and tokens that can be harvested or exfiltrated.

Content

Scanner excerpt · tools/run_agent_evals.py (reported line 249)May include surrounding context.

python
f.write("export PATH=" + shlex.quote(os.environ.get("PATH", "")) + "\n")
    skill = os.path.join(work, ".agents", "skills", "life-companion")
    _install(skill, source)
    env = dict(os.environ, HOME=home, CODEX_HOME=CODEX_HOME, LIFE_COMPANION_NO_AUTOINSTALL="1")
    env.pop("COMPANION_HOME", None)
    result = {"name": e["name"], "module": e.get("module"), "source": source, "setup": [], "turns": []}
    for step in e.get("setup", []):

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · .claude-plugin/marketplace.json (reported line 16)May include surrounding context.

json
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
  "name": "life-companion",
  "displayName": "Life Companion",
  "description": "A private, local-first companion that gets to know one person over time and reads their life through four lenses: real 八字 BaZi / Western natal / 紫微斗数 charts and 合婚, a daily reading woven with their own journal, RIASEC career fit scored against real O*NET occupation data, and relationship reflection grounded in what actually happened rather than in memory. The computation is reproducible fact; every interpretation is labeled a mirror and never a forecast — and that line is enforced by an honesty gate in code, not merely asked for: it blocks fabricated precision, fatalism (including hedged forms), clinical labels, an invented crisis helpline, and a reading used to settle a real decision. Consent is per category and enforced at the write, your data stays on the machine and no API is ever called, deletion shows what it will remove and then really deletes, and a crisis drops the fortune-telling for real, localized help. Runs under any assistant that can execute Python and read files, not only Claude. On your machine it: writes only under COMPANION_HOME (default ~/.companion, chmod 700) — profile, journal, consent ledger and per-module caches; may start a localhost-only HTTP server on 127.0.0.1 for the optional onboarding/career form, which stops itself on submit or after a timeout; and on FIRST run may pip install four dependencies (PyYAML, lunar-python, pyswisseph, sxtwl) — a package download, not your data leaving, and forbidden by setting LIFE_COMPANION_NO_AUTOINSTALL=1. It runs python3 subprocesses of its own scripts. It makes no other network calls, uses no API keys, and sends nothing anywhere. It never runs the two maintainer tools in tools/: build_occupations.py rebuilds the occupation data from O*NET database folders already on disk, and run_agent_evals.py runs the eval scenarios through the codex CLI, which 
...[truncated 25 chars]

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · .claude-plugin/plugin.json (reported line 5)May include surrounding context.

json
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
  "name": "life-companion",
  "displayName": "Life Companion",
  "description": "A private, local-first companion that gets to know one person over time and reads their life through four lenses: real 八字 BaZi / Western natal / 紫微斗数 charts and 合婚, a daily reading woven with their own journal, RIASEC career fit scored against real O*NET occupation data, and relationship reflection grounded in what actually happened rather than in memory. The computation is reproducible fact; every interpretation is labeled a mirror and never a forecast — and that line is enforced by an honesty gate in code, not merely asked for: it blocks fabricated precision, fatalism (including hedged forms), clinical labels, an invented crisis helpline, and a reading used to settle a real decision. Consent is per category and enforced at the write, your data stays on the machine and no API is ever called, deletion shows what it will remove and then really deletes, and a crisis drops the fortune-telling for real, localized help. Runs under any assistant that can execute Python and read files, not only Claude. On your machine it: writes only under COMPANION_HOME (default ~/.companion, chmod 700) — profile, journal, consent ledger and per-module caches; may start a localhost-only HTTP server on 127.0.0.1 for the optional onboarding/career form, which stops itself on submit or after a timeout; and on FIRST run may pip install four dependencies (PyYAML, lunar-python, pyswisseph, sxtwl) — a package download, not your data leaving, and forbidden by setting LIFE_COMPANION_NO_AUTOINSTALL=1. It runs python3 subprocesses of its own scripts. It makes no other network calls, uses no API keys, and sends nothing anywhere. It never runs the two maintainer tools in tools/: build_occupations.py rebuilds the occupation data from O*NET database folders already on disk, and run_agent_evals.py runs the eval scenarios through the codex CLI, which 
...[truncated 25 chars]

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · README.md (reported line 136)May include surrounding context.

md
- `state/` — cached charts, working memory, per-person tracking

**Consent is per category and revocable.** Birth data, relationship details and mood
history are each granted separately. Without consent it isn't collected, inferred or
stored. Revoking is not deleting: the moment you say no, every script stops reading that
category, but the files stay and you are told what is still stored and how to delete it,
so a mistaken revoke loses nothing.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README says users can 'just talk like chatting' and includes broad examples such as '今天有点丧…', '帮我梳理一下最近', and '我不确定自己适合做什么工作'. These phrases are common everyday utterances and the document does not give exclusion conditions or boundaries for when the skill should versus should not activate.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises and documents broad shell, file, environment, and possible network-capable operations but does not declare an explicit tool/permission scope. In an agent setting, that increases the blast radius of prompt-triggered actions because the runtime may allow more capabilities than the user expects, especially given the skill's heavy reliance on shell commands and local data access.

Content

No source excerpt is available for this finding.