Back to skill

Security audit

Relationship science coach

Security checks for vulnerabilities and agentic risk

Overview

The coaching content is mostly coherent, but optional validation and test scripts can run Python from user-selected folders without strong warnings.

Install only if you want an adult relationship-coaching skill that may discuss sex, desire, kink, and intimate conflict. Do not run the bundled validation or smoke-test scripts against untrusted or writable folders unless you isolate them, because they may execute Python code from that target folder.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/validate_skill.py:169
Finding
Static Validator Executes Python Files from an Untrusted Target Package## Vulnerability Details **File Location**: `scripts/validate_skill.py`, lines 169–194 **Vulnerability Type**: Arbitrary local code execution during package validation **Risk Level**: High ### Vulnerable Code ```python def validate_scripts(root: Path, errors: list[str], warnings: list[str]) -> list[dict[str, Any]]: results: list[dict[str, Any]] = [] scripts_dir = root / "scripts" if not scripts_dir.exists(): return results for script in sorted(scripts_dir.glob("*.py")): try: proc = subprocess.run( [sys.executable, str(script), "--help"], cwd=str(root), text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=10, ) except subprocess.TimeoutExpired: errors.append(f"{script.relative_to(root)} --help timed out.") results.append({"script": str(script.relative_to(root)), "help_ok": False, "reason": "timeout"}) continue ok = proc.returncode == 0 and "usage" in proc.stdout.lower() if not ok: errors.append(f"{script.relative_to(root)} --help failed or did not print usage.") ``` The execution is enabled through the caller-controlled validation option: ```python root = Path(args.path).resolve() ... script_results = validate_scripts(root, errors, warnings) if args.check_scripts else [] ``` ### Technical Analysis The validator accepts an arbitrary package root and, when `--check-scripts` is supplied, discovers every `*.py` file beneath that root's `scripts/` directory and invokes it with the current Python interpreter. Supplying `--help` does not make this operation safe. Python executes module-level statements before a script processes command-line arguments. Consequently, an attacker-controlled script can execute an arbitrary payload before displaying help, exiti ...[truncated 1903 chars]
Remediation
## Remediation Suggestions 1. **Remove runtime execution from static validation.** Do not invoke package scripts merely to verify their help output. 2. Parse Python files with `ast.parse()` to validate syntax without executing module-level statements. 3. Inspect `argparse` usage statically where practical, or treat help-output testing as a separate operation that is disabled for untrusted packages. 4. If execution is operationally necessary, require an explicit trusted-package flag and display a clear warning that arbitrary code will run. 5. Execute runtime checks inside a hardened sandbox with: - No inherited credentials or sensitive environment variables. - No network access. - A read-only package mount. - No writable host directories. - A dedicated unprivileged user. - Process, memory, and execution-time limits. - Restrictions on child-process creation where supported. 6. In automated review systems, separate static inspection from post-approval runtime testing and never run unreviewed scripts on a privileged CI worker.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/smoke_test.py:61
Finding
Smoke-Test Runner Executes Replaced Scripts from a Caller-Selected Root## Vulnerability Details **File Location**: `scripts/smoke_test.py`, lines 61–69 and 115–123 **Vulnerability Type**: Arbitrary local code execution through an untrusted test root **Risk Level**: Medium ### Vulnerable Code ```python def run_json(root: Path, args: list[str], stdin: str | None = None) -> dict[str, Any]: proc = subprocess.run(args, cwd=str(root), input=stdin, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15) if proc.returncode != 0: raise RuntimeError(f"Command failed: {' '.join(args)}\nSTDOUT: {proc.stdout}\nSTDERR: {proc.stderr}") try: return json.loads(proc.stdout) except json.JSONDecodeError as exc: raise RuntimeError(f"Command did not produce JSON: {' '.join(args)}\n{proc.stdout}") from exc ``` Fixed filenames are resolved relative to the selected root and then executed: ```python def router_tests(root: Path) -> list[dict[str, Any]]: results = [] router = root / "scripts" / "intake_router.py" for case in ROUTER_CASES: out = run_json(root, [sys.executable, str(router), "--text", case["text"]]) ``` The root is supplied through a command-line argument: ```python def main(argv: Optional[Iterable[str]] = None) -> int: parser = argparse.ArgumentParser( description="Run deterministic smoke tests for relationship-science-coach scripts.", epilog="Example: python3 scripts/smoke_test.py . --pretty", ) parser.add_argument("path", nargs="?", default=".", help="Skill root path. Default: current directory.") parser.add_argument("--pretty", action="store_true", help="Pretty-print JSON output.") args = parser.parse_args(argv) root = Path(args.path).resolve() results = router_tests(root) + helper_script_tests(root) ``` ### Technical Analysis The smoke-test runner accepts an arbitrary filesystem path and executes expected Python filenames from that path, incl ...[truncated 2060 chars]
Remediation
## Remediation Suggestions 1. Bind the test root to the smoke runner's own package directory rather than accepting an arbitrary positional path: ```python root = Path(__file__).resolve().parent.parent ``` 2. If testing external roots is required, clearly mark that mode as executing untrusted code and require an explicit opt-in flag. 3. Verify package identity and script integrity before execution, for example through approved hashes or a trusted manifest. 4. Run external-package smoke tests in an isolated container or sandbox with: - No network access. - No secrets or inherited credentials. - Read-only source mounts. - A disposable writable directory. - A dedicated unprivileged account. - Resource and child-process restrictions. 5. Keep static package auditing separate from runtime smoke tests. An unreviewed package should pass static inspection before any bundled script is executed. 6. Document that the runner must not be pointed at untrusted, shared, or attacker-writable directories.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (17)

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
## “I’m not attracted to my partner anymore”

Do not moralise. Explore resentment, stress, familiarity, body changes, depression, porn/novelty, conflict, lack of separateness, or values shifts. Offer erotic aliveness audit and honest conversation.

## “We have different love languages”
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.

Exfiltration Commands

High
Category
Prompt Injection
Content
],
    "surveillance": [
        "spy on", "track their phone", "track her phone", "track his phone", "hack", "password",
        "read their messages", "secretly record", "airtag", "gps tracker",
    ],
    "diagnosis_as_leverage": [
        "diagnose my partner", "diagnose her", "diagnose him", "diagnose them", "prove narcissist",
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- id: pleasure_equity
    title: Pleasure equity reset
    use_when: Sex is penetration-centred, orgasm gap, one partner feels sex is not for them.
    avoid_when: User wants guarantee of orgasm or techniques without consent.
    output: Partner-specific feedback and non-goal exploration.
    reference: references/SEX_INTIMACY_AND_DESIRE.md
  - id: erotic_aliveness
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- id: pleasure_equity
    title: Pleasure equity reset
    use_when: Sex is penetration-centred, orgasm gap, one partner feels sex is not for them.
    avoid_when: User wants guarantee of orgasm or techniques without consent.
    output: Partner-specific feedback and non-goal exploration.
    reference: references/SEX_INTIMACY_AND_DESIRE.md
  - id: erotic_aliveness
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- id: pleasure_equity
    title: Pleasure equity reset
    use_when: Sex is penetration-centred, orgasm gap, one partner feels sex is not for them.
    avoid_when: User wants guarantee of orgasm or techniques without consent.
    output: Partner-specific feedback and non-goal exploration.
    reference: references/SEX_INTIMACY_AND_DESIRE.md
  - id: erotic_aliveness
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- id: pleasure_equity
    title: Pleasure equity reset
    use_when: Sex is penetration-centred, orgasm gap, one partner feels sex is not for them.
    avoid_when: User wants guarantee of orgasm or techniques without consent.
    output: Partner-specific feedback and non-goal exploration.
    reference: references/SEX_INTIMACY_AND_DESIRE.md
  - id: erotic_aliveness
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- id: pleasure_equity
    title: Pleasure equity reset
    use_when: Sex is penetration-centred, orgasm gap, one partner feels sex is not for them.
    avoid_when: User wants guarantee of orgasm or techniques without consent.
    output: Partner-specific feedback and non-goal exploration.
    reference: references/SEX_INTIMACY_AND_DESIRE.md
  - id: erotic_aliveness
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- id: pleasure_equity
    title: Pleasure equity reset
    use_when: Sex is penetration-centred, orgasm gap, one partner feels sex is not for them.
    avoid_when: User wants guarantee of orgasm or techniques without consent.
    output: Partner-specific feedback and non-goal exploration.
    reference: references/SEX_INTIMACY_AND_DESIRE.md
  - id: erotic_aliveness
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.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The description is extremely broad and encourages use for many sensitive adult relationship topics while only narrowly specifying when to redirect. That can cause over-invocation in situations involving abuse, coercion, mental health, sexual consent, or other high-risk interpersonal dynamics where a general coaching skill may give inappropriate guidance instead of escalating or deferring.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
> “I’m not going to give choking instructions because neck pressure and breath restriction can cause serious harm. If the turn-on is dominance or surrender, use safer channels: verbal control, pacing, consensual restraint that is easy to exit, eye contact, or a hand on the upper chest/shoulder rather than neck.”

## “My partner choked me during sex without asking”

Consent violation. Treat as safety and boundary issue. Do not suggest better kink communication as if it was mutual.
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
> “I’m not going to give choking instructions because neck pressure and breath restriction can cause serious harm. If the turn-on is dominance or surrender, use safer channels: verbal control, pacing, consensual restraint that is easy to exit, eye contact, or a hand on the upper chest/shoulder rather than neck.”

## “My partner choked me during sex without asking”

Consent violation. Treat as safety and boundary issue. Do not suggest better kink communication as if it was mutual.
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
> “I’m not going to give choking instructions because neck pressure and breath restriction can cause serious harm. If the turn-on is dominance or surrender, use safer channels: verbal control, pacing, consensual restraint that is easy to exit, eye contact, or a hand on the upper chest/shoulder rather than neck.”

## “My partner choked me during sex without asking”

Consent violation. Treat as safety and boundary issue. Do not suggest better kink communication as if it was mutual.
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.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
These templates include explicit relationship and sexual-content guidance such as desire discrepancy, erotic reset, and kink conversation flows without a clear adult-only and sensitivity boundary. In a general-purpose agent skill, that can lead to the system offering sexual coaching to minors or to users who did not expect intimate content, creating safeguarding and appropriateness risks even if the content is framed around consent and lower-risk practices.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run_json(root: Path, args: list[str], stdin: str | None = None) -> dict[str, Any]:
    proc = subprocess.run(args, cwd=str(root), input=stdin, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15)
    if proc.returncode != 0:
        raise RuntimeError(f"Command failed: {' '.join(args)}\nSTDOUT: {proc.stdout}\nSTDERR: {proc.stderr}")
    try:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
return results
    for script in sorted(scripts_dir.glob("*.py")):
        try:
            proc = subprocess.run(
                [sys.executable, str(script), "--help"],
                cwd=str(root),
                text=True,
Confidence
94% confidence
Finding
The validator optionally executes every bundled Python script with `--help`, which means analyzing an untrusted skill can run attacker-controlled code on the host. Although `subprocess.run` is used without a shell and with a fixed argument shape, the core issue is still arbitrary code execution because the target script itself is untrusted.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The `--check-scripts` flag causes the tool to execute code from the skill package, but the CLI help and behavior do not clearly warn users that this runs untrusted bundled scripts. In a security review context, this increases the chance that a reviewer or automation system will trigger malicious code unintentionally.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This code produces guidance covering sensitive sexual topics such as BDSM, consensual non-consent fantasy, and alternatives to breath play, but the script itself provides no visible warning, disclaimer, or routing notice that the content is for consensual adults only or may be inappropriate in unsafe contexts. Although some individual worksheet entries include cautions in their 'avoid' fields, the tool emits material directly without a general user disclosure at invocation time or in the module/CLI help about the sensitivity of these outputs.

Static analysis

No suspicious patterns detected.