T09 · Insecure Skill Coding Practices
- Location
SKILL.md:138- Finding
State-Changing MCP Operations Lack an Enforced Authorization Gate
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:138-149; corroborated byreferences/agent-guardrails.md:23-27andreferences/cli-reference.md:87-94
Vulnerability Type: Missing authorization and confirmation enforcement for destructive operations
Risk Level: HighRelevant snippets:
SKILL.md:138-149:text The skill delivers reads and writes and records them; it does **not** decide whether a write is permitted. That is your agent's judgement, or the permission of the account you connect it with (connect with a PostgreSQL role that has no write privileges (a read-only role, or one without INSERT/UPDATE/DELETE/DDL) — writes then fail at the server). There is no read-only switch, policy file, or approval gate. - **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.postgres-aiops/audit.db` (relocatable via `POSTGRES_AIOPS_HOME`): params, result, status, duration, and the risk tier. The CLI writes the same row the MCP path does. - `POSTGRES_AUDIT_APPROVED_BY` / `POSTGRES_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block. - **Runaway guard** — a safety backstop, not authorization: the same call looped in a tight window trips a circuit breaker. Disable with `POSTGRES_RUNAWAY_MAX=0`. - Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI.references/agent-guardrails.md:23-27:text **Authorization is not this tool's job.** Whether a write is permitted is decided by the account you connect it with (connect with a PostgreSQL role that has no write privileges — a read-only role, or one without INSERT/UPDATE/DELETE/DDL — and the write fails at the server) or by your agent's prompt. `POSTGRES_AUDIT_APPROVED_BY` / `POSTGRES_AUDIT_RATIONALE` are optional annotations recorded on the audit row; they are never required and never block a call....[truncated 3036 chars]
- Remediation
View remediation
Remediation Suggestions
- Default all MCP write operations to dry-run and reject execution unless a separate, explicit approval step has completed.
- Generate a short-lived, single-use approval token from the preview step. Bind it cryptographically to the target, operation, parameters, database identity, and requesting user.
- Require stronger approval for high-risk or irreversible operations such as backend termination, query cancellation, full vacuum, reindexing, and statistics reset.
- Add a code-enforced read-only mode and make it the default for new installations.
- Enforce authorization inside the MCP execution path rather than relying solely on an agent prompt or database-role permissions.
- Validate that the approving identity is authorized for the exact target and operation; do not treat optional audit annotations as approval.
- Preserve audit logging and least-privilege database roles as defense-in-depth, but do not use them as substitutes for pre-execution authorization.
