Back to skill

Security audit

PharmaClaw Pharmacology Agent

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its pharmacology purpose, but it can transmit molecule structures externally and loads an undeclared sibling dashboard module during execution, so users should review it carefully before installing.

Install only if you are comfortable with SMILES being sent to ADMETlab and, when present, to a local dashboard hook. For confidential drug-discovery work, require an explicit network opt-in, remove or pin the sibling lab_hook import, and run the skill in a sandbox with limited filesystem and network access.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (1)

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/chain_entry.py:9
Finding

Untrusted Sibling-Directory Module Loading Enables Tool Hijacking

Content
View full analysis

Vulnerability Details

File Location: scripts/chain_entry.py, lines 9–14; invocation sites at lines 231–232, 250, and 268
Vulnerability Type: Untrusted Python import-path manipulation
Risk Level: Medium

Vulnerable Code

python
# === PharmaLab Dashboard Hook ===
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'pharmaclaw-lab-ui', 'scripts'))
try:
    from lab_hook import lab_update
except ImportError:
    def lab_update(*a, **kw): pass

The imported function is subsequently called with user-derived molecular data:

python
lab_update("pharmacology", "analyzing", f"ADME profiling {canonical_smiles[:40]}...",
           smiles=canonical_smiles)
python
lab_update("pharmacology", "idle", "ADME profile complete")
python
lab_update("pharmacology", "error", f"Failed: {str(e)[:60]}")

Technical Analysis

The script prepends an external sibling directory to sys.path, giving that location priority during Python module resolution. It then imports lab_hook, which is not included in the audited project and therefore cannot be authenticated or reviewed as part of this Skill.

An attacker with write access to ../../pharmaclaw-lab-ui/scripts/ can create or replace lab_hook.py. Python executes module-level code immediately during import, before the Skill processes its main workload. Catching ImportError does not mitigate this issue because a planted module imports successfully.

The imported lab_update function also receives canonicalized SMILES values and error details. A malicious replacement can capture this information, alter application behavior, perform network communication, or execute arbitrary actions available to the current process.

Attack Path

  1. The attacker obtains write access to the external pharmaclaw-lab-ui/scripts sibling directory.
  2. The attacker creates or replaces lab_hook.py with malicious module-level code or a malicious lab_update functi ...[truncated 1072 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the dashboard hook and sys.path mutation if the integration is not essential.
  2. Package lab_hook as a reviewed, version-pinned dependency and import it through the normal package mechanism.
  3. Do not add mutable external directories to the beginning of sys.path.
  4. If local loading is unavoidable, resolve the module from a fixed trusted path, verify its integrity against a pinned cryptographic hash or signature, and reject unexpected ownership or writable permissions.
  5. Run the Skill with a dedicated least-privileged account in a sandbox that restricts filesystem access, environment secrets, and outbound networking.
  6. Require explicit configuration or opt-in before sending molecular inputs to dashboard integrations.
  7. Avoid passing full canonicalized SMILES or detailed errors unless necessary; minimize or redact data supplied to the hook.
  8. Add a startup assertion or automated test confirming that lab_hook.__file__ resolves only to the approved package location.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior expands beyond the declared ADME/pharmacology scope into toxicity prediction and related structural alerting, while also claiming PAINS behavior that may not actually exist. This mismatch undermines informed consent, policy enforcement, and downstream trust because other agents or users may rely on an incomplete or inaccurate understanding of what the skill does and what data or outputs it produces.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documents use of an external ADMETlab 3.0 API and therefore implies network access, but the manifest does not declare any tool scope or permission boundary. That creates an undeclared outbound-data path where user-supplied molecular structures may be transmitted off-platform without explicit approval or policy review.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger terms are very broad and likely to activate during ordinary scientific discussion, causing the skill to run when the user did not intend it. In combination with possible network/API use and expanded toxicity capabilities, over-triggering increases the risk of unconsented data processing and unnecessary exposure of sensitive research inputs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation broadens the skill from pharmacology profiling into toxicity assessment, which is a meaningful scope expansion in a scientific decision-support context. Even if not overtly malicious, hidden expansion increases the chance of unauthorized use, unexpected downstream automation, and misuse of safety-sensitive predictions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill does not warn users that submitted molecular structures may be sent to an external ADMETlab 3.0 API. In a drug-discovery context, SMILES strings can represent proprietary compounds, so undisclosed external transmission creates confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest describes an agent for ADME/PK profiling, drug-likeness, QED/SA score, and specific ADME endpoints, but this file explicitly queries and computes broader toxicity endpoints such as hERG, Ames, DILI, carcinogenicity, respiratory toxicity, and eye irritation. Toxicology is related but materially broader than the stated manifest scope, so the implemented behavior exceeds the described purpose.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This outbound POST request transmits chemical structure data to an external domain. In this skill context, that is more sensitive than generic telemetry because medicinal chemistry inputs can be commercially valuable; sending them off-box without clear notice or control creates a real confidentiality risk even though the transport uses HTTPS.

Content

Scanner excerpt · scripts/admetlab3.py (reported line 100)May include surrounding context.

python
try:
        # ADMETlab 3.0 accepts SMILES via POST
        payload = {"smiles": smiles}
        resp = requests.post(
            f"{ADMETLAB_URL}/alogps",
            json=payload,
            timeout=TIMEOUT,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script sends user-supplied SMILES to a third-party external service without any explicit user-facing disclosure or opt-in. In a drug-discovery context, SMILES may encode proprietary or pre-publication compounds, so silent transmission can leak sensitive intellectual property or confidential research data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest says the skill computes PAINS alerts, but this file never performs PAINS substructure screening or returns PAINS-related output. The only alert logic present is for nitro groups and aromatic amines under mutagenicity heuristics, which is not equivalent to PAINS filtering.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill modifies sys.path to import a dashboard hook from a sibling project and then invokes that hook during execution, creating undeclared side effects outside the stated pharmacology analysis function. This expands the trust boundary: local code from another repository path can be loaded and executed, and analysis activity is silently reported externally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code sends the canonical SMILES string to lab_update during analysis without any consent, disclosure, or data-minimization controls. In this domain, chemical structures may be proprietary drug candidates, so transmitting them to a dashboard or external hook can leak sensitive IP and research data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest presents the skill as a SMILES-based pharmacology profiler and mentions chaining from chemistry-query, but does not disclose any dependency on or use of an external ADMETlab 3.0 service. The overview states that the skill combines ADMETlab 3.0 ML predictions 'when available,' which is a meaningful operational behavior not described in the manifest-level contract.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The main entry documentation for scripts/chain_entry.py defines input as a JSON object with a 'smiles' field only. The error-handling section then states the agent will request 'smiles' or 'name', which contradicts the stated interface and suggests support for a name-based mode that is not part of the documented contract here.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest scopes this skill to pharmacology/ADME/PK profiling, but the output includes a hard-coded recommendation to route users to "ip-expansion". Intellectual-property workflow steering is not part of the stated pharmacology purpose and introduces a capability outside the declared context.

Content

No source excerpt is available for this finding.