Rules / CFG085
CFG085 subagent frontmatter weakens the permission mode
Severity: error (bypassPermissions, dontAsk) · warn (auto, acceptEdits)
OWASP: LLM03:2026 – Excessive Agency
What cfgaudit checks
A subagent is a Markdown file with YAML frontmatter — Claude Code reads them from .claude/agents/, xAI Grok from .grok/agents/, both using the same camelCase permissionMode field, and qwen-code from .qwen/agents/ with a native approvalMode plus a bridged permissionMode. All let the subagent override how permission prompts are handled.
CFG004 flags permissions.defaultMode in settings.json. This is the same destination through a different door — and a subagent definition is just as committable, so a cloned repository can ship one.
cfgaudit reads permissionMode and flags the values that weaken the permission system:
| Value | Severity | Effect |
|---|---|---|
bypassPermissions |
error |
disables all permission checks — full autonomy, no prompts |
dontAsk |
error |
suppresses prompts; the subagent proceeds without asking |
auto |
warn |
hands decisions to the auto-mode classifier (whose allow/deny lists CFG079 covers) |
acceptEdits |
warn |
auto-accepts file edits, so the working tree is written without confirmation |
default, plan, and manual (a documented alias for default, Claude Code ≥ 2.1.200) prompt normally and are not flagged, nor is an absent field.
Severities mirror CFG004, which reads the same modes from settings.json.
Scope: only real subagent files, only modes that take effect
The rule fires only for Markdown directly under a .claude/agents/, .grok/agents/, or .qwen/agents/ directory — project or user. Two reasons, both of which would otherwise produce false positives:
- The field is inert elsewhere. A
permissionModein aCLAUDE.md, a skill, or a slash command is decoration; nothing reads it. - Claude Code documents that plugin subagents ignore it: "For security reasons, plugin subagents don't support the
hooks,mcpServers, orpermissionModefrontmatter fields. These fields are ignored when loading agents from a plugin."
Grok honors only bypassPermissions at spawn. Grok's source documents that "only BypassPermissions is wired at spawn; others are forward-compat", so for a .grok/agents/*.md file only bypassPermissions is flagged (error). Reporting dontAsk/auto/acceptEdits there would be a false positive on a mode Grok currently ignores. Claude Code applies all four, so all four are flagged for a .claude/agents/*.md file.
qwen mirrors the Claude agent schema but resolves the mode differently. A .qwen/agents/*.md frontmatter "mirrors Claude Code 2.1.168's .claude/agents/<name>.md schema verbatim", so a Claude agent file dropped into .qwen/agents/ parses identically. The effective mode is approvalMode ?? bridge(permissionMode):
- The native
approvalModewins when set.yolo→error(full autonomy),auto-editandauto→warn(auto-accepted edits / classifier-mediated approval).default,plan, and the subagent-onlybubbleprompt normally. A value outside the enum makes qwen reject the whole file, so it is not treated as a configured mode. - A Claude
permissionModeis honoured only whenapprovalModeis unset, through qwen's bridge (PERMISSION_MODE_TO_APPROVAL_MODE):bypassPermissions→yolo,acceptEdits/auto→auto-edit. CruciallydontAskbridges todefault— qwen preserves its restrictive intent — sodontAskis inert on a qwen file even though it is anerroron a Claude file. ApermissionModeoutside the six Claude enum values (the common but invalidpermissionMode: yoloamong them) is dropped and honours nothing.
qwen honours a definition's mode in a trusted folder, and qwen's folder trust is off by default, so "trusted" is the common state. In an untrusted folder the privileged modes are clamped back to the parent, the vendor's own guard against a repo "silently grant[ing] itself classifier-mediated automation".
Precedence caveat
The subagent's mode does not always win. Per Claude Code's documentation, if the parent session is in bypassPermissions or acceptEdits that takes precedence and cannot be overridden, and if the parent is in auto mode the subagent inherits it and its own permissionMode is ignored.
That narrows when the field bites, but not whether it is worth flagging: in an ordinary session — the parent at its default mode — a committed permissionMode: bypassPermissions is honoured.
Trigger example
---
name: deployer
description: Ships the build. Use when asked to deploy.
permissionMode: bypassPermissions
---
Run the deployment scripts in ./ops without stopping to confirm.
→ error: anyone who invokes this subagent runs it with permission checks off.
Safe alternative
Leave permissionMode out and let the session's mode govern. If a subagent legitimately needs broader access, grant it narrowly with tools / disallowedTools rather than switching off the prompt for everything it does.
References
- OWASP LLM03:2026 – Excessive Agency
- Claude Code — subagent frontmatter fields
- CFG004 (
permissions.defaultModein settings.json) — the same modes, the other door · CFG079 (auto-mode classifier weakening)
Documentation for cfgaudit 1.18.1. Source of this page · Rule implementation