Back to skill

Security audit

digital-baseline-messenger

Security checks for vulnerabilities and agentic risk

Overview

This messaging skill is mostly coherent, but it needs Review because it stores private chat data locally and can pass account API keys through configurable external service code.

Install only if you trust the Digital Baseline service and the unresolved digital_baseline_skill dependency. Treat the local database as containing private conversations and contacts, avoid running it from shared or repository directories, and be especially cautious with merge_agents because it requires a source account API key and may send it through the configured service endpoint.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
digital_baseline_messenger.py:296
Finding

Reusable account API key crosses an endpoint-configurable, unaudited network boundary

Content
View full analysis

Vulnerability Details

File Location: digital_baseline_messenger.py:296-313 and digital_baseline_messenger.py:611-613
Vulnerability Type: Sensitive credential exposure through unsafe trust boundaries
Risk Level: High

Relevant Code

python
def __init__(
    self,
    base_url: Optional[str] = None,
    api_key: Optional[str] = None,
    agent_did: Optional[str] = None,
    db_path: str = DEFAULT_DB_PATH,
    **kwargs,
):
    skill_kwargs: Dict[str, Any] = {}
    if base_url:
        skill_kwargs["base_url"] = base_url
    if api_key:
        skill_kwargs["api_key"] = api_key
    if agent_did:
        skill_kwargs["agent_did"] = agent_did
    skill_kwargs.update(kwargs)

    self.skill = DigitalBaselineSkill(**skill_kwargs)
    self.cache = MessageCache(db_path)
    self._my_did = self.skill.agent_did
python
def merge_agents(self, source_api_key: str) -> Dict:
    return self.skill.merge_agents(source_api_key)

Technical Analysis

The wrapper accepts a caller-controlled base_url and forwards it to DigitalBaselineSkill. It also passes a reusable source-account API key to that external dependency during account merging. The implementation of DigitalBaselineSkill is not included in the audited project, so this package cannot enforce or verify:

  • The destination to which the source API key is transmitted.
  • Whether HTTPS and certificate verification are mandatory.
  • Whether redirects can move the credential to another origin.
  • Whether the dependency logs, stores, or otherwise discloses the credential.
  • Whether the configured endpoint is the legitimate Digital Baseline service.

The behavior is particularly sensitive because SKILL.md describes merge_agents(did), while the implementation requires source_api_key. Users therefore may not understand that account merging crosses a reusable credential into a network dependency.

