Back to skill

Security audit

Homeroom Week Voice Pack

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Beatra homeroom voice-generation skill, but it grants broad shared account access and silently updates executable code, so it should be reviewed carefully before installation.

Install only if you trust Beatra with a shared account-level device credential that can cover more than this one voice workflow. Consider disabling automatic updates with `python3 scripts/mcp_client.py update --auto off` before routine use, and be aware that authorization sends device/platform metadata and stores a persistent token under `~/.beatra`.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/authorize.py:34
Finding

Overprivileged Device Token Grants Unrelated Media and Account Capabilities

Content
View full analysis

Vulnerability Details

File Location: scripts/authorize.py, lines 34–37
Vulnerability Type: Excessive OAuth scope and violation of least privilege
Risk Level: High

Vulnerable Code

python
SCOPE = (
    "mcp:tools artifacts:write images:generate videos:generate music:generate "
    "speech:generate voices:read voices:write wallet:spend tasks:read artifacts:read tasks:cancel"
)

The declared Skill functionality requires text-to-speech generation, voice selection, optional voice cloning and sample upload, and access to the resulting tasks. The requested token additionally authorizes image, video, and music generation, unrestricted MCP tool access, wallet spending, broad artifact access, and task cancellation.

Technical Analysis

The authorization scope is a shared, full-account capability rather than a package-specific credential. This violates least privilege because compromise or misuse of this Skill grants access to operations unrelated to producing homeroom voice clips.

The broad mcp:tools permission is especially sensitive when combined with the unrestricted tool dispatcher in scripts/mcp_client.py. The client can attach the bearer credential to arbitrary MCP tool calls instead of limiting execution to the small set required by the Skill.

Although the token is stored with restrictive POSIX permissions, secure storage does not compensate for excessive server-side privileges. Any code or instruction capable of invoking the bundled client inherits the complete authorization scope.

