Back to skill

Security audit

Variant Annotation

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate research variant-annotation skill, but it needs review because it can transmit sensitive genetic inputs externally and has a medical-classification flaw when population data is missing.

Use this only for research or education, not diagnosis or treatment. Before installing, review whether variant identifiers or batch files are sensitive, assume queries go to NCBI, avoid passing valuable API keys on the command line, and treat ACMG output as provisional until the missing-frequency scoring bug and dependency issue are fixed.

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

Warning
Location
scripts/main.py:154
Finding
NCBI API Key Embedded and Repeated in Request URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:154-168` **Vulnerability Type**: API credential exposure through URL query parameters and unbounded recursive retries **Risk Level**: Medium ### Vulnerable Code ```python if self.api_key: url = f"{url}&api_key={self.api_key}" if "?" in url else f"{url}?api_key={self.api_key}" try: req = urllib.request.Request( url, headers={ "User-Agent": "VariantAnnotator/1.0 (academic research)", "Accept": "application/json" } ) with urllib.request.urlopen(req, timeout=30) as response: return json.loads(response.read().decode('utf-8')) except urllib.error.HTTPError as e: if e.code == 429: time.sleep(1) return self._ncbi_request(url) ``` ### Technical Analysis The NCBI API key is appended directly to the URL query string. HTTPS protects the request in transit, but full URLs are commonly retained by proxies, network-monitoring products, debugging tools, exception telemetry, and application logs. Any such retention may expose the credential. The HTTP 429 retry path recursively passes the already modified URL back to `_ncbi_request()`. Because that method appends the API key on every invocation, repeated rate-limit responses produce a URL containing the credential multiple times. The retry has no maximum attempt count, so a sustained 429 response can also cause excessive recursion and eventual process failure. Network access to `eutils.ncbi.nlm.nih.gov` is necessary for the declared live ClinVar and dbSNP functionality. The problem is therefore not the network request itself, but avoidable credential handling and unbounded retry behavior. ### Attack Path 1. A user invokes the Skill with `--api-key`. 2. The key is appended to every NCBI request URL. 3. A proxy, monitoring service, debugger, or URL-level telemetry system records the full request URL. 4. An actor with access to those records obtains the API key and ...[truncated 694 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer an NCBI-supported authentication mechanism that does not place credentials in URLs, if available. - If NCBI requires the API key as a query parameter, construct the request from immutable base parameters and add the key exactly once. - Ensure URLs are redacted before being logged, included in exceptions, or sent to telemetry. - Never include the API key in user-visible error messages. - Replace recursive retries with a bounded iterative retry loop. - Use exponential backoff with jitter and honor the `Retry-After` response header. - Set a maximum retry count and return a controlled error when it is exceeded. - Consider accepting the key through a protected environment variable or secret manager rather than a command-line argument, since command-line values may be visible in process listings. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unnecessary and Unpinned Third-Party Dependency<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1` **Vulnerability Type**: Unpinned package installation and unnecessary supply-chain exposure **Risk Level**: Low ### Vulnerable Code ```text dataclasses ``` The documented installation command in `SKILL.md` is: ```bash pip install -r requirements.txt ``` ### Technical Analysis The dependency has no exact version or integrity hash. Consequently, installation resolves whichever package release the configured package index serves at that time, making builds non-reproducible and allowing future package changes to enter the environment without code review. `dataclasses` has been part of the Python standard library since Python 3.7. The Skill does not declare Python 3.6 as a supported runtime or otherwise demonstrate that the backport is required. Installing this package on modern Python versions therefore expands the supply-chain attack surface without supporting the Skill's minimum necessary functionality. No evidence was found that the current package is malicious. The confirmed issue is unnecessary, mutable third-party code acquisition. ### Attack Path 1. A user follows the documented prerequisite and runs `pip install -r requirements.txt`. 2. Pip resolves `dataclasses` from the configured package index or an organization-controlled mirror. 3. A compromised package release, compromised mirror, or unsafe future update is selected because no version or hash is enforced. 4. Package installation or later import executes code that was not part of the audited Skill artifact. ### Impact Assessment The package installer normally runs with the invoking user's privileges. A compromised dependency could therefore read or modify files accessible to that user, access available environment variables and credentials, or execute network requests. The audited artifact does not itself demonstrate such exploitation. The present risk is avoidable supply-chain exposure, with impact dependent on the ...[truncated 46 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `dataclasses` from `requirements.txt` when supporting Python 3.7 or later. - Declare the minimum supported Python version explicitly, preferably through project metadata. - If Python 3.6 support is genuinely required, condition the dependency on the interpreter version. - Pin the backport to a reviewed version and use cryptographic hashes. - Install dependencies with hash enforcement, such as `pip install --require-hashes`. - Generate and review a locked dependency file as part of release auditing. - Avoid installing project dependencies with elevated operating-system privileges. ]]>

other

Error
Location
scripts/main.py:274
Finding
Missing Population Frequency Data Is Misclassified as ACMG PM2 Evidence<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:274-283` **Vulnerability Type**: Medical classification integrity failure caused by unsafe missing-data handling **Risk Level**: High ### Vulnerable Code ```python max_freq = 0.0 for pop, freq in allele_freqs.items(): if freq and freq > max_freq: max_freq = freq if max_freq < 0.0001: criteria.append("PM2") score += self.ACMG_SCORES["PM2"] evidence["PM2"] = f"Absent from population databases (max MAF: {max_freq:.2e})" elif max_freq > 0.05: criteria.append("BA1") score += self.ACMG_SCORES["BA1"] evidence["BA1"] = f"Common variant (MAF: {max_freq:.3f} > 5%)" elif max_freq > 0.01: criteria.append("BS1") score += self.ACMG_SCORES["BS1"] evidence["BS1"] = f"Allele frequency greater than expected ({max_freq:.3f})" ``` ### Technical Analysis `max_freq` is initialized to zero. If all supplied population frequency values are `None`, the loop never changes it. The code then interprets this synthetic zero as an observed maximum frequency below `0.0001` and awards ACMG criterion PM2. Missing data and an observed allele frequency of zero are materially different states. The resulting evidence summary falsely states that the variant is absent from population databases even when no usable population observation was obtained. The implementation only attempts limited dbSNP frequency extraction and does not query the gnomAD or ExAC sources advertised in `SKILL.md`. Nevertheless, the scoring input includes an unpopulated gnomAD field. This makes the unsafe missing-data path likely for variants without a successfully parsed dbSNP frequency. ### Attack Path 1. A user submits a variant for which no usable population frequency is returned or parsed. 2. The frequency fields passed to `_calculate_acmg_score()` are all `None`. 3. `max_freq` remains at its initialized value of `0.0`. 4. The code awards PM2 and adds two pathogenicity points. 5. The output incorrect ...[truncated 815 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Represent missing frequency data explicitly rather than initializing the maximum to zero. - Track whether at least one valid frequency observation was obtained before evaluating PM2, BA1, or BS1. - Apply PM2 only after successful queries against appropriate population databases and after validating coverage, ancestry, genome build, and variant normalization. - Return evidence such as `population_frequency_status: "unknown"` when no reliable value is available. - Do not state that a variant is absent from databases unless that absence was affirmatively established. - Implement the gnomAD or other population-data integrations claimed by the documentation, or remove those claims. - Validate parsed frequency values as finite numbers in the range zero through one. - Add tests covering all-`None` frequencies, explicit zero observations, malformed values, partial database failures, and conflicting frequencies. - Clearly separate imported ClinVar classifications from independently calculated ACMG assessments. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
Findings (9)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises network and file read/write behavior but does not declare any explicit tool scope or permissions boundary. In an agent environment, this creates ambiguity about what resources the skill may access and increases the risk of unintended file access, data exfiltration, or broader tool invocation than reviewers and orchestrators expect.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The trigger text is broad enough to activate on general discussions of pathogenicity or clinical significance, not just concrete variant-annotation tasks. Over-broad activation can cause the skill to process unintended user content, invoke networked lookups unnecessarily, and return medical-style interpretations in contexts where the user did not ask for this specialized workflow.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- **PM3**: For recessive disorders, detected in trans with a pathogenic variant
- **PM4**: Protein length changes as a result of in-frame deletions/insertions in a nonrepeat region or stop-loss variants
- **PM5**: Novel missense change at an amino acid residue where a different missense change determined to be pathogenic has been seen before
- **PM6**: Assumed de novo, but without confirmation of paternity and maternity

### Supporting Pathogenic (PP)
- **PP1**: Cosegregation with disease in multiple affected family members in a gene definitively known to cause the disease
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- **PM3**: For recessive disorders, detected in trans with a pathogenic variant
- **PM4**: Protein length changes as a result of in-frame deletions/insertions in a nonrepeat region or stop-loss variants
- **PM5**: Novel missense change at an amino acid residue where a different missense change determined to be pathogenic has been seen before
- **PM6**: Assumed de novo, but without confirmation of paternity and maternity

### Supporting Pathogenic (PP)
- **PP1**: Cosegregation with disease in multiple affected family members in a gene definitively known to cause the disease
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This file contains concrete genetic variant examples with asserted pathogenic/benign interpretations and expected outputs, but it does not state that the content is for testing/reference only and not for clinical, diagnostic, or medical decision-making. In a variant-annotation skill, users or downstream agents could mistakenly treat these examples as authoritative medical guidance, creating a risk of unsafe health interpretation or overconfident automation.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The code sends user-supplied variant identifiers and an optional NCBI API key to external NCBI endpoints without any explicit consent flow, warning, or data-handling notice. In this skill’s context, variant queries can reveal highly sensitive genetic and health-related information, so silent transmission creates a real privacy and compliance risk even if the destination is a legitimate biomedical service.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The tool ingests variant lists from local files and then processes them for annotation without warning that the file contents may contain sensitive genetic data. Because this skill is specifically designed to analyze clinical significance and pathogenicity, users may unknowingly submit regulated or personally sensitive genomic information for external lookup, increasing privacy, confidentiality, and compliance exposure.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The line 'AI自主验收状态: 需人工检查' introduces Chinese-language content in the skill documentation without offering a language choice or explaining a locale-specific requirement. This can violate language/locale policy expectations for user-facing skill materials.

Unpinned Dependencies

Low
Category
Supply Chain
Content
dataclasses
Confidence
60% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Static analysis

No suspicious patterns detected.