Network communi ...[truncated 1661 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace reusable API-key transfer with a short-lived, single-purpose merge token issued by the source account's trusted server.
  2. Bind the merge token to the destination account, operation, expected service origin, and a short expiration period.
  3. Restrict production API endpoints to an explicit HTTPS allowlist. If custom endpoints are needed for testing, require a separate, conspicuous development option.
  4. Reject plain HTTP URLs and enforce TLS certificate verification.
  5. Prevent authorization headers and credentials from being forwarded across redirects to another origin.
  6. Require explicit user confirmation before initiating an account merge and clearly identify the credential or authorization being transferred.
  7. Ensure credentials are never written to logs, exceptions, telemetry, local caches, or returned response objects.
  8. Correct SKILL.md so that the documented method signature and security implications match the implementation.
  9. Audit and pin the DigitalBaselineSkill implementation responsible for the actual network request.

T09 · Insecure Skill Coding Practices

Warning
Location
digital_baseline_messenger.py:62
Finding

Private messages and contact metadata are persisted in an unprotected plaintext SQLite database

Content
View full analysis

Vulnerability Details

File Location: digital_baseline_messenger.py:35 and digital_baseline_messenger.py:62-147
Vulnerability Type: Plaintext storage of sensitive communication data
Risk Level: Medium

Relevant Code

python
DEFAULT_DB_PATH = ".messenger_cache.db"
python
def _get_conn(self) -> sqlite3.Connection:
    if self._conn is None:
        self._conn = sqlite3.connect(self._db_path)
        self._conn.row_factory = sqlite3.Row
        self._conn.execute("PRAGMA journal_mode=WAL")
        self._conn.execute("PRAGMA foreign_keys=ON")
    return self._conn
python
conn.executescript("""
CREATE TABLE IF NOT EXISTS sessions (
    session_id   TEXT PRIMARY KEY,
    session_type TEXT NOT NULL DEFAULT 'dm',
    group_name   TEXT,
    other_did    TEXT,
    other_name   TEXT,
    last_message TEXT,
    last_msg_at  TEXT,
    unread_count INTEGER DEFAULT 0,
    total_msgs   INTEGER DEFAULT 0,
    synced_at    TEXT
);

CREATE TABLE IF NOT EXISTS messages (
    id           TEXT PRIMARY KEY,
    session_id   TEXT NOT NULL,
    sender_did   TEXT NOT NULL,
    message_type TEXT DEFAULT 'text',
    content      TEXT,
    sequence_num INTEGER,
    created_at   TEXT,
    synced_at    TEXT,
    FOREIGN KEY (session_id) REFERENCES sessions(session_id)
);
CREATE INDEX IF NOT EXISTS idx_msg_session_seq
    ON messages(session_id, sequence_num);
CREATE INDEX IF NOT EXISTS idx_msg_content
    ON messages(content);

CREATE TABLE IF NOT EXISTS contacts (
    contact_did  TEXT PRIMARY KEY,
    alias        TEXT,
    display_name TEXT,
    reputation   REAL,
    source       TEXT,
    synced_at    TEXT
);

CREATE TABLE IF NOT EXISTS sync_cursors (
    session_id TEXT PRIMARY KEY,
    last_seq   INTEGER DEFAULT 0
);
""")
conn.commit()

Technical Analysis

The Skill stores message bodies, recent-message previews, p ...[truncated 2271 chars]

Remediation
View remediation

Remediation Suggestions

  1. Store the cache under the platform-specific private application-data directory rather than the current working directory.
  2. Create the directory and database with owner-only permissions and verify permissions before opening an existing database.
  3. Apply equivalent protections to SQLite database, WAL, shared-memory, backup, and temporary files.
  4. Encrypt sensitive fields or use an encrypted database implementation, with keys obtained from an operating-system credential store rather than hardcoded or colocated with the database.
  5. Provide configurable retention periods and an option to disable message-body caching while retaining only synchronization metadata.
  6. Implement a documented cache purge function that removes the primary database and associated SQLite sidecar files.
  7. Add .messenger_cache.db, WAL files, shared-memory files, and backups to recommended ignore patterns.
  8. Warn users before enabling local persistence and document what data is retained.
  9. Avoid storing full message previews in the sessions table when they are not necessary.

T08 · Insecure Dependencies

Warning
Location
digital_baseline_messenger.py:42
Finding

Security-critical network functionality is delegated to an absent and unpinned dependency

Content
View full analysis

Vulnerability Details

File Location: digital_baseline_messenger.py:42-58 and SKILL.md:168-170
Vulnerability Type: Unpinned security-critical dependency and incomplete supply-chain controls
Risk Level: Medium

Relevant Code

python
try:
    from digital_baseline_skill import DigitalBaselineSkill
except ImportError:
    import importlib.util
    _here = Path(__file__).parent / "digital_baseline_skill.py"
    if _here.exists():
        _spec = importlib.util.spec_from_file_location(
            "digital_baseline_skill", str(_here)
        )
        _mod = importlib.util.module_from_spec(_spec)
        _spec.loader.exec_module(_mod)
        DigitalBaselineSkill = _mod.DigitalBaselineSkill
    else:
        raise ImportError(
            "digital_baseline_skill.py is required; place it in the same directory or install digital-baseline-skill"
        )

The dependency documentation specifies only minimum versions:

text
requests >= 2.20.0
websocket-client >= 0.57.0

Technical Analysis

Authentication and nearly all network operations are delegated to DigitalBaselineSkill, but its source is not present in the audited artifact and no exact version or integrity hash is specified. The code also dynamically loads a same-directory file named digital_baseline_skill.py when present.

Consequently, the reviewed package does not determine the effective security behavior of authentication, endpoint validation, TLS configuration, redirects, credential storage, or network transmission. Deployments may execute different dependency versions despite using the same audited Messenger source.

The same-directory fallback also creates a local module-substitution risk: anyone able to place or replace digital_baseline_skill.py in that directory can cause it to execute during import. This does not independently cross an existing filesystem permission boundary, but it broadens t ...[truncated 1582 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin exact dependency versions in a lockfile and verify package hashes during installation.
  2. Explicitly declare and pin the supported digital-baseline-skill package version.
  3. Audit the dependency implementation responsible for authentication, TLS, redirects, credential handling, and endpoint selection.
  4. Obtain packages only from a trusted registry and use provenance or signature verification where available.
  5. Remove the same-directory dynamic-loading fallback, or verify the local module against an expected cryptographic digest before loading it.
  6. Make the installation reproducible in continuous integration and run dependency vulnerability scanning.
  7. Execute the Skill under a dedicated, minimally privileged operating-system identity with restricted filesystem and network access.
  8. Keep credentials out of process-wide environment variables when a narrower credential-injection mechanism is available.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The documented purpose emphasizes messaging, but the API surface also includes subscription management, plan handling, identity anchor configuration, and agent identity merging, while the claimed WebSocket behavior may actually be polling. Hidden or under-described account, identity, and billing-related actions materially expand the trust boundary and can lead users to authorize a skill that can modify identities or trigger paid features they did not expect.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill documents clear network capabilities such as REST API use, WebSocket connectivity, contact sync, and offline message retrieval, but does not declare any tool scope or allowed-tools restrictions. This creates a permission-transparency gap: an agent operator may enable the skill without realizing it can initiate outbound network communication and persistent syncing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill promotes local SQLite message caching but does not warn users that message contents may persist on disk across sessions. In a messaging context, local persistence can expose sensitive conversations, contact metadata, and identifiers to other local users, malware, backups, or forensic recovery if not explicitly disclosed and secured.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill advertises automatic contact sync, offline message retrieval, and real-time push behavior, but does not clearly warn that messages and contact data may be transmitted automatically over the network and kept in sync in the background. In a communications skill, undisclosed automatic transmission can leak sensitive content or metadata and may violate operator expectations about when outbound network activity occurs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill persistently stores message contents, contacts, and metadata in a local SQLite database by default, but the top-level description does not clearly warn about local retention or discuss sensitivity. In a messaging context, cached conversations and contact data can contain private or regulated information, so silent storage increases confidentiality risk on shared hosts, developer machines, or compromised environments.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill metadata and description position this as a messaging SDK, but the code also exposes subscription purchase/verification and account merge operations. That scope expansion is security-relevant because it enables financial actions and identity/account linkage that a caller may not expect from a messaging component, increasing the chance of misuse through over-privileged integration or deceptive packaging.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The polling feature continuously calls remote sync operations and downloads message/contact data in the background, but its documentation only describes functionality and logging behavior. It does not clearly warn users that enabling polling results in recurring network access and local storage of newly retrieved messages.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The module docstring, method comments, and CLI usage/help text are written in Chinese only, with no option for alternate language output. This imposes a specific language/locale on users rather than offering a choice or documenting that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The top-level documentation states the SDK adds complete communication abilities and the quick-start example suggests background real-time reception, while the actual implementation uses a polling thread that sleeps and calls sync repeatedly. This is an active documentation-to-code mismatch rather than a mere omission because the advertised delivery mechanism differs materially from the implemented one.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

Both the manifest and module header advertise WebSocket realtime push as part of the SDK's complete communication capability. In this file, realtime behavior is implemented by background polling via start_polling/_poll_loop and repeated sync calls, with no WebSocket setup or event stream handling present.

Content

No source excerpt is available for this finding.