Back to skill

Security audit

Ontology 1

Security checks for vulnerabilities and agentic risk

Overview

This is a local ontology memory tool, but its persistent writes can store invalid or sensitive data despite claiming pre-write validation.

Review before installing. Use it only in workspaces where persistent shared memory under memory/ontology is acceptable, do not store secrets or tokens in the graph, and consider limiting invocation to explicit ontology read/write requests until mutations enforce validation before writing.

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:111
Finding
Graph Mutations Bypass Pre-Commit Schema Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ontology.py:111-128`, `scripts/ontology.py:144-159`, `scripts/ontology.py:178-191`, and `scripts/ontology.py:511-542` **Vulnerability Type**: Missing pre-commit validation permitting invalid or sensitive data to be persisted **Risk Level**: Medium ### Vulnerable Code ```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 ``` ```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] ``` ```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 = { "op": "relate", "from": from_id, "rel": rel_type, "to": to_id, "properties": properties, "timestamp": timestamp } append_op(graph_path, record) return record ``` The command dispatcher invokes these mutation functions directly: ```python if args.command == ...[truncated 4508 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Validate every proposed mutation before writing** - Load the applicable schema inside each mutation workflow. - Apply the proposed operation to an in-memory copy of the current graph. - Run all relevant entity and relation constraints against the proposed state. - Append the operation only if validation succeeds. 2. **Reject forbidden sensitive properties at the mutation boundary** - For constrained types such as `Credential`, reject forbidden property names during both creation and update. - Consider recursively checking nested objects for sensitive fields. - Return a nonzero exit status without echoing sensitive values. 3. **Validate relations before creation** - Require both endpoint entities to exist. - Enforce `from_types` and `to_types`. - Enforce cardinality constraints. - Test whether adding an acyclic relation would introduce a cycle before committing it. 4. **Make writes atomic** - Validate first and then append under an appropriate file lock. - Prevent a concurrent writer from changing the graph between validation and commit. - Flush and synchronize critical writes where durability is required. 5. **Provide safe handling for existing invalid data** - Add a repair or quarantine command that can remove or redact invalid records. - Do not rely on append-only deletion to protect secrets already present in historical JSONL records, because deleted values remain in earlier log entries. - Document and implement secure graph compaction or secret-redaction procedures. 6. **Add regression tests** - Verify that credentials containing forbidden fields never reach disk. - Verify rejection of missing required properties and invalid enum values. - Verify rejection of dangling, type-invalid, cardinality-violating, and cyclic relations. - Verify that failed validation leaves the graph byte-for-byte unchanged. ]]>
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 (13)

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/ontology.py create --type Person --props '{"name":"Alice","email":"alice@example.com"}'
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
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[]?
```
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill clearly instructs the agent to create and modify persistent workspace files under memory/ontology, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where a caller may invoke a state-mutating skill without an upfront, machine-readable restriction on file-write capability, increasing the chance of unintended or over-broad writes.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are very broad, including common language like 'remember' and 'what do I know about', which can cause the skill to activate in contexts the user did not intend. Because this skill performs persistent graph writes and cross-skill shared-state access, accidental invocation can lead to unwanted storage, linkage, or propagation of sensitive or incorrect data.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The skill documentation does not prominently warn at the outset that it writes persistent workspace data, even though later sections describe creating directories and appending to graph.jsonl. Users or orchestrators may treat it like a read/query utility and inadvertently cause lasting local state changes, which is especially relevant for memory-like skills handling person, account, device, and document metadata.

Static analysis

No suspicious patterns detected.