Back to skill

Security audit

Meeting Cadence Optimizer

Security checks for vulnerabilities and agentic risk

Overview

The main meeting analysis is coherent, but the package includes broad, credential-using read/write helpers that go beyond the stated meeting-cadence purpose.

Review before installing. The documented analysis and optional save behavior are understandable, but install only if you are comfortable with the skill accessing Fulcra reflection history and with the package containing broader CRM/Fulcra helper scripts. Prefer using `analyze` first, require explicit approval for `save` or weekly automation, pin the Fulcra CLI version, avoid setting API base or CLI command override environment variables unless you trust them, and do not provide an Attio API key unless you intentionally want the unrelated Attio helper surface available.

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/lib/fulcra_annotations.py:57
Finding

Unpinned Third-Party CLI Is Downloaded and Executed with Access to Fulcra Credentials

Content
View full analysis
Remediation
View remediation
``` 2. Use a lockfile and require cryptographic hashes for all resolved artifacts where supported. 3. Configure an explicit, trusted package index and disable untrusted fallback indexes. 4. Prefer installing the reviewed dependency during a controlled installation step instead of downloading executable code during normal Skill execution. 5. Record and verify the expected package version before requesting an access token. 6. Run the external CLI with a minimized environment containing only variables required for authentication. 7. Consider replacing the external token-printing subprocess with a reviewed library or narrowly scoped credential-provider integration. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/lib/concierge_secrets.py:50
Finding

Secret Temporary File Is Populated Before Restrictive Permissions Are Applied

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (39)

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

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The request destination is derived from ATTIO_API_BASE, which is taken directly from the environment and then used to send authenticated HTTP requests with the Bearer token. If an attacker can influence the environment, they can redirect traffic to an attacker-controlled host and exfiltrate the Attio API key and any CRM data sent in requests.

Content

Scanner excerpt · scripts/lib/attio_client.py (reported line 54)May include surrounding context.

python
headers["Content-Type"] = "application/json"
    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            body = resp.read().decode() or "{}"
            return resp.status, json.loads(body)
    except urllib.error.HTTPError as exc:

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

API_BASE is sourced from the environment and concatenated into outbound requests that include the Bearer access token in the Authorization header. If an attacker can set FULCRA_API_BASE, the helper will send authenticated requests and potentially sensitive payloads to an attacker-controlled server, resulting in credential exfiltration and unauthorized data access. This is more dangerous here because the skill claims deterministic analysis of the user's own data, but the helper can redirect all reads and writes off-platform.

Content

Scanner excerpt · scripts/lib/fulcra_annotations.py (reported line 84)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=30) as response:
            body = response.read()
            return response.status, body.decode() if body else ""
    except urllib.error.HTTPError as exc:

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Exposing a generic event readback CLI and listing arbitrary annotation definitions exceeds the declared use case and broadens data exposure. Even if read-only, hidden general-purpose access can reveal unrelated personal records beyond meeting-cadence inputs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill description promises read-back deterministic analysis, but the implementation includes record creation, assertion, update, deletion, and note insertion. That mismatch is dangerous because users and orchestrators may grant this skill trust appropriate for analytics while it actually has write/delete capability against CRM records.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This file exposes broad create, update, delete, and note-writing operations for arbitrary Attio objects, far beyond the stated skill purpose of deterministic read-back analysis of user history. In an agent setting, this unnecessarily expands the action surface and enables destructive or unauthorized CRM modifications if the skill is invoked or repurposed incorrectly.

Content

No source excerpt is available for this finding.

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/lib/concierge_cli.py (reported line 30)May include surrounding context.

python
def run_cli(args: list[str]) -> tuple[int, str]:
    env = os.environ.copy()
    env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), *args]
    try:

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/lib/fulcra_annotations.py (reported line 55)May include surrounding context.

python
def run_cli(args: list[str]) -> tuple[int, str]:
    env = os.environ.copy()
    env.setdefault("PYTHONUTF8", "1")
    cmd = [*shlex.split(CLI_COMMAND, posix=(os.name != "nt")), *args]
    try:

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/lib/attio_client.py (reported line 7)May include surrounding context.

python
Resolution order for any key:
  1. Environment variable (e.g. ATTIO_API_KEY) -- wins, good for CI / one-offs.
  2. ~/.fulcra-concierge/secrets.json -- the persistent local store.

Secrets are never printed. Skills read keys through `get_secret`; they should
not open secrets.json themselves. Keeping one loader means one place to harden

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/lib/concierge_secrets.py (reported line 5)May include surrounding context.

python
Resolution order for any key:
  1. Environment variable (e.g. ATTIO_API_KEY) -- wins, good for CI / one-offs.
  2. ~/.fulcra-concierge/secrets.json -- the persistent local store.

Secrets are never printed. Skills read keys through `get_secret`; they should
not open secrets.json themselves. Keeping one loader means one place to harden

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/lib/concierge_secrets.py (reported line 8)May include surrounding context.

python
Resolution order for any key:
  1. Environment variable (e.g. ATTIO_API_KEY) -- wins, good for CI / one-offs.
  2. ~/.fulcra-concierge/secrets.json -- the persistent local store.

Secrets are never printed. Skills read keys through `get_secret`; they should
not open secrets.json themselves. Keeping one loader means one place to harden

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/lib/concierge_secrets.py (reported line 9)May include surrounding context.

python
Secrets are never printed. Skills read keys through `get_secret`; they should
not open secrets.json themselves. Keeping one loader means one place to harden
(file perms, future keychain support) instead of N copies across skills.
"""
from __future__ import annotations

Credential Access

High
Category
Privilege Escalation
Confidence
77% confidence
Finding

The module stores secrets in a plaintext JSON file under a path that can be redirected by the FULCRA_CONCIERGE_HOME environment variable. In multi-user, shared, or improperly permissioned environments, this increases the risk of local credential disclosure or accidental placement of secrets in an unsafe location.

Content

Scanner excerpt · scripts/lib/concierge_secrets.py (reported line 17)May include surrounding context.

python
import os
from pathlib import Path

SECRETS_PATH = Path(os.environ.get("FULCRA_CONCIERGE_HOME", Path.home() / ".fulcra-concierge")) / "secrets.json"


def _load_file() -> dict:

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

set_secret persists secrets to plaintext secrets.json and only applies chmod to the temporary file before replacement, which may leave the final file permissions dependent on platform behavior or existing filesystem state. That creates a local credential exposure risk if the final file or containing directory is accessible to other users or processes.

Content

Scanner excerpt · scripts/lib/concierge_secrets.py (reported line 47)May include surrounding context.

python
def set_secret(name: str, value: str) -> None:
    """Persist a secret into secrets.json (merging with any existing keys) and
    lock the file down to the current user. Used by setup helpers, not skills."""
    SECRETS_PATH.parent.mkdir(parents=True, exist_ok=True)
    data = _load_file()

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This module is a generic helper that can create, update, delete, and record Fulcra annotations, which materially exceeds the skill's declared purpose of read-only meeting-cadence analysis. Over-privileged capabilities increase the blast radius of misuse, prompt injection, operator error, or later code reuse, enabling unauthorized mutation of the user's data rather than merely analysis. The mismatch with the skill description makes this especially concerning.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code can create tags and resolve missing tags by auto-creating them, which is a write capability unrelated to analyzing historical meeting/debrief correlations. This allows unintended data mutation and taxonomy pollution, and in a compromised agent flow could silently alter a user's Fulcra metadata. Because the skill is supposed to read existing annotations only, these mutation paths are unjustified and raise risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The module can ingest new records into Fulcra and verify them, transforming a retrospective analysis skill into an active data-writing tool. That creates opportunities for silent falsification of user records, contamination of longitudinal analytics, and misuse of the user's account if triggered unexpectedly. Given the skill description explicitly says to read back annotations and compute numbers deterministically, this discrepancy makes the behavior more dangerous.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README advertises broad trigger phrases such as 'optimize my schedule' and 'too many meetings' that can plausibly appear in ordinary conversation, increasing the chance the skill is invoked when the user did not specifically intend this analysis. Unintended invocation is especially relevant because the skill reads personal annotation history, so an over-broad trigger can cause unnecessary access to sensitive behavioral data even if the computation itself is deterministic.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares no explicit tool restrictions even though it references shell execution, network access, environment use, and write-capable behavior elsewhere in the file. In an agent setting, missing scope boundaries can let the model invoke more capability than the user would expect, increasing the blast radius if the skill is misused or paired with compromised helper scripts.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
80% confidence
Finding

The prerequisite uv tool run fulcra-api auth login references an external tool without a pinned version, so behavior may drift over time or a compromised upstream release could change what is executed. For agent skills, unpinned dependencies weaken reproducibility and create a supply-chain risk at the authentication boundary.

Content

No source excerpt is available for this finding.