Back to skill

Security audit

Database Operations

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent database helper, but its sample audit trigger can copy password hashes into audit logs and some database-changing examples need stronger production safeguards.

Review this skill before installing if you expect agents to generate production database code. Do not copy the audit trigger as written for tables containing password hashes, tokens, secrets, MFA data, or personal data; use explicit allowlists or field exclusions. Treat migration and EF update commands as templates only after confirming the target environment, backups, generated SQL, staging results, and rollback plan.

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
SKILL.md:84
Finding

Audit Trigger Stores Current and Historical Password Hashes

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 57 and 84-115
Vulnerability Type: Sensitive data exposure through unrestricted audit logging
Risk Level: Medium

The user schema contains a sensitive authentication field:

sql
password_hash VARCHAR(255) NOT NULL,

The audit implementation stores complete row representations for every insert, update, and delete:

sql
CREATE TABLE audit_log (
  id BIGSERIAL PRIMARY KEY,
  table_name VARCHAR(255) NOT NULL,
  record_id BIGINT NOT NULL,
  operation audit_operation NOT NULL,
  old_values JSONB,
  new_values JSONB,
  changed_fields TEXT[],
  user_id BIGINT REFERENCES users(id),
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_audit_table_record ON audit_log(table_name, record_id);
CREATE INDEX idx_audit_user_time ON audit_log(user_id, created_at);

-- Trigger function
CREATE OR REPLACE FUNCTION audit_trigger_function()
RETURNS TRIGGER AS $$
BEGIN
  IF TG_OP = 'DELETE' THEN
    INSERT INTO audit_log (table_name, record_id, operation, old_values)
    VALUES (TG_TABLE_NAME, OLD.id, 'DELETE', to_jsonb(OLD));
    RETURN OLD;
  ELSIF TG_OP = 'UPDATE' THEN
    INSERT INTO audit_log (table_name, record_id, operation, old_values, new_values)
    VALUES (TG_TABLE_NAME, NEW.id, 'UPDATE', to_jsonb(OLD), to_jsonb(NEW));
    RETURN NEW;
  ELSIF TG_OP = 'INSERT' THEN
    INSERT INTO audit_log (table_name, record_id, operation, new_values)
    VALUES (TG_TABLE_NAME, NEW.id, 'INSERT', to_jsonb(NEW));
    RETURN NEW;
  END IF;
END;
$$ LANGUAGE plpgsql;

-- Apply to any table
CREATE TRIGGER audit_users
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW EXECUTE FUNCTION audit_trigger_function();

Technical Analysis

The generic trigger converts entire users rows to JSONB using to_jsonb(OLD) and to_jsonb(NEW). Because those rows include password_hash, the audit table receiv ...[truncated 2013 chars]

Remediation
View remediation

Remediation Suggestions

  1. Exclude sensitive fields before writing row data to the audit table:

    sql
    to_jsonb(NEW) - 'password_hash'
    to_jsonb(OLD) - 'password_hash'
    
  2. Prefer an explicit allowlist of auditable columns rather than serializing complete rows. This prevents newly added secrets, tokens, recovery codes, or personal data from silently entering the audit log.

  3. Use table-specific audit policies where schemas contain authentication or other sensitive data. A generic trigger should accept a reviewed exclusion list or construct sanitized JSONB.

  4. Revoke direct SELECT access to audit_log from ordinary application, reporting, and support roles. Provide restricted views that expose only fields necessary for legitimate audit workflows.

  5. Establish retention and secure-deletion policies for audit records and ensure those policies cover backups, replicas, exports, and analytics destinations.

  6. Remove existing password hashes from stored audit data. For example, after taking appropriate operational precautions:

    sql
    UPDATE audit_log
    SET
      old_values = old_values - 'password_hash',
      new_values = new_values - 'password_hash'
    WHERE table_name = 'users';
    
  7. Review whether exposed hashes require forced password resets. Prioritize privileged users and verify that the application uses a modern password-hashing algorithm with appropriate work factors and unique salts.

  8. Add automated tests asserting that prohibited fields such as password_hash, password-reset tokens, MFA secrets, and session tokens never appear in audit JSON.

Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list is overly broad and includes generic terms like 'database', 'schema', 'SQL', and 'index', which can cause the skill to activate in contexts far beyond its intended scope. Over-triggering can route unrelated user requests into a high-authority database operations skill, increasing the chance of unsafe schema, migration, or production-impacting guidance being surfaced inappropriately.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
84% confidence
Finding

Using EXPLAIN as a trigger term can collide with a common built-in command or generic assistant intent such as 'explain this', causing shadow activation of this database skill when the user did not intend database analysis. That misrouting is more dangerous here because the skill provides operational database and migration guidance that could influence high-impact actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The migration section includes a destructive step (ALTER TABLE users DROP COLUMN name;) in a zero-downtime rename example without an explicit warning about irrecoverable data loss, dependency breakage, or the need for staged verification before removal. Users may copy the sequence mechanically and execute the final drop before application code, backups, replicas, or downstream consumers are fully migrated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The EF Core section shows dotnet ef database update as a direct apply command, including production-script generation, but does not explicitly warn users to review generated SQL, validate backups, confirm target environment, and test rollback before execution. In a database-operations skill, omission of those safety guardrails can lead to accidental production schema changes, outages, or data loss.

Content

No source excerpt is available for this finding.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

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

md
2. ❌ Missing indexes on foreign keys — always index FK columns
3. ❌ `LIKE '%search%'` — use full-text search or trigram indexes instead
4. ❌ Large `IN` clauses — use `ANY(ARRAY[...])` or join a values list
5. ❌ No `LIMIT` on unbounded queries — always paginate
6. ❌ Creating indexes without `CONCURRENTLY` in production
7. ❌ Running migrations without testing rollback
8. ❌ Ignoring `EXPLAIN ANALYZE` output — always verify execution plans

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The example forces the text search configuration to english in both indexing and querying. This bakes in a language assumption without offering locale selection or documenting that the example is intentionally English-specific, which can conflict with language/locale policy expectations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.