Attack Path

  1. The user runs scripts/authorize.py.
  2. The authorization flow requests the complete scope shown above.
  3. The returned bearer token is stored in ~/.beatra/credentials.json.
  4. An attacker-controlled instruction, compromised package update, or unauthorized local caller invokes scripts/mcp_client.py.
  5. The client attaches the shared bearer token to the request.
  6. The caller uses ...[truncated 655 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace the shared full-scope token with a package-specific, least-privilege credential.
  • Restrict the default scope to text-to-speech, required model and voice reads, package-owned task reads, and narrowly scoped artifact creation.
  • Request voice-cloning and upload privileges only when the user explicitly selects cloning.
  • Remove image, video, music, broad artifact-read, wallet-spend, and task-cancellation scopes unless separately required and approved.
  • Separate read-only wallet access from credit-spending authority.
  • Restrict task reads and cancellation to tasks created by this package or installation.
  • Display the exact requested permissions to the user before authorization.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/mcp_client.py:1463
Finding

Authenticated Client Allows Arbitrary MCP Tool Dispatch

Content
View full analysis

Vulnerability Details

File Location: scripts/mcp_client.py, lines 1463–1491
Vulnerability Type: Unrestricted privileged tool selection
Risk Level: High

Vulnerable Code

python
def _run_command(command: str, tool_name: str | None = None) -> dict[str, Any]:
    session = _session_with_registration(
        state_dir=Path.home() / ".beatra",
        post_json=_default_post_json,
    )
    if command == "tools":
        return session.request(2, "tools/list", {})
    try:
        arguments = json.load(os.sys.stdin)
    except json.JSONDecodeError as exc:
        raise RuntimeError("Tool arguments on stdin must be one JSON object") from exc
    if not isinstance(arguments, dict):
        raise RuntimeError("Tool arguments on stdin must be one JSON object")
    assert tool_name is not None
    return session.request(
        2,
        "tools/call",
        {"name": tool_name, "arguments": arguments},
    )


def main() -> int:
    parser = argparse.ArgumentParser(description="Call Beatra through Streamable HTTP")
    subparsers = parser.add_subparsers(dest="command", required=True)
    subparsers.add_parser("verify", help="Run the non-billable connection check")
    subparsers.add_parser("tools", help="List available Beatra tools")
    call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin")
    call.add_argument("tool_name")

Technical Analysis

The client accepts an arbitrary tool_name from the command line and forwards it through an authenticated tools/call request. No local allowlist verifies that the requested operation belongs to the declared homeroom speech workflow.

Stdin must contain a JSON object, but there is no package-specific argument validation or distinction between read-only and billable operations. The unrestricted dispatcher is dangerous because the authorization token includes broad MCP, generation, wallet, arti ...[truncated 1204 chars]

Remediation
View remediation

Remediation Suggestions

  • Enforce a static package-specific allowlist of permitted MCP tools.
  • Limit the allowlist to the speech, model, voice, upload, package-owned task, and explicitly documented wallet-read operations required by this Skill.
  • Reject unknown tool names before creating an authenticated session.
  • Validate each permitted operation against a local argument schema.
  • Separate read-only commands from billable or state-changing commands.
  • Require explicit user confirmation immediately before billable generation, cloning, upload, cancellation, or wallet-spending operations.
  • Use a server-side package policy so bypassing the local client still cannot access unrelated capabilities.

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/mcp_client.py:969
Finding

Silent Automatic Updates Can Replace Executable Skill Code Without Fresh Consent

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/mcp_client.py, lines 516–523
  • scripts/mcp_client.py, lines 969–1017
  • scripts/mcp_client.py, lines 1542–1544
  • SKILL.md, lines 180–200
  • references/automatic-updates-and-safety.md, lines 3–19

Vulnerability Type: Remote executable payload replacement
Risk Level: High

Vulnerable Code

Default-on update state:

python
def _read_update_state(update_home: Path) -> dict[str, Any]:
    path = update_home / "state.json"
    try:
        value = json.loads(path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return {"schema_version": 1, "auto_update": True}
    if not isinstance(value, dict) or value.get("schema_version") != 1:
        return {"schema_version": 1, "auto_update": True}
    return value

Silent update implementation:

python
def maybe_auto_update(
    *,
    state_dir: Path | None = None,
    install_root: Path | None = None,
    get_bytes: GetBytes = _default_get_bytes,
    now: float | None = None,
) -> bool:
    """Best-effort silent update. Never block the requested MCP command."""

    resolved_state = state_dir or Path.home() / ".beatra"
    try:
        resolved_root = (install_root or _current_install_root()).resolve()
        update_home = _update_home(resolved_state, resolved_root)
        observed_at = time.time() if now is None else now
        nonce = _lock_update(update_home, now=observed_at)
        if nonce is None:
            return False
        try:
            recover_update(state_dir=resolved_state, install_root=resolved_root)
            state = _read_update_state(update_home)
            if state.get("auto_update", True) is False:
                return False
            last_checked = state.get("last_checked_at")
            if (
                isinstance(last_checked, (int, float))
                and observed_at - 
...[truncated 3554 chars]
Remediation
View remediation

Remediation Suggestions

  • Disable automatic installation by default.
  • Permit automatic update checks, but require informed user confirmation before replacing executable files.
  • Verify discovery documents and release manifests with a detached digital signature using a pinned release public key.
  • Keep release-signing keys separate from CDN and web publication credentials.
  • Display the current version, target version, changed files, and executable changes before installation.
  • Support a mode that downloads and verifies an update without applying it.
  • Preserve the existing path, archive, size, ownership, rollback, and downgrade protections.
  • Consider requiring an additional confirmation whenever authorization or credential-handling code changes.

other

Warning
Location
scripts/authorize.py:340
Finding

Authorization Collects and Transmits Hostname and Agent Environment Telemetry

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/authorize.py, lines 340–369
  • scripts/authorize.py, lines 454–466
  • scripts/mcp_client.py, lines 1149–1167
  • scripts/mcp_client.py, lines 1220–1229
  • scripts/mcp_client.py, lines 1369–1378

Vulnerability Type: Environment reconnaissance and device-linking telemetry
Risk Level: Medium

Vulnerable Code

Agent-platform detection:

python
def detect_host_platform(explicit: str | None = None) -> str:
    """The agent environment this process runs inside (docs/device-model.md).

    Order: explicit agent self-report > environment signatures > unknown.
    Detection reads the process environment only — nothing else runs,
    nothing reaches the network.
    """
    if explicit:
        candidate = explicit.strip().lower().replace(" ", "-")
        if _PLATFORM_VALUE.fullmatch(candidate):
            return candidate
    env = os.environ
    if env.get("CLAUDECODE") == "1" or "CLAUDE_CODE_ENTRYPOINT" in env:
        return "claude-code"
    if any(key.startswith("CODEX_") for key in env):
        return "codex"
    ai_agent = env.get("AI_AGENT", "").lower()
    matched = re.match(r"([a-z0-9-]+)_", ai_agent)
    if matched and _PLATFORM_VALUE.fullmatch(matched.group(1)):
        return matched.group(1)
    return "unknown"

Hostname collection:

python
def device_display_name() -> str | None:
    """A hostname the user will recognise in the console device list."""
    try:
        name = socket.gethostname().strip()
    except OSError:
        return None
    if not name or not name.isprintable():
        return None
    return name[:120]

Transmission during authorization:

python
form: dict[str, str] = {
    "client_id": CLIENT_ID,
    "resource": MCP_URL,
    "scope": SCOPE,
    "platform": host_platform,
    "client_name": PACKAGE_DISPLAY_NAME,
    "external_installation_
...[truncated 3037 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not collect or transmit the hostname by default.
  • Replace the hostname with a random, user-editable device label.
  • Make platform and installation telemetry opt-in rather than mandatory.
  • Display every metadata field that will be transmitted before authorization.
  • Provide a documented flag that disables hostname, platform, registration, and per-call source attribution.
  • Rotate or scope installation identifiers where long-term cross-package correlation is unnecessary.
  • Apply retention limits and access controls to server-side device metadata.
  • Continue avoiding broader reconnaissance such as IP, interface, process, or full-environment enumeration.
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
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill documentation references uninstall/disconnect behavior that reads and modifies local installation files, checks installed package inventory, revokes authorization over the network, and removes credentials/state. Including privileged lifecycle-management actions inside a classroom voice skill expands its authority beyond user expectations and creates opportunities for destructive or privacy-impacting side effects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill documentation references uninstall/disconnect behavior that reads and modifies local installation files, checks installed package inventory, revokes authorization over the network, and removes credentials/state. Including privileged lifecycle-management actions inside a classroom voice skill expands its authority beyond user expectations and creates opportunities for destructive or privacy-impacting side effects.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill documentation references uninstall/disconnect behavior that reads and modifies local installation files, checks installed package inventory, revokes authorization over the network, and removes credentials/state. Including privileged lifecycle-management actions inside a classroom voice skill expands its authority beyond user expectations and creates opportunities for destructive or privacy-impacting side effects.

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
(`scripts/mcp_client.py` / `beatra.assets.upload`). Keep the returned

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
92% confidence
Finding

The public description presents the skill solely as converting week plans into voice clips, but the manifest changelog indicates inclusion of ledger and balance operations. That discrepancy is a strong indicator of scope deception or poor security hygiene, increasing the risk that users grant credentials to a skill whose real capabilities exceed its stated educational/audio purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest changelog explicitly mentions adding read-only balance and ledger calls, which are unrelated to a homeroom voice-pack generation skill. This capability mismatch is dangerous because it can mislead users into authorizing a skill that appears educational/audio-focused while also enabling access to financial or account metadata through the connected MCP service.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
76% confidence
Finding

The skill is configured to use a device-bearer credential file from the user's home directory, which means execution of this skill can access existing authenticated MCP credentials. In the context of a simple voice-pack skill—especially one already showing balance/ledger scope mismatch—this raises the risk of unauthorized use of account-linked capabilities or abuse of stored tokens beyond the user’s expectations.

Content

Scanner excerpt · manifest.json (reported line 53)May include surrounding context.

json
},
  "mcp": {
    "authentication": "device-bearer",
    "credential_file": "~/.beatra/credentials.json",
    "name": "beatra",
    "transport": "streamable-http",
    "url": "https://mcp.beatra.ai/mcp"

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 · references/installation-and-auth.md (reported line 14)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

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 · references/installation-and-auth.md (reported line 21)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

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 · references/installation-and-auth.md (reported line 49)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

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 · references/mcp-connection.md (reported line 10)May include surrounding context.

text

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

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

python
```

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

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

python
```

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

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

python
```

They share the one full-scope Device Token stored in
`~/.beatra/credentials.json`. Installing or switching packages must not trigger
another authorization when that credential is already valid. Do not add,
enable, trust, or configure a host Beatra Connector. Never print or move the
token into command arguments, environment variables, logs, chat, or another

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The OAuth scope requests include wallet spending, task control, artifact read/write, image/video/music generation, and voice management, which substantially exceed the skill’s stated purpose of producing homeroom week voice clips. Overbroad authorization violates least privilege and increases blast radius if the skill, host, or stored token is abused or compromised.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The authorization flow actively provisions a shared credential with capabilities far beyond a homeroom voice-pack workflow, then stores that bearer token for reuse. In context, a school-oriented voice skill does not justify broad access to spending, multimedia generation, task cancellation, or voice administration, so any misuse could affect data, billing, and account resources well outside the intended feature set.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The client implements broad capabilities unrelated to the advertised voice-pack purpose: package self-update, installation registration, environment fingerprinting, and local inventory tracking. In skill context, this is dangerous because a content-generation tool gains persistent code-replacement and telemetry behaviors that expand the trust boundary far beyond what a user would reasonably expect.

Content

No source excerpt is available for this finding.

Self-Modification

High
Category
Rogue Agent
Confidence
94% confidence
Finding

The exposed self-update capability allows the skill package to modify its own installed code. In the context of a classroom voice-generation skill, self-modification is especially risky because it creates a path for behavior changes after installation, undermining user review and increasing the blast radius if the upstream distribution channel is ever compromised.

Content

Scanner excerpt · scripts/mcp_client.py (reported line 1503)May include surrounding context.

python
)
    update = subparsers.add_parser(
        "update",
        help="Check, install, or configure Beatra package self-updates",
    )
    update.add_argument(
        "--check",