Back to skill

Security audit

dnasp

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent offline DNA population-genetics tool that writes local reports and reproducibility files, with no evidence of hidden network use, persistence, or unrelated authority.

Install only if you are comfortable with the tool storing local copies of your supplied DNA/VCF and metadata files under the output directory's reproducibility folder. Use a private output location for sensitive genetic data and delete or restrict that bundle when sharing results.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an analytical bioinformatics skill for running population genetics methods on DNA/VCF inputs. However, the provided code chunk is not analysis code; it is test infrastructure for ensuring the skill metadata matches the command-line interface and that version strings are synchronized across files. This is a materially different primary purpose from the declared behavior. While such tests may support the overall skill package, the supplied code chunk itself does not implement the declared analytical functionality.

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · dnasp.py (reported line 5473)May include surrounding context.

python
─────────────────────────────────────────
# Demo data
# ─────────────────────────────────────────────────────────────────────────────

DEMO_FASTA = """\
>pop1_seq1
TTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGTTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGTTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGTTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGGCTGGTACTGTTTTTAAAGAATCT
>pop1_seq2
TTTTATCATGATAATAAAGAACAATGTATTATCATAGCCGGTCCTACTGTTTTGCTTTCTCGTATGTGGTTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGTTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGTTTTATCATGATAATAAAGAACAATGTATTATCATAGCTGGTCCTACTGTTTTGCTTTCTCGTATGTGGGCTGGTACTGTT

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The function writes a shell script containing a command string and marks it executable. If the command content is influenced by untrusted input, this creates a ready-to-run artifact that can propagate unsafe shell syntax or harmful commands, increasing the chance of later command execution by a user or automation.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The reproducibility routine copies original input files, secondary inputs, population files, HKA files, and VCFs into an output-side reproducibility bundle automatically. In a genomics skill, those inputs may contain highly sensitive human genetic data or identifiers, so silently duplicating them increases exposure, retention, and accidental exfiltration risk beyond the user's apparent intent.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · tests/test_coalescent_pvalues.py (reported line 480)May include surrounding context.

python
"--analysis", "polymorphism,fufs", "--n-sim", "50", "--sim-seed", "3",
                      "--output", str(out)])
    assert rc == 0
    ct = __import__("json").loads((out / "summary.json").read_text())["coalescent"]
    report = (out / "report.md").read_text()
    section = report[report.index("## Coalescent simulation"):]
    assert "Replicates <= observed" in section and "Replicates >= observed" in section

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code creates a reproducibility directory and writes files to disk via mkdir, write_bytes, and later helper calls, but it provides no visible prompt, log, or print to disclose these filesystem modifications to the user. Because these are side-effecting file operations and this file contains no user-facing warning mechanism, it meets the missing-warning criterion for code files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

write_result_json serializes run metadata and data into result.json, which is a file write that may affect user data handling expectations. This file includes no prompt, print, or other user-facing notice explaining that structured results will be persisted to disk.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · dnasp.py (reported line 4270)May include surrounding context.

python
"""
    def serialise(value):
        if is_dataclass(value):
            return {f.name: serialise(getattr(value, f.name)) for f in fields(value)
                    if f.name not in {'pairs', 'incompatible_pairs'}}
        if isinstance(value, dict):
            return {json.dumps(k) if isinstance(k, tuple) else str(k): serialise(v)

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · tests/test_historical_comparisons.py (reported line 64)May include surrounding context.

python
'Tajima D': 'TajimaD', "Tajima's D": 'TajimaD', 'Fu & Li D*': 'FuLiD_star',
        'Fu & Li D* (no outgroup)': 'FuLiD_star', 'Fu & Li F*': 'FuLiF_star',
        'Fu & Li F* (no outgroup)': 'FuLiF_star', 'R2': 'R2', 'Ramos-Onsins & Rozas R2': 'R2'}
    if label in direct: return getattr(rs, direct[label])
    if 'θ_W' in label: return rs.ThetaW_nuc
    if label.startswith('ZnS'): return r['ld'].ZnS
    if label in {'ZA', 'ZZ'}: return getattr(r['ld'], 'Za' if label == 'ZA' else 'ZZ')

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · tests/test_historical_comparisons.py (reported line 67)May include surrounding context.

python
if label in direct: return getattr(rs, direct[label])
    if 'θ_W' in label: return rs.ThetaW_nuc
    if label.startswith('ZnS'): return r['ld'].ZnS
    if label in {'ZA', 'ZZ'}: return getattr(r['ld'], 'Za' if label == 'ZA' else 'ZZ')
    if label.startswith('Rm'): return r['recombination'].Rm
    if label.startswith('Raggedness'): return r['popsize'].raggedness
    if label == 'Mismatch: mean': return r['popsize'].mean

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · tests/test_historical_comparisons.py (reported line 94)May include surrounding context.

python
if label.startswith('MK '):
        field = next((x for x in ('Pn', 'Ps', 'Dn', 'Ds') if f' {x} ' in label), None)
        if field is None: field = 'NI' if 'Neutrality' in label else 'alpha' if 'α' in label else 'fisher_p'
        return getattr(r['mk'], field)
    if label == 'Ka (dN)': return r['kaks'].Ka
    if label == 'Ks (dS)': return r['kaks'].Ks
    if label == 'ω = Ka/Ks': return r['kaks'].omega