Back to skill

Security audit

Schema Builder

Security checks for vulnerabilities and agentic risk

Overview

This database schema skill is mostly purpose-related, but it includes under-disclosed generators that can produce unsafe SQL and hardcoded administrator seed credentials.

Review this skill before installing. It does not show exfiltration or system compromise behavior, but its richer schema generator is under-disclosed and can emit SQL or seed data that should not be executed against staging or production databases without validation and manual review.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/schema.sh:160
Finding
SQL Injection Through Unsanitized Table Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/schema.sh:160-168`, `scripts/schema.sh:181-203`, and `scripts/schema.sh:240-246` **Vulnerability Type**: SQL injection in generated schema, migration, and seed statements **Risk Level**: High ### Vulnerable Code ```python sql = tables.get(name, """CREATE TABLE IF NOT EXISTS {name} ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, description TEXT NULL, status VARCHAR(20) DEFAULT 'active', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;""".format(name=name)) ``` ```python print("""-- Migration: create_{name}_table -- Timestamp: {ts} -- ========== UP ========== CREATE TABLE IF NOT EXISTS {name} ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, description TEXT NULL, status VARCHAR(20) DEFAULT 'active', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO migrations (name, batch) VALUES ('create_{name}_table', 1); -- ========== DOWN ========== -- DROP TABLE IF EXISTS {name}; -- DELETE FROM migrations WHERE name = 'create_{name}_table';""".format(name=name, ts=ts)) ``` ```python sql = seeds.get(name, """INSERT INTO {name} (name, description, status) VALUES ('Sample 1', 'First sample record', 'active'), ('Sample 2', 'Second sample record', 'active'), ('Sample 3', 'Third sample record', 'inactive'), ('Sample 4', 'Fourth sample record', 'active'), ('Sample 5', 'Fifth sample record', 'archived');""".format(name=name)) ``` ### Technical Analysis The value assigned to `name` originates from the command-line argument passed through `$ARG`. For unknown template names, it is interpolated directly into SQL identifiers and, in the m ...[truncated 2097 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate every user-provided SQL identifier before generating output: ```python import re IDENTIFIER = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") if not IDENTIFIER.fullmatch(name): raise SystemExit("Invalid table name") ``` 2. Apply the same validation to table, column, index, schema, and migration identifiers wherever they can be supplied externally. 3. After validation, quote identifiers using the target database's supported quoting mechanism. Do not treat quoting as a substitute for the allowlist. 4. Do not interpolate identifiers into SQL string values. Use database parameter binding when the output will be executed programmatically. 5. If the tool only supports a fixed set of schemas, replace the fallback interpolation behavior with an explicit allowlist and reject unknown table names. 6. Add automated negative tests covering semicolons, quotes, whitespace, comments, backticks, control characters, Unicode confusables, and SQL keywords. 7. Ensure generated migrations are reviewed before execution and run under a least-privileged database account that cannot access unrelated schemas. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/schema.sh:208
Finding
Predictable Unsalted Password Hashes in Generated Seed Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/schema.sh:208-221` **Vulnerability Type**: Insecure password hashing and hardcoded test credentials **Risk Level**: Medium ### Vulnerable Code ```python seeds = { "users": """INSERT INTO users (username, email, password_hash, role, is_active) VALUES ('alice', 'alice@example.com', '{h1}', 'admin', TRUE), ('bob', 'bob@example.com', '{h2}', 'user', TRUE), ('charlie', 'charlie@example.com', '{h3}', 'user', TRUE), ('diana', 'diana@example.com', '{h4}', 'moderator', TRUE), ('eve', 'eve@example.com', '{h5}', 'user', FALSE);""".format( h1=hashlib.sha256(b"password123").hexdigest()[:60], h2=hashlib.sha256(b"password456").hexdigest()[:60], h3=hashlib.sha256(b"password789").hexdigest()[:60], h4=hashlib.sha256(b"password000").hexdigest()[:60], h5=hashlib.sha256(b"password111").hexdigest()[:60] ), ``` ### Technical Analysis The user seed generator creates fixed accounts from publicly visible passwords. It hashes those passwords with a single, unsalted SHA-256 operation and truncates each hexadecimal digest to 60 characters. SHA-256 is designed for speed and is unsuitable as a password-storage algorithm. It provides no configurable work factor or memory hardness, and the lack of a unique salt allows precomputation and immediate recognition of identical passwords. In this case, cracking is unnecessary because the plaintext passwords are embedded directly in the source. The seeded `alice` account receives the `admin` role and the known password `password123`. Although the generated output includes a development/testing warning, the code does not technically prevent import into shared, staging, or production databases. Whether direct login succeeds depends on the consuming application's authentication implementation and whether it accepts this hash representation. The insecure credentials nevertheless become exploitable whenev ...[truncated 1216 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not ship fixed passwords for seeded accounts, especially accounts assigned administrator or moderator roles. 2. Generate cryptographically random, one-time development credentials at seed time and display them only through an appropriate protected channel. 3. Use the consuming application's normal password-hashing implementation rather than implementing hashing in the schema generator. Approved choices include Argon2id, scrypt, or bcrypt with an appropriate cost parameter and a unique random salt per password. 4. Avoid truncating password hashes. Store the complete encoded output, including algorithm, version, work factor, salt, and digest. 5. Make authentication seed generation an explicit opt-in operation separate from ordinary sample-data generation. 6. Add deployment safeguards that reject test users and known development email addresses outside isolated development environments. 7. Prefer disabled accounts or records without usable credentials when sample users are needed only to exercise database relationships. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description partially matches the code: it does build database schemas, generate SQL, and show relationship models/ER diagrams. However, the implementation materially extends beyond that purpose. It also generates migration scripts, seed data, optimization advice, NoSQL schemas, and a schema comparison helper. These are substantive extra capabilities rather than minor implementation details. There is no evidence of unrelated external access or hidden side effects; the mismatch is due to undeclared functionality breadth rather than malicious behavior.

Session Persistence

Medium
Category
Rogue Agent
Content
### `create`

```bash
scripts/script.sh create <table cols>
```

### `alter`
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The manifest describes this skill as building database schemas with SQL generation and relationship modeling, which implies SQL-oriented schema design. The `nosql` command expands the skill into MongoDB document-schema generation, a materially different capability not reflected in the manifest description.

Whitespace Padding

Medium
Category
Prompt Injection
Content
DATA_DIR="$HOME/.local/share/schema-builder"
mkdir -p "$DATA_DIR"

#
#
#
#
Confidence
80% confidence
Finding
Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Static analysis

No suspicious patterns detected.