Back to skill

Security audit

Ontology

Security checks for vulnerabilities and agentic risk

Overview

This skill is not overtly malicious, but it needs review because it broadly persists agent memory and its code does not enforce the promised validation before saving data.

Install only if you want a shared persistent workspace memory graph. Avoid storing secrets or tokens in it, run validation after changes, and prefer explicit user confirmation before any create, update, delete, relate, or schema-append operation.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ontology.py:120
Finding

Graph Mutations Bypass Schema Validation Before Persistence

Content
View full analysis

Vulnerability Details

File Location: scripts/ontology.py:120-134, scripts/ontology.py:174-182, scripts/ontology.py:201-212, and scripts/ontology.py:250-279
Vulnerability Type: Missing pre-commit validation
Risk Level: Medium

The documented security contract states in SKILL.md:12:

text
Every mutation is validated against type constraints before committing.

However, entity creation directly appends an unvalidated operation:

python
def create_entity(type_name: str, properties: dict, graph_path: str, entity_id: str = None) -> dict:
    """Create a new entity."""
    entity_id = entity_id or generate_id(type_name)
    timestamp = datetime.now(timezone.utc).isoformat()
    
    entity = {
        "id": entity_id,
        "type": type_name,
        "properties": properties,
        "created": timestamp,
        "updated": timestamp
    }
    
    record = {"op": "create", "entity": entity, "timestamp": timestamp}
    append_op(graph_path, record)
    
    return entity

Updates are also committed without validating the resulting entity:

python
def update_entity(entity_id: str, properties: dict, graph_path: str) -> dict | None:
    """Update entity properties."""
    entities, _ = load_graph(graph_path)
    if entity_id not in entities:
        return None
    
    timestamp = datetime.now(timezone.utc).isoformat()
    record = {"op": "update", "id": entity_id, "properties": properties, "timestamp": timestamp}
    append_op(graph_path, record)
    
    entities[entity_id]["properties"].update(properties)
    entities[entity_id]["updated"] = timestamp
    return entities[entity_id]

Relations are likewise persisted without checking endpoint existence, allowed types, cardinality, or acyclicity:

python
def create_relation(from_id: str, rel_type: str, to_id: str, properties: dict, graph_path: str):
    """Create a relation between entities."""
    timestamp = datetime.now(timezone.utc).isoformat()
    record = {
      
...[truncated 4064 chars]
Remediation
View remediation

Remediation Suggestions

  1. Validate every proposed mutation before calling append_op():

    • For creation, validate the complete proposed entity against its type schema.
    • For updates, merge the proposed properties into a copy of the current entity and validate the resulting entity.
    • For relations, validate endpoint existence, endpoint types, cardinality, and acyclicity against the graph state that would result from the operation.
  2. Pass the schema path into mutation functions or introduce a graph-store class that owns both graph and schema configuration. Do not rely on callers to run a separate validation command.

  3. Reject forbidden secret-bearing properties before persistence. For Credential, explicitly deny password, secret, token, key, and api_key, and require a valid secret_ref.

  4. Ensure atomic behavior: validation must complete successfully before the append occurs. Return a nonzero CLI exit status and a clear error when a mutation violates the schema.

  5. Consider defensive secret-pattern checks in addition to property-name restrictions, because callers may place sensitive values under unexpected property names.

  6. Add regression tests covering:

    • Missing required fields.
    • Forbidden Credential fields.
    • Invalid enum values.
    • Relations with missing endpoints.
    • Disallowed relation endpoint types.
    • Cardinality violations.
    • Cyclic relations marked as acyclic.
    • Updates that turn a previously valid entity into an invalid one.
  7. Provide a remediation or compaction procedure for existing invalid records. Since the graph is append-only, merely appending an update does not erase a secret from historical storage; exposed secrets should be rotated and the graph securely rewritten where appropriate.

Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (12)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'

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/schema.md (reported line 165)May include surrounding context.

forbidden_properties: [password, secret, token, key, api_key] properties: service: string secret_ref: string # Reference to secret store (e.g., "keychain:github-token") expires: datetime? scope: string[]?

text

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill performs workspace file writes to memory/ontology/* and may create directories/files, but it declares no explicit tool scope or permissions boundary. In an agent system, this can enable unintended persistence or state modification if the skill is invoked implicitly or by a broad trigger, making its write capability harder to constrain and audit.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger phrases are broad and overlap with common user intents such as "remember," "what do I know about," and generic entity CRUD or cross-skill access. Because this skill can write persistent state, overly broad routing increases the chance it is activated for ordinary conversation, causing accidental data retention, unintended graph mutations, or inappropriate cross-skill data sharing.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.