Back to skill

Security audit

Agent Ontology

Security checks for vulnerabilities and agentic risk

Overview

This is a purposeful local memory skill, but it needs Review because persistent graph writes are broadly scoped and the promised validation and secret protections are not actually enforced.

Install only if you are comfortable with a persistent local memory file. Avoid storing passwords, API keys, tokens, private messages, or regulated personal data in it until schema validation, secret-field rejection, file permission hardening, and deletion/update controls are implemented.

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:28
Finding
Missing Schema Enforcement Allows Plaintext Credential Storage and Invalid Graph Records<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ontology.py:28-40`, `scripts/ontology.py:143-156`, and `scripts/ontology.py:243-245` **Vulnerability Type**: Missing input validation and plaintext sensitive-data storage **Risk Level**: Medium ### Vulnerable Code Entity properties are persisted without schema or credential-safety validation: ```python def create_entity(entity_type, properties): ensure_dirs() entity_id = generate_id(entity_type) entity = { "id": entity_id, "type": entity_type, "properties": properties, "created": datetime.utcnow().isoformat() + "Z", "updated": datetime.utcnow().isoformat() + "Z" } record = {"op": "create", "entity": entity} with open(GRAPH_FILE, 'a') as f: f.write(json.dumps(record) + "\n") return entity ``` The CLI accepts arbitrary JSON properties and passes them directly to the storage function: ```python if cmd == "create": entity_type, props = None, {} i = 2 while i < len(sys.argv): if sys.argv[i] == "--type" and i + 1 < len(sys.argv): entity_type = sys.argv[i + 1]; i += 2 elif sys.argv[i] == "--props" and i + 1 < len(sys.argv): props = json.loads(sys.argv[i + 1]); i += 2 else: i += 1 if not entity_type: print("Error: --type is required"); sys.exit(1) result = create_entity(entity_type, props) ``` The validation command does not inspect any stored data or load the declared schema: ```python elif cmd == "validate": ensure_dirs() print("✅ Validation passed") ``` This conflicts with the declared credential rules in `references/schema.md:125-131`: ```yaml Credential: required: [service, secret_ref] 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[]? ``` ### Technical Analysis Th ...[truncated 3476 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Load an authoritative machine-readable schema before accepting any write. The existing Markdown reference should be converted into or backed by a real schema file. 2. Allow only explicitly defined entity types and properties. Reject unknown types rather than assigning them a generic identifier prefix. 3. Validate all required properties, data types, enum values, date formats, URLs, and reference values before persistence. 4. For `Credential` entities, reject direct secret-bearing fields such as `password`, `secret`, `token`, `key`, and `api_key`, including an agreed case-normalization policy. 5. Require `secret_ref` to point to an approved secret-management mechanism. Never persist the corresponding secret value in the graph. 6. Validate relations before writing them: - Confirm that both endpoint entities exist. - Enforce allowed source and destination types. - Enforce cardinality rules. - Reject unsupported relation names. - Perform graph traversal to prevent cycles in relations marked as acyclic. 7. Replace the unconditional `validate` response with a complete scan of stored entities and relations. Print actionable validation errors and return a nonzero status when any violation is found. 8. Create the storage directory and graph file with least-privilege permissions, such as directory mode `0700` and file mode `0600`, without relying solely on the process umask. 9. Add tests proving that forbidden credential fields, missing required fields, invalid enums, nonexistent relation endpoints, and dependency cycles are rejected. 10. Review existing `graph.jsonl` records for secrets. Remove exposed values safely and rotate any credentials that may already have been persisted. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

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.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The activation examples are very broad conversational phrases such as "Remember that..." and "What do I know about X?", which can overlap with normal user dialogue and cause the skill to activate unexpectedly. In a skill that performs knowledge-graph writes and updates, over-broad triggering increases the chance of unintended persistence, incorrect graph mutations, or disclosure of stored information when the user did not explicitly intend to use this capability.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill explicitly stores information in a persistent append-only graph file but does not warn users that their inputs may be retained. This creates a privacy and data-governance risk because users may disclose personal, sensitive, or contextual information under the assumption it is ephemeral, and append-only storage also makes later deletion or correction harder.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The module docstring states this CLI provides 'CRUD operations on typed knowledge graph,' which implies create, read, update, and delete support. In the actual code, commands only implement create/read-style operations and relationship creation; there are no update or delete commands or corresponding code paths.

Static analysis

No suspicious patterns detected.