Back to skill

Security audit

Subjective Check-In

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its wellness-journal purpose, but it handles very private health and calendar data with under-scoped runtime controls that deserve review before installation.

Review before installing. Use this only if you are comfortable storing mood, energy, physical notes, intentions, sleep, and calendar-derived context in Fulcra. Prefer a version that pins the Fulcra CLI, disallows arbitrary `FULCRA_API_BASE` and `FULCRA_CLI_COMMAND` overrides, and asks before every save.

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

Error
Location
scripts/fulcra_checkin.py:39
Finding

Fulcra bearer token and sensitive wellness data can be redirected to an arbitrary server

Content
View full analysis

Vulnerability Details

File Location: scripts/fulcra_checkin.py:39, 128-133
Vulnerability Type: Unvalidated credential-bearing endpoint override
Risk Level: High

Vulnerable Code

python
API_BASE = os.environ.get("FULCRA_API_BASE", "https://api.fulcradynamics.com").rstrip("/")
python
def request(method: str, path: str, payload: Any | None = None) -> tuple[int, str]:
    headers = {"Authorization": f"Bearer {access_token()}"}
    data = None
    if payload is not None:
        data = json.dumps(payload).encode()
        headers["Content-Type"] = "application/json"
    req = urllib.request.Request(API_BASE + path, data=data, headers=headers, method=method)

Technical Analysis

The destination of every direct API request is controlled by the FULCRA_API_BASE environment variable. The program does not validate the scheme or hostname before attaching the genuine Fulcra bearer token to the request.

Consequently, a modified execution environment can redirect authenticated requests from the intended https://api.fulcradynamics.com service to an attacker-controlled server. The override also permits non-HTTPS URLs, allowing credentials and payloads to be transmitted without transport encryption.

This affects both read and write operations. In addition to the bearer token, write requests can contain intimate information such as mood, energy, physical symptoms, sleep information, social battery, and daily intentions. Allowing those values to leave the approved Fulcra boundary exceeds the minimum network privileges necessary for the declared check-in functionality.

Attack Path

  1. An attacker gains the ability to influence the Skill's environment, wrapper script, process launcher, or Agent configuration.
  2. The attacker sets FULCRA_API_BASE to an attacker-controlled endpoint, such as https://attacker.example.
  3. The user or Agent invokes the context or save command.
  4. T ...[truncated 1098 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the FULCRA_API_BASE override from production execution and use a fixed trusted endpoint:
    python
    API_BASE = "https://api.fulcradynamics.com"
    
  2. If an override is required for development, gate it behind an explicit test mode that refuses to use production credentials.
  3. Parse the URL and enforce both:
    • Scheme exactly equal to https.
    • Hostname exactly equal to an approved Fulcra hostname.
  4. Never attach a production bearer token to a non-allowlisted origin.
  5. Reject URLs containing user information, unexpected ports, fragments, or ambiguous hostname forms.
  6. Use separate, narrowly scoped test credentials for development endpoints.
  7. Document the permitted endpoint and fail closed when validation fails.
  8. Consider server-issued tokens with the narrowest available read/write scopes and short expiration periods.

T08 · Insecure Dependencies

Error
Location
scripts/fulcra_checkin.py:41
Finding

Unpinned Fulcra CLI is dynamically retrieved and executed in a credential-bearing workflow

Content
View full analysis

Vulnerability Details

File Location: scripts/fulcra_checkin.py:41, 110-117, 325-334; SKILL.md:38-44, 150-155
Vulnerability Type: Unpinned executable dependency and unsafe command override
Risk Level: High

Vulnerable Code

python
CLI_COMMAND = os.environ.get("FULCRA_CLI_COMMAND", "uv tool run fulcra-api")
python
env = os.environ.copy()
env["HOME"] = DEFAULT_HOME
env.setdefault("PYTHONUTF8", "1")
cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), "auth", "print-access-token"]
try:
    token = subprocess.check_output(
        cmd, env=env, text=True, stderr=subprocess.DEVNULL, timeout=60
    ).strip()
python
def run_cli(args: list[str]) -> tuple[int, str]:
    env = os.environ.copy()
    env["HOME"] = DEFAULT_HOME
    env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), *args]
    try:
        proc = subprocess.run(cmd, env=env, text=True, capture_output=True, timeout=120)

The Skill instructions also direct execution without a pinned version:

bash
uv tool run fulcra-api auth print-access-token
bash
uv tool run fulcra-api auth login

Technical Analysis

The default command uses uv tool run fulcra-api without pinning a reviewed package version or supplying an integrity hash. This permits the effective executable code to change after the Skill has been audited. The project contains no lockfile or equivalent artifact that establishes the exact package build expected at runtime.

The dependency executes in a particularly sensitive context:

  • It participates in authentication and prints an access token.
  • It runs with the user's normal local permissions.
  • It receives the user's HOME directory.
  • It reads private sleep and calendar records.
  • The documented login workflow permits access to the Fulcra credential cache.

In addition, FULCRA_CLI_COMMAND allows the co ...[truncated 2509 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin fulcra-api to a reviewed, immutable version instead of resolving the latest available package:
    bash
    uv tool run 'fulcra-api==REVIEWED_VERSION'
    
  2. Maintain a lockfile or equivalent dependency manifest with integrity hashes.
  3. Prefer installing the pinned CLI into a dedicated virtual environment during a controlled setup step rather than retrieving it during each Skill invocation.
  4. Verify the package publisher, source repository, release signature, and package hashes.
  5. Remove FULCRA_CLI_COMMAND from production behavior. If configurability is required:
    • Require an absolute executable path.
    • Resolve and validate the canonical path.
    • Restrict it to an administrator-configured allowlist.
    • Reject additional embedded arguments.
  6. Execute the CLI with a minimized environment rather than forwarding the entire process environment.
  7. Use a narrowly scoped service interface for token retrieval so the external executable cannot directly inspect broader credentials.
  8. Apply the least available Fulcra token scopes and short expiration periods.
  9. Update SKILL.md and README.md so every documented invocation uses the same pinned and verified dependency.
  10. Add automated checks that reject unpinned dependency commands and unexpected CLI executable paths.
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (24)

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

Critical
Category
Data Flow
Confidence
99% confidence
Finding

API_BASE is taken from the environment and used to construct authenticated HTTP requests carrying the bearer token. If an attacker can set FULCRA_API_BASE, the script will send valid authorization headers and sensitive health/check-in data to an attacker-controlled endpoint, enabling credential exfiltration and private data disclosure.

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 135)May include surrounding context.

python
headers["Content-Type"] = "application/json"
    req = urllib.request.Request(API_BASE + path, data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req, timeout=45) as resp:
            body = resp.read()
            return resp.status, body.decode() if body else ""
    except urllib.error.HTTPError as exc:

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 97)May include surrounding context.

md
Tone rules that matter:
- Warm and concise beats thorough. One question at a time.
- Mirror their language. If they say "wiped," reflect "wiped."
- Don't moralize about sleep or screen time. You're capturing, not correcting.
- If they give a one-word answer, that's fine -- don't pry. Move on.

## Step 3 -- Save to Fulcra

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

text

This opens a browser, asks the user to approve a short code, and caches credentials at
`~/.config/fulcra/credentials.json`; later calls refresh silently. The login polls for
about two minutes, so start it and let the user approve at their pace.

Never print access tokens, refresh tokens, or the contents of the credentials file.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
`~/.config/fulcra/credentials.json`; later calls refresh silently. The login polls for
about two minutes, so start it and let the user approve at their pace.

Never print access tokens, refresh tokens, or the contents of the credentials file.

Windows first-run gotchas (details in `references/fulcra-write-notes.md`): the CLI can
fail to create its `~/.config/fulcra` folder if `~/.config` doesn't exist yet, and the

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
`~/.config/fulcra/credentials.json`; later calls refresh silently. The login polls for
about two minutes, so start it and let the user approve at their pace.

Never print access tokens, refresh tokens, or the contents of the credentials file.

Windows first-run gotchas (details in `references/fulcra-write-notes.md`): the CLI can
fail to create its `~/.config/fulcra` folder if `~/.config` doesn't exist yet, and 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 · scripts/fulcra_checkin.py (reported line 108)May include surrounding context.

python
if env_token:
        _token_cache = env_token.strip()
        return _token_cache
    env = os.environ.copy()
    env["HOME"] = DEFAULT_HOME
    env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), "auth", "print-access-token"]

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 · scripts/fulcra_checkin.py (reported line 327)May include surrounding context.

python
if env_token:
        _token_cache = env_token.strip()
        return _token_cache
    env = os.environ.copy()
    env["HOME"] = DEFAULT_HOME
    env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), "auth", "print-access-token"]

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 118)May include surrounding context.

python
).strip()
    except (FileNotFoundError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as exc:
        fail(
            "Could not get a Fulcra access token. Set FULCRA_ACCESS_TOKEN, or make the "
            f"Fulcra CLI runnable (`{CLI_COMMAND} auth login`). Underlying error: {exc}"
        )
    if not token:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 122)May include surrounding context.

python
).strip()
    except (FileNotFoundError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as exc:
        fail(
            "Could not get a Fulcra access token. Set FULCRA_ACCESS_TOKEN, or make the "
            f"Fulcra CLI runnable (`{CLI_COMMAND} auth login`). Underlying error: {exc}"
        )
    if not token:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README promotes collecting and saving sensitive wellness/journal data to Fulcra but does not clearly warn users that subjective mental, physical, and social state information will be stored in an external system. In this skill context, the data is especially privacy-sensitive, so lack of explicit disclosure can lead to uninformed consent and accidental exposure of intimate personal information.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The README instructs users to run an external MCP/API tool by name only (uv tool run fulcra-api) without pinning a version or immutable source. That creates a supply-chain risk: a future compromised, malicious, or incompatible release could be installed and executed implicitly by users following the documentation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes shell commands, reads environment-backed authentication state, and accesses remote Fulcra services, but it does not declare any explicit tool restrictions. That creates unnecessary ambient authority: if the skill is triggered, the agent may execute shell/network actions beyond what a reviewer can easily verify from metadata.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger conditions include broad everyday phrases like 'how am I doing today?' and allow proactive activation when the user casually mentions sleep or feelings. That increases the chance of unintended execution, causing the agent to read calendar/sleep context and store sensitive subjective-health data without sufficiently explicit consent for this specific workflow.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

The skill intentionally persists highly sensitive wellness and schedule-adjacent information to Fulcra on an ongoing basis as part of a daily routine. While persistence is core functionality rather than obviously malicious behavior, the stored data includes mood, physical symptoms, social battery, intentions, sleep context, and timestamps, creating meaningful privacy and profiling risk if invoked unexpectedly or without clear consent.

Content

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

md
2. **Have the conversation.** Ask the questions below in a natural back-and-forth,
   weaving in the context. Adapt to what they say -- if they volunteer their energy
   while answering the mood question, don't re-ask it.
3. **Save the check-in to Fulcra.** Once you've covered the ground, write it.
4. **Close warmly.** One or two sentences reflecting what you heard, plus their
   intention for the day. Don't recite the saved fields back like a receipt.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding

The skill relies on uv tool run fulcra-api without pinning a version, so behavior depends on whatever package version is resolved at execution time. A compromised upstream release or breaking change could alter authentication or data-handling behavior and silently expand risk.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding

This is a second unpinned invocation of uv tool run fulcra-api, again introducing supply-chain and reproducibility risk. Because it is used for login/auth flows, a malicious or altered upstream package could mishandle credentials or prompt unsafe user actions.

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 · references/fulcra-write-notes.md (reported line 1)May include surrounding context.

md
# Fulcra read/write notes (for the subjective-checkin skill)

Read this when a write fails, verification comes up short, or you need to understand
exactly what the bundled `fulcra_checkin.py` does under the hood. It is NOT needed for

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The documentation instructs use of uv tool run fulcra-api without pinning a specific version or digest, which can cause the skill to execute whatever version is currently resolved at runtime. If the upstream package changes unexpectedly or is compromised, the skill may consume altered behavior or malicious code, especially because this CLI is used to access sensitive user data and influence subsequent writes.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The script documentation indicates use of uv tool run fulcra-api without a pinned version. That allows the resolved CLI implementation to drift over time or be replaced by a malicious upstream release, which is particularly sensitive here because the tool is trusted to mint access tokens and read personal data.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The default runtime command uses uv tool run fulcra-api without version pinning, so the skill depends on mutable external tooling. In this skill, that increases risk because the tool is used for token retrieval and context reads, giving a compromised dependency access to credentials and highly sensitive user data.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 113)May include surrounding context.

python
env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), "auth", "print-access-token"]
    try:
        token = subprocess.check_output(
            cmd, env=env, text=True, stderr=subprocess.DEVNULL, timeout=60
        ).strip()
    except (FileNotFoundError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as exc:

Tainted flow: 'cmd' from os.environ.get (line 330, credential/environment) → subprocess.check_output (code execution)

Medium
Category
Data Flow
Confidence
97% confidence
Finding

The token acquisition path executes a command whose base comes from FULCRA_CLI_COMMAND. A malicious value can cause execution of an attacker-chosen binary during credential retrieval, which is especially dangerous because this path handles authentication material and runs before normal API operations.

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 113)May include surrounding context.

python
env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), "auth", "print-access-token"]
    try:
        token = subprocess.check_output(
            cmd, env=env, text=True, stderr=subprocess.DEVNULL, timeout=60
        ).strip()
    except (FileNotFoundError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as exc:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 332)May include surrounding context.

python
env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), *args]
    try:
        proc = subprocess.run(cmd, env=env, text=True, capture_output=True, timeout=120)
    except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
        return 1, f"CLI invocation failed: {exc}"
    if proc.returncode != 0:

Tainted flow: 'cmd' from os.environ.get (line 330, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
97% confidence
Finding

The executable command is derived from FULCRA_CLI_COMMAND, an environment variable, and then executed. In an agent runtime, environment variables are part of the trust boundary; if an attacker or compromised wrapper can influence them, they can replace the intended Fulcra CLI with an arbitrary program and gain code execution in the skill context.

Content

Scanner excerpt · scripts/fulcra_checkin.py (reported line 332)May include surrounding context.

python
env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), *args]
    try:
        proc = subprocess.run(cmd, env=env, text=True, capture_output=True, timeout=120)
    except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
        return 1, f"CLI invocation failed: {exc}"
    if proc.returncode != 0:

Static analysis

No suspicious patterns detected.