Back to skill

Security audit

Security Hardener

Security checks for vulnerabilities and agentic risk

Overview

This security-audit skill is mostly coherent, but one documented test can delete a real banking ledger record despite claiming the audit is read-only.

Review before installing or using this skill. Do not run the kill-switch test against production or any database with real ledger data; require a test environment, a dedicated fixture, and rollback-only validation. The rest of the audit commands are mostly local/read-only checks, but Rails runner access should still be treated as sensitive because it uses the app's database permissions.

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

Error
Location
SKILL.md:148
Finding

Destructive Kill-Switch Test Can Delete a Production Ledger Record

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 148–160
Vulnerability Type: Unsafe destructive operation and misleading exception handling
Risk Level: High

Vulnerable Code

bash
### Kill Switch Test

Verify that the kill switch mechanism works (Gebud 10 — Test What You Fear):

```bash
# Check that Decision#destroy raises
cd ZK_BANKIR_PATH
bin/rails runner "
  begin
    Decision.last.destroy
    puts '❌ KILL SWITCH FAILED: destroy allowed'
  rescue => e
    puts '✅ Kill switch active: destroy blocked'
  end
" 2>&1
text

### Technical Analysis

The test calls `destroy` on the last persisted `Decision` record in the database. If deletion protection is absent or defective—the exact condition this procedure is intended to detect—the operation succeeds and permanently deletes a real ledger record.

This behavior contradicts the Skill's claim that its audits are “read-only by default” and “never modify” data. Because the command does not require an isolated test environment or wrap the operation in a transaction that is guaranteed to roll back, following the documented audit workflow against a production deployment can alter production state.

The broad `rescue => e` introduces an additional correctness problem. Any `StandardError`, rather than only the specific exception expected from the deletion guard, is reported as evidence that the kill switch is active. For example, if the table has no records, `Decision.last` returns `nil`, and calling `destroy` raises an unrelated `NoMethodError`; the script then incorrectly reports that deletion was blocked. Database connectivity, callback, or application errors could produce similar false-positive results.

### Attack Path

1. An operator follows the documented “Full Security Audit” procedure against a running ZK-Bankir deployment.
2. The Rails runner connects to the deployment's configured database.
3. The kill-switch test retrieves the most recent persisted decision through `Decision.last`
...[truncated 1038 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not invoke destroy on an existing record in a production or operator-selected database.
  2. Move the behavioral test to an isolated test database and create a dedicated fixture solely for this check.
  3. If an in-process check is unavoidable, use a transaction that is unconditionally rolled back, while accounting for callbacks or integrations that may cause external side effects:
ruby
expected_error = Decision::DestroyForbidden

Decision.transaction(requires_new: true) do
  record = Decision.create!(required_fixture_attributes)

  begin
    record.destroy!
    abort "KILL SWITCH FAILED: destroy was allowed"
  rescue expected_error
    puts "Kill switch active: destroy blocked"
  ensure
    raise ActiveRecord::Rollback
  end
end
  1. Prefer a non-destructive unit or integration test that directly verifies the deletion guard, callback, policy, and expected exception.
  2. Rescue only the specific exception raised by the intended protection. Treat all other exceptions as test errors rather than successful security enforcement.
  3. Explicitly fail when no suitable test record exists.
  4. Require an explicit test-environment check before running any destructive security validation, such as aborting unless Rails.env.test?.
  5. Update the documentation's “read-only” claim or, preferably, redesign the procedure so that the claim is accurate.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill claims to be read-only, yet the kill-switch test invokes Decision.last.destroy, which is a state-changing destructive action even if it is expected to fail. In a security-hardening skill, undocumented mutation is especially dangerous because operators may run it in production under the assumption that it is safe, and any misconfiguration or bypass of the protection could delete real ledger data.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
Policy.where(active: true).each do |p|
    puts \"Policy ##{p.id}: #{p.name}\"
    puts \"  Rules: #{p.rules}\"
    puts \"  Auto-approve: <\$#{p.rules['approval_threshold']}\"
    puts \"  Hard-deny: >\$#{p.rules['max_trade_size']}\"
  end
" 2>&1

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
Policy.where(active: true).each do |p|
    puts \"Policy ##{p.id}: #{p.name}\"
    puts \"  Rules: #{p.rules}\"
    puts \"  Auto-approve: <\$#{p.rules['approval_threshold']}\"
    puts \"  Hard-deny: >\$#{p.rules['max_trade_size']}\"
  end
" 2>&1

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The kill-switch test is presented as a verification step without clearly warning that it attempts to delete a real record. Even though the intended outcome is an exception, documenting a destructive operation without prominent warning increases the chance of accidental execution against production data and normalizes unsafe testing practices.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The Incident Response section instructs users to 'list all recent decisions, flag anomalies' as part of the skill's workflow. Elsewhere, the file implements hash-chain checks, endpoint probes, policy inspection, and a destroy test, but no command actually retrieves recent decisions or performs anomaly review, so the documented intent overstates what the skill does.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.