feat(config): load safe mise.toml files without trust#10360
Conversation
Config files that only contain min_version and [tools] entries with plain version strings cannot execute code or change mise's behavior, so they no longer require trusting the file before parsing. Anything else — env vars, tasks, hooks, settings, aliases, templates, tool options like postinstall/install_env — still requires trust, as does everything in paranoid mode. Configs the user chose to ignore stay unloaded even when safe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughDefines a “safe config” TOML subset exempt from interactive trust checks, wires path-level trust decisions into config/include/task loading, adds decoded-template/header parsing checks, updates docs/help text, and adds unit and E2E tests for safe and unsafe cases. ChangesSafe config auto-loading without trust
Sequence Diagram (high-level config load & trust decision) sequenceDiagram
participant CLI as mise CLI
participant FromStr as MiseToml::from_str
participant IsExempt as MiseToml::is_trust_exempt
participant SafeBody as is_safe_config_body
participant Trust as trust_check
participant ConfigLoader as Config loader
participant IncludeChecker as task_include_requires_trust
participant TaskRunner as Task execution
CLI->>FromStr: request parse/load (path, body)
FromStr->>IsExempt: evaluate(body, path)
IsExempt->>SafeBody: scan for templates & allowed keys
IsExempt-->>FromStr: exempt? (bool)
FromStr->>Trust: run when not exempt
FromStr->>ConfigLoader: hand off parsed config
ConfigLoader->>IncludeChecker: decide include trust per-path
IncludeChecker->>Trust: run if include requires trust
ConfigLoader->>TaskRunner: execute/install tasks/tools (explicit commands)
🎯 4 (Complex) | ⏱️ ~45 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Greptile SummaryThis PR allows "safe"
Confidence Score: 5/5Safe to merge; the allowlist is conservative, the template bypass is closed at both the raw-text and decoded-TOML layers, and paranoid mode / ignored configs remain fully gated. The two-layer template check (raw scan + recursive decoded-TOML scan) correctly closes the Unicode-escape bypass. The No files require special attention. Important Files Changed
Reviews (5): Last reviewed commit: "test(task): exercise decoded #MISE heade..." | Re-trigger Greptile |
| if contains_template_syntax(body) { | ||
| return false; | ||
| } | ||
| let Ok(toml::Value::Table(table)) = toml::from_str::<toml::Value>(body) else { |
There was a problem hiding this comment.
TOML parsed twice per safe config load
is_safe_config_body calls toml::from_str::<toml::Value>(body) to validate the structure, and then from_str on MiseToml calls toml::Deserializer::parse(body) again immediately after. For the common case — the plain tools-only config this feature is optimised for — this doubles the parsing work on every load. Caching the parsed toml::Value or combining the safety check with the existing parse pass would avoid the redundant work, though the impact is small for typical config sizes.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
e2e/config/test_trust_safe_config (1)
30-33: 📐 Maintainability & Code Quality | ⚡ Quick winMake trust-required assertions specific to the canonical error text.
grep -qi "trust"is broad and can pass on unrelated output. Matching the canonical untrusted-config wording makes this E2E check much more reliable.Suggested assertion tightening
-echo "$output" | grep -qi "trust" || fail "expected trust error for template, got: $output" +echo "$output" | grep -q "are not trusted" || fail "expected trust error for template, got: $output" +echo "$output" | grep -q 'Trust them with `mise trust`' || fail "expected trust guidance for template, got: $output" -echo "$output" | grep -qi "trust" || fail "expected trust error for tool options, got: $output" +echo "$output" | grep -q "are not trusted" || fail "expected trust error for tool options, got: $output" +echo "$output" | grep -q 'Trust them with `mise trust`' || fail "expected trust guidance for tool options, got: $output" -echo "$output" | grep -qi "trust" || fail "expected trust error for env, got: $output" +echo "$output" | grep -q "are not trusted" || fail "expected trust error for env, got: $output" +echo "$output" | grep -q 'Trust them with `mise trust`' || fail "expected trust guidance for env, got: $output"Also applies to: 39-40, 47-48
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/config/test_trust_safe_config` around lines 30 - 33, The test uses a broad check echo "$output" | grep -qi "trust" which can match unrelated text; update the assertions that check the command output (the output variable produced by `output=$(MISE_YES=0 mise ls 2>&1 || true)` and the subsequent grep lines at the other occurrences) to match the canonical untrusted-config error string exactly (use the precise wording the CLI emits for "template requires trust" / "untrusted config" instead of just "trust") so the E2E assertions on lines around the `output` variable are specific and deterministic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mise.usage.kdl`:
- Around line 3507-3509: Update the "Safe config files" paragraph to state that
`[tools]` entries may be either plain version strings or arrays of plain version
strings (i.e., lists of simple version strings with no templates or tool
options) in addition to `min_version`; locate the paragraph referencing
"min_version and [tools] entries with plain version strings" and expand it to
explicitly allow arrays of plain strings so the wording matches the PR behavior
contract.
In `@src/config/config_file/mise_toml.rs`:
- Around line 1979-2001: The current is_safe_config_body only checks for Tera
template markers in the raw TOML body, allowing Unicode-escaped templates inside
tool version strings to bypass the check; update is_safe_config_body (the
function) so after parsing the toml::Value::Table it additionally iterates the
"tools" table values and for each string or array element decodes/inspects the
actual string values and runs contains_template_syntax on those decoded strings
(reject if any contains template syntax), and add a unit test in
test_is_safe_config_body that includes a tool entry like node = "\u007b\u007b
exec(command='echo 20') \u007d\u007d" to assert the function returns false.
---
Nitpick comments:
In `@e2e/config/test_trust_safe_config`:
- Around line 30-33: The test uses a broad check echo "$output" | grep -qi
"trust" which can match unrelated text; update the assertions that check the
command output (the output variable produced by `output=$(MISE_YES=0 mise ls
2>&1 || true)` and the subsequent grep lines at the other occurrences) to match
the canonical untrusted-config error string exactly (use the precise wording the
CLI emits for "template requires trust" / "untrusted config" instead of just
"trust") so the E2E assertions on lines around the `output` variable are
specific and deterministic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3f3640d4-9db9-4a3e-b24b-ce369c65187b
📒 Files selected for processing (6)
docs/cli/trust.mddocs/faq.mde2e/config/test_trust_safe_configmise.usage.kdlsrc/cli/trust.rssrc/config/config_file/mise_toml.rs
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.6.5 x -- echo |
24.9 ± 1.7 | 20.2 | 31.2 | 1.00 |
mise x -- echo |
26.3 ± 2.3 | 21.5 | 47.7 | 1.06 ± 0.12 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.6.5 env |
24.5 ± 1.7 | 20.6 | 30.2 | 1.05 ± 0.11 |
mise env |
23.4 ± 1.9 | 19.0 | 29.9 | 1.00 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.6.5 hook-env |
22.6 ± 1.6 | 19.2 | 29.8 | 1.00 |
mise hook-env |
24.0 ± 1.8 | 19.8 | 29.5 | 1.06 ± 0.11 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.6.5 ls |
19.7 ± 1.4 | 16.4 | 24.4 | 1.00 |
mise ls |
20.5 ± 1.7 | 16.2 | 25.6 | 1.04 ± 0.11 |
xtasks/test/perf
| Command | mise-2026.6.5 | mise | Variance |
|---|---|---|---|
| install (cached) | 156ms | 158ms | -1% |
| ls (cached) | 70ms | 71ms | -1% |
| bin-paths (cached) | 83ms | 78ms | +6% |
| task-ls (cached) | 153ms | 154ms | +0% |
Defining a task is inert — it only executes when the user explicitly runs it — so [tasks] no longer disqualifies a config from loading without trust. Template-free task include files (mise-tasks/ scripts and TOML task files) are likewise loadable untrusted, since templates are the only thing that can execute while tasks load. This also fixes a latent hole: task includes skipped their trust check whenever any config existed at the root, even one that loaded without being trusted (e.g. a plain .tool-versions), letting a templated task file render exec() at load time. Includes now require trust unless a config at the root was actually trusted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
e2e/tasks/test_task_monorepo_trust (1)
46-64: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUnset CI auto-trust before the new negative-path assertion.
This script now asserts an untrusted-config error, but
is_trusted()short-circuits to true in CI. Without the sameunset CI GITHUB_ACTIONS GITHUB_ACTIONsetup used in the other trust e2es, this case won't actually exercise the failure path on GitHub Actions.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/tasks/test_task_monorepo_trust` around lines 46 - 64, The test fails to exercise the untrusted path in CI because is_trusted() is short-circuited; before the negative-path assertion that checks for "are not trusted" (the assert_contains line) add the same CI auto-trust disabling used in other trust e2es: unset or clear CI, GITHUB_ACTIONS, and GITHUB_ACTION environment variables (in addition to setting MISE_TRUSTED_CONFIG_PATHS="") so is_trusted() will evaluate false and the trust error path is tested.
♻️ Duplicate comments (1)
src/config/config_file/mise_toml.rs (1)
1984-2005: 🔒 Security & Privacy | 🔴 Critical | ⚡ Quick winBase these trust checks on decoded TOML strings, not raw file text.
is_safe_config_bodyinsrc/config/config_file/mise_toml.rsandtask_include_requires_trustinsrc/config/mod.rsboth only scan the raw source, so unicode-escaped delimiters like\u007b\u007b exec(...) \u007d\u007dbypass the trust gate. After TOML parsing those become real Tera templates, and the later task/tool render paths can execute them. Parse the TOML first, re-check decoded string values, and add regressions for escaped-template root configs and task include files.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/config/config_file/mise_toml.rs` around lines 1984 - 2005, The current trust checks in is_safe_config_body (and similarly task_include_requires_trust) only scan the raw file text so unicode-escaped template delimiters can bypass detection; change the logic to parse the TOML first (use toml::from_str to get toml::Value::Table), then re-run contains_template_syntax on the decoded string values (for keys like "min_version", "tasks", and inside the "tools" table: each version string and each string element of version arrays) and treat any decoded string containing template syntax as unsafe; update task_include_requires_trust to perform the same parse-then-inspect flow for included task files and add regression tests covering unicode-escaped templates in root configs and task include files.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@e2e/tasks/test_task_monorepo_trust`:
- Around line 46-64: The test fails to exercise the untrusted path in CI because
is_trusted() is short-circuited; before the negative-path assertion that checks
for "are not trusted" (the assert_contains line) add the same CI auto-trust
disabling used in other trust e2es: unset or clear CI, GITHUB_ACTIONS, and
GITHUB_ACTION environment variables (in addition to setting
MISE_TRUSTED_CONFIG_PATHS="") so is_trusted() will evaluate false and the trust
error path is tested.
---
Duplicate comments:
In `@src/config/config_file/mise_toml.rs`:
- Around line 1984-2005: The current trust checks in is_safe_config_body (and
similarly task_include_requires_trust) only scan the raw file text so
unicode-escaped template delimiters can bypass detection; change the logic to
parse the TOML first (use toml::from_str to get toml::Value::Table), then re-run
contains_template_syntax on the decoded string values (for keys like
"min_version", "tasks", and inside the "tools" table: each version string and
each string element of version arrays) and treat any decoded string containing
template syntax as unsafe; update task_include_requires_trust to perform the
same parse-then-inspect flow for included task files and add regression tests
covering unicode-escaped templates in root configs and task include files.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6f6e1167-e97b-44b8-8184-45e2e4dc2227
📒 Files selected for processing (10)
docs/cli/trust.mddocs/faq.mde2e/config/test_trust_safe_confige2e/tasks/test_task_monorepo_truste2e/tasks/test_task_untrusted_config_errormise.usage.kdlsrc/cli/trust.rssrc/config/config_file/mise_toml.rssrc/config/config_file/mod.rssrc/config/mod.rs
✅ Files skipped from review due to trivial changes (2)
- mise.usage.kdl
- src/cli/trust.rs
🚧 Files skipped from review as they are similar to previous changes (2)
- docs/cli/trust.md
- docs/faq.md
is_safe_config_body only checked the raw TOML body for Tera delimiters, so a value like "\u007b\u007b exec(...) \u007d\u007d" (which TOML decodes to a real template) loaded without trust and executed via exec() when the tool version or task field rendered. Re-check every decoded string (keys and values, at any depth) for template syntax so escaped delimiters can't slip through. Also load safe (untrusted) mise.toml files through tracked-config reload paths: get_tracked_config_files skipped any path without a trust marker, which safe configs don't create, so their tool pins went missing from `mise ls --all-sources`, `mise upgrade`, and `mise prune`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for the reviews — addressed in c70a4dc:
This comment was generated by an AI coding assistant. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c70a4dc. Configure here.
task_include_requires_trust only scanned the raw file text, so a mise-tasks/*.toml field or a #MISE script header written with escaped delimiters (e.g. "\u007b\u007b exec(...) \u007d\u007d") decoded to a real template after parsing and rendered — running exec() — during `mise tasks` without trust. Now also reject template syntax found in the decoded TOML: whole-file for .toml includes, and #MISE header values for scripts (the only part parsed and rendered at load). Reuses the recursive toml_value_has_template helper added for is_safe_config_body. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Addressed the task-include variant in c01306d (Cursor, high — "Task includes skip decoded templates"). Confirmed it was real and reproduced it: a Fix: Tests: unit This comment was generated by an AI coding assistant. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@e2e/tasks/test_task_include_trust_escaped`:
- Around line 21-30: Update the test header to use escaped template delimiters
so the header contains an escaped literal template (not raw unescaped {{...}});
replace the current header string in mise-tasks/evil.sh (the line that sets
`#MISE` description="{{ exec(command='touch script-marker') }}") with an
escaped-brace form (e.g. backslash-escaped or otherwise escaped delimiters like
\{\{ ... \}\}) so the test exercises the script-header raw-text gate correctly
and fails if decoded headers stop being checked.
In `@src/task/mod.rs`:
- Around line 507-519: The regex in parse_mise_header_toml currently only
matches `#MISE`/`#[MISE]` without a space and thus misses `# MISE`, `// MISE`,
`:: MISE`; update the regex in parse_mise_header_toml so the comment marker
group (?:#|//|::) allows optional whitespace after it and the MISE token/bracket
form is matched with that spacing, keeping the TOML capture group intact (e.g.
use a pattern like
r"^(?:#|//|::)\s*(?:MISE|\[MISE\])\s+([a-z0-9_.-]+\s*=\s*[^\n]+)$") so
captures.extract().1 and the subsequent toml::de::from_str logic continue to
work.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 66bf2b5d-19ad-4f60-a9aa-b681d0a39823
📒 Files selected for processing (4)
e2e/tasks/test_task_include_trust_escapedsrc/config/config_file/mise_toml.rssrc/config/mod.rssrc/task/mod.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- src/config/mod.rs
| /// Parse the `#MISE key=value` (and `// MISE`, `:: MISE`, `[MISE]`) header | ||
| /// lines out of a task script into their decoded TOML values. | ||
| fn parse_mise_header_toml(body: &str) -> Result<Vec<toml::Value>> { | ||
| body.lines() | ||
| .filter_map(|line| { | ||
| regex!(r"^(?:#|//|::)(?:MISE| ?\[MISE\]) ([a-z0-9_.-]+\s*=\s*[^\n]+)$").captures(line) | ||
| }) | ||
| .map(|captures| captures.extract().1) | ||
| .map(|[toml]| { | ||
| toml::de::from_str::<toml::Value>(toml) | ||
| .map_err(|e| eyre::eyre!("failed to parse task header TOML {toml:?}: {e}")) | ||
| }) | ||
| .collect() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Allow whitespace before plain MISE headers.
Line 512 only matches #MISE and # [MISE]-style prefixes. It does not match # MISE / // MISE / :: MISE, so Task::from_path() now drops metadata for those header forms. That also contradicts the doc comment here and the existing test_from_path_toml_headers() case with # MISE alias="b".
Suggested fix
- regex!(r"^(?:#|//|::)(?:MISE| ?\[MISE\]) ([a-z0-9_.-]+\s*=\s*[^\n]+)$").captures(line)
+ regex!(r"^(?:#|//|::)\s*(?:MISE|\[MISE\])\s+([a-z0-9_.-]+\s*=\s*[^\n]+)$").captures(line)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/task/mod.rs` around lines 507 - 519, The regex in parse_mise_header_toml
currently only matches `#MISE`/`#[MISE]` without a space and thus misses `#
MISE`, `// MISE`, `:: MISE`; update the regex in parse_mise_header_toml so the
comment marker group (?:#|//|::) allows optional whitespace after it and the
MISE token/bracket form is matched with that spacing, keeping the TOML capture
group intact (e.g. use a pattern like
r"^(?:#|//|::)\s*(?:MISE|\[MISE\])\s+([a-z0-9_.-]+\s*=\s*[^\n]+)$") so
captures.extract().1 and the subsequent toml::de::from_str logic continue to
work.
The script-header case used a literal {{ template, which the raw-text gate
already rejects, so it didn't actually guard the decoded-header check. Use
escaped {{ delimiters so the test locks down file_has_decoded_template
for the #MISE script path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Two follow-ups from the latest review (1dd9a7e):
This comment was generated by an AI coding assistant. |

Summary
mise.tomlfiles that cannot execute code at load time or change mise's behavior without an explicit user action no longer require trust. A config is exempt from the trust gate only when:{{,{%,{#) and on every decoded TOML string (keys/values, any depth) so escaped delimiters can't slip through — andmin_version,[tasks], and[tools]entries whose values are plain version strings (or arrays of them)Tools install and tasks run only on explicit commands (
mise install,mise run), so loading these configs executes nothing. Template-free file tasks (mise-tasks/scripts and included TOML task files) are likewise loadable without trust — templates are the only thing that can execute while tasks load.Everything else keeps the existing trust prompt/error:
[env],[hooks],[settings],[alias],[plugins],[task_config],env_file/dotenv, tool entries with options (tables) — since options likepostinstallrun shell commands andinstall_envcan alter the install environment — and any file with template syntax. Paranoid mode still requires trust for every file, and ignored configs stay unloaded even when safe.The check is allowlist-based, so an unrecognized or future config construct fails safe (still prompts for trust).
Security hardening
is_safe_config_bodyoriginally only scanned the raw TOML body, sotiny = "{{ exec(...) }}"— which TOML decodes to{{ exec(...) }}— passed as "safe" and then executed via Tera when the tool version / task field rendered, with no trust prompt. Fixed by recursively re-checking every decoded TOML string for template syntax. Regression tests added (unit + e2e) for both the tools and tasks paths.load_tasks_in_dirskipped the include trust check whenever any config existed at the root, even one loaded without trust (e.g. a plain.tool-versions), so a templatedmise-tasks/*.tomlcould renderexec()atmise taskstime. Includes now require trust unless a root config was actually trusted (newconfig_file::is_path_trusted).Other fixes
get_tracked_config_filesskipped any path without a trust marker, which safe configs don't create — so their tool pins went missing frommise ls --all-sources,mise upgrade, andmise prune. Safe configs are now loaded there too (MiseToml::path_is_trust_exempt). Regression test:e2e/config/test_trust_safe_config_tracked.Tests
test_is_safe_config_body: tools/tasks safe cases, plus rejection of templates, tool-options, and escaped templates in tool versions, task fields, and keyse2e/config/test_trust_safe_config: safe tools+tasks (config and file tasks) load/run with no trust marker; literal- and escaped-template variants in versions, task fields, and file-task headers, plus tool-options and[env], are all blocked with nothing executinge2e/config/test_trust_safe_config_tracked: safe config's pins survive tracked-config reload from another directorytest_task_untrusted_config_error/test_task_monorepo_trustupdated for the new semantics; all other trust e2e tests pass unchanged🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Refactor
Tests
Note
High Risk
Changes when untrusted config is parsed and when templates can run at load time; mistakes could allow code execution without a trust prompt.
Overview
Untrusted
mise.tomlfiles that only pin tools and define tasks can now load withoutmise trust, when their content is allowlisted (min_version, plain[tools]strings/arrays,[tasks]with no tool-option tables) and has no Tera templates. Parsing skipstrust_checkviais_trust_exempt/path_is_trust_exempt; everything else ([env], hooks, settings, templates,postinstall, etc.) still requires trust, and paranoid / ignored configs stay gated.Security tightening: decoded TOML strings are scanned for templates so Unicode-escaped
{{ exec(...) }}cannot bypass a raw-body check. Task includes andmise-tasksfiles only auto-load without trust when template-free; templated#MISEheaders and included TOML still require trust. Trusted vs trust-exempt is split withis_path_trustedso safe configs cannot vouch for includes, and tracked-config reload no longer drops safe configs missing a trust marker.Docs/CLI help and e2e tests document and cover safe load, escaped-template blocks, and tracked-config visibility.
Reviewed by Cursor Bugbot for commit 1dd9a7e. Bugbot is set up for automated code reviews on this repo. Configure here.