Hmbown/CodeWhale · critical

the envelope must independently refuse the write-capable…

Error message

the envelope must independently refuse the write-capable filter

What it means

In the read-only-role enforcement test (crates/tui/src/tools/subagent/tests.rs:8255), `registry.envelope_refusal("bash", &call).expect("the envelope must independently refuse the write-capable filter")` asserts that the execution envelope returns a refusal (an `Option`/`Result` that is `Some`/`Ok`) for `sort -o filter-output.txt input.txt`, a command that writes via an output flag. A panic means the envelope failed to flag the write-capable filter — a security-relevant regression, not an environmental fault.

Solutions

  1. Run the test and check which deny rules evaluate for `sort -o filter-output.txt input.txt`.
  2. Restore/extend the write-detection rule so output-flag usage of text filters is refused.
  3. If the rule identifier changed, update both the rule and the assertion string together.
  4. Verify `envelope_refusal` returns a refusal rather than `None` for postures where posture permits but envelope denies.

Example fix

// before
let envelope_refusal = registry.envelope_refusal("bash", &call).expect("the envelope must independently refuse the write-capable filter");
// after (test diagnostics)
let envelope_refusal = registry.envelope_refusal("bash", &call)
    .unwrap_or_else(|| panic!("envelope did not refuse write-capable filter: {call}"));
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the command against write-capable patterns before dispatch
fn writes_output_file(cmd: &str) -> bool {
    // e.g. sort -o <file>, tee, redirect targets
    cmd.contains(" -o ") || cmd.contains(">") || cmd.contains("tee ")
}

Try / catch

// In tests, assert refusal presence with a diagnostic message
let refusal = registry.envelope_refusal("bash", &call)
    .unwrap_or_else(|| panic!("envelope failed to refuse write-capable command: {call}"));
assert!(refusal.contains("[execution_envelope.executes.write_denied]"));

Prevention

When it happens

Trigger: Modifying the envelope's deny rules (e.g. the `[execution_envelope.executes.write_denied]` rule) so `sort -o <file>` no longer matches write-capable filter usage, or changing how `envelope_refusal` signals refusal (returning `None` on allowed commands).

Common situations: Relaxing the bash carve-out for text filters, renaming the refusal rule marker so the assertion string no longer matches, or refactoring rule evaluation order so the write rule is skipped.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/3d89b384a990cf33. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/tests.rs:8255

        std::fs::write(&input_path, "b\na\n").expect("input fixture");
        let output_path = tmp.path().join("filter-output.txt");
        let mut runtime =
            stub_runtime().with_agent_tool_surface_options(enabled_agent_surface_options());
        runtime.context = ToolContext::new(tmp.path().to_path_buf());
        runtime.worker_profile = WorkerRuntimeProfile::for_role(role.clone());
        seed_read_only_role_deny_list(&mut runtime);
        let registry = SubAgentToolRegistry::new(
            runtime,
            role.clone(),
            None,
            crate::tools::todo::new_shared_todo_list(),
            crate::tools::plan::new_shared_plan_state(),
        );

        let call = json!({"command": "sort -o filter-output.txt input.txt"});
        let envelope_refusal = registry
            .envelope_refusal("bash", &call)
            .expect("the envelope must independently refuse the write-capable filter");
        assert!(
            envelope_refusal.contains("[execution_envelope.executes.write_denied]"),
            "{role:?} envelope refusal did not identify its failed rule: {envelope_refusal}"
        );

        let posture_refusal = registry
            .execute("agent_read_only_filter", "bash", call)
            .await
            .expect_err("a read-only inspection role must not write through sort")
            .to_string();
        assert!(
            posture_refusal.contains("[shell.readonly.command]"),
            "{role:?} posture refusal did not identify its failed rule: {posture_refusal}"
        );
        assert!(
            !output_path.exists(),
            "{role:?} read-only filter created {} from {}",
            output_path.display(),

View on GitHub (pinned to 433685b202)