Skip to content

fix(env): redact secrets in mise set listing and task-specific env#8583

Merged
jdx merged 4 commits intomainfrom
fix/redact-set-and-task-env
Mar 13, 2026
Merged

fix(env): redact secrets in mise set listing and task-specific env#8583
jdx merged 4 commits intomainfrom
fix/redact-set-and-task-env

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Mar 13, 2026

Summary

  • mise set (no args) now redacts values marked with redact = true or matching redactions patterns in the listing output. Added --no-redact flag to show raw values when needed.
  • Task-specific env redactions (e.g. from env._.file or redact = true in [tasks.*.env]) are now registered with the global redactor, fixing redaction in task output.

Closes #5368

Test plan

  • Verify mise set redacts values for env vars with redact = true
  • Verify mise set --no-redact shows raw values
  • Verify task-specific env._.file with redactions patterns are properly redacted in task output
  • Verify existing cargo test passes

🤖 Generated with Claude Code


Note

Medium Risk
Changes how environment values are displayed and how redaction patterns are registered, which could unintentionally hide/show values in CLI/task output. Core execution paths are mostly unchanged but touch global redactor behavior in tasks.

Overview
Redacts secret env values in mise set output by default when listing variables, covering redact = true, age-encrypted entries (default redacted), and config-level redactions patterns; adds --no-redact to show raw values.

Fixes task output redaction for task-scoped env vars by registering redactions resolved from task context (including env._.file and task-level redactions) with the global redactor so secrets are consistently masked in mise run output.

Docs/man/usage specs and shell completion metadata are updated, and new e2e tests cover the redaction/override behavior for both mise set and tasks.

Written by Cursor Bugbot for commit 860282a. This will update automatically on new commits. Configure here.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the handling of sensitive information within mise by implementing robust redaction capabilities. It ensures that secrets are masked when listing environment variables via mise set and correctly applies redaction rules to task-specific environment outputs, enhancing overall security and preventing accidental exposure of confidential data.

Highlights

  • Enhanced Secret Redaction in mise set: The mise set command (when called without arguments) now automatically redacts sensitive values that are marked with redact = true or match defined redactions patterns in its listing output.
  • New --no-redact Flag: A new --no-redact flag has been introduced for mise set, allowing users to explicitly display raw, unredacted secret values when necessary.
  • Improved Task-Specific Environment Redaction: Task-specific environment redactions, such as those from env._.file or redact = true within [tasks.*.env], are now correctly registered with the global redactor, ensuring proper redaction in task output.
Changelog
  • docs/cli/set.md
    • Documented the new --no-redact flag for the mise set command.
  • mise.usage.kdl
    • Registered the --no-redact flag for the mise set command in the usage definition.
  • src/cli/set.rs
    • Added the no_redact field to the Set struct to control redaction behavior.
    • Implemented logic in list_all to redact environment variable values unless the --no-redact flag is present.
  • src/task/task_context_builder.rs
    • Added code to register config-level redactions with the global redactor during task context building.
    • Included logic to register task-specific redactions with the global redactor, ensuring they are applied to task output.
Activity
  • The author has provided a test plan to verify the new redaction behavior for mise set and task-specific environments, including checking the --no-redact flag and existing cargo test passes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses secret redaction in two key areas. First, it introduces redaction for mise set output, with a --no-redact flag to bypass it. Second, it ensures that task-specific redaction patterns are correctly registered with the global redactor, fixing an issue where secrets could be exposed in task outputs. The implementation looks solid, with corresponding updates to documentation and CLI definitions. I have no specific comments on the changes.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR fixes two related redaction gaps: mise set (no args) now applies redact = true and redactions patterns when listing env vars, with a new --no-redact escape hatch; and task-specific env vars (loaded via env._.file or redact = true in [tasks.*.env]) are now registered with the global redactor so task output is also protected. The changes integrate cleanly with the existing Aho-Corasick–based _REDACTOR and the lazy env_results caching in Config.

Key changes:

  • src/cli/set.rs: new rows_from_directives helper handles per-variable redact = true and Age-default redaction for --file/-E paths; the default path runs config.env_results() to prime the global redactor and then applies config.redact() over every row value.
  • src/task/mod.rs + src/task/task_context_builder.rs: after resolving task-specific env directives, add_redactions is called with both the config's glob patterns and the task's redact = true keys against the full (or task-scoped) env map.

One gap to address: When --file points to a file outside the config hierarchy, variables in that file that match the main config's redactions glob patterns (but have no per-variable redact = true) will not be redacted. config.env_results() only registers values from the main config's own env, so the external file's values are never seen by the global redactor. See inline comment on list_all for a suggested fix. The same applies to the -E path.

Confidence Score: 3/5

  • Mostly safe to merge; one edge-case redaction gap in --file mode could silently expose values matching glob patterns from the main config when the file is outside the config hierarchy.
  • The core logic for the default listing path and both task execution paths is sound and well-tested. The implementation correctly primes the global redactor and handles both redact=true per-variable and redactions glob patterns for the common cases. The deduction is for the identified gap in --file-to-external-file mode where glob-pattern redaction doesn't fire — a real but narrow attack surface that the existing tests do not cover. No runtime crashes, data corruption, or build-breaking issues were found.
  • src/cli/set.rs — specifically the list_all function's handling of the --file and -E paths with respect to glob-pattern redaction for external files.

Important Files Changed

Filename Overview
src/cli/set.rs Adds --no-redact flag, rows_from_directives helper for inline redact=true/Age handling, and a call to config.env_results() to prime the global redactor. Per-variable redact=true is handled correctly; however, glob redactions patterns from the main config are not applied to vars that exist only in an external --file target, leaving a potential secret-leak gap for that edge case.
src/task/mod.rs After resolving task-specific env directives, newly registers task env values against both config.redaction_keys() glob patterns and per-directive redact=true key names. task_env_map (task-specific only) is passed to add_redactions, which is correct because config-level env values are already registered during ts.full_env()env_results()load_env(). Logic is sound.
src/task/task_context_builder.rs Two add_redactions calls added: one for config-level redact=true keys (uses env before task env is merged), one for task-level redact=true keys and config glob patterns (uses full env including task env). Separation of responsibilities is correct; the full env map passed to the second call ensures glob patterns correctly match task-specific vars.
e2e/cli/test_set Good coverage for redact=true, redactions pattern, --file in-hierarchy, and --file outside hierarchy. Missing a test for the case where the external --file target has keys matching the main config's redactions glob pattern (without per-variable redact=true).
e2e/tasks/test_task_redactions Two new test cases correctly verify task-specific env._.file with redactions patterns and with redact=true. Logic is sound and matches intended behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[mise set no-args] --> B[list_all]
    B --> D{no_redact flag?}
    D -->|false| E[config.env_results primes global redactor]
    E --> F{--file or -E flag?}
    F -->|yes| G[rows_from_directives\nhandles redact=true and Age inline\nNOTE: glob patterns miss external-file vars]
    F -->|no default path| H[env_with_sources returns resolved values]
    G --> I[config.redact applies registered patterns to each row]
    H --> I
    I --> J[Print redacted table]
    D -->|true no-redact| K[Return raw rows without redaction]
    K --> J

    L[mise run task] --> M{task_cf present?}
    M -->|complex path| O[TaskContextBuilder\nresolve_task_env_with_config]
    O --> P[add_redactions: config redact=true keys vs config env]
    P --> Q[add_redactions: config glob patterns + task redact=true keys vs full env]
    M -->|simple or no task_cf| R[task.render_env in mod.rs]
    R --> S[add_redactions: config glob patterns + task redact=true keys vs task_env_map]
    Q --> T[Execute task - global redactor protects all output]
    S --> T
Loading

Comments Outside Diff (1)

  1. src/cli/set.rs, line 240-256 (link)

    redactions glob patterns not applied to external --file vars

    When --file points to a file outside the config hierarchy, config.env_results() (called to prime the global redactor) only processes the main config's env vars — not the external file's vars. As a result, any variable in the external file that matches a redactions glob pattern from the main config (e.g. redactions = ["DB_*"]) will not be redacted by the subsequent config.redact() pass.

    Concretely, if the main config contains redactions = ["DB_*"] and the external file contains DB_PASSWORD = "..." (with no per-variable redact = true), running mise set --file /tmp/external.toml will print the plaintext value unredacted.

    The per-variable redact = true path is correctly handled by rows_from_directives, but the glob-pattern path relies on the global redactor having already seen the matching values, which it hasn't for vars that exist only in the external file.

    A fix would be to extract the external file's resolved env values and register them against the config-level patterns before calling config.redact():

    if !self.no_redact {
        let external_env: EnvMap = mise_toml
            .env_entries()?
            .into_iter()
            .filter_map(|ed| match ed {
                EnvDirective::Val(k, v, _) => Some((k, v)),
                _ => None,
            })
            .collect();
        config.add_redactions(config.redaction_keys(), &external_env);
    }

    The same gap applies to the -E (environment-specific file) path at lines 333–336.

Fix All in Claude Code

Last reviewed commit: 860282a

- `mise set` (no args) now redacts values marked with `redact = true`
  or matching `redactions` patterns. Use `--no-redact` to show raw values.
- Eagerly load env_results before listing so redactions work with
  `--file` and `-E` flags too.
- Register task-specific env redactions (e.g. from `env._.file` in tasks)
  with the global redactor so they are properly redacted in task output.
- Also apply config-level `redactions` patterns against task-specific
  env vars in both render_env and TaskContextBuilder paths.
- Add e2e tests for `mise set` redaction and task-specific env redaction.

Closes #5368

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx force-pushed the fix/redact-set-and-task-env branch from 5186e85 to 22f0a6b Compare March 13, 2026 13:56
@jdx
Copy link
Copy Markdown
Owner Author

jdx commented Mar 13, 2026

bugbot run

When --file or -E points to a file outside the loaded config hierarchy,
the global redactor has no knowledge of its secrets. Fix by checking the
EnvDirectiveOptions.redact field directly when building rows from
directives, so redaction works regardless of whether the file is in the
config hierarchy.

Also always redact Age-encrypted values in directive-based listings
since they are inherently secret.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 13, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.8 x -- echo 23.2 ± 0.2 22.6 24.4 1.00
mise x -- echo 23.7 ± 0.4 23.1 28.5 1.02 ± 0.02

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.8 env 22.7 ± 0.4 22.0 26.4 1.00
mise env 23.2 ± 0.3 22.6 26.9 1.02 ± 0.02

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.8 hook-env 23.4 ± 0.3 22.8 25.5 1.00
mise hook-env 23.8 ± 0.3 23.2 25.8 1.02 ± 0.02

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.8 ls 22.7 ± 0.3 22.1 24.2 1.00
mise ls 23.0 ± 0.2 22.5 24.3 1.02 ± 0.02

xtasks/test/perf

Command mise-2026.3.8 mise Variance
install (cached) 150ms 150ms +0%
ls (cached) 82ms 82ms +0%
bin-paths (cached) 85ms 85ms +0%
task-ls (cached) 837ms 815ms +2%

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Age directives default to redacting for security (matching env
resolution behavior), but now correctly skip redaction when the user
explicitly sets redact=false on an age directive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx enabled auto-merge (squash) March 13, 2026 14:46
@jdx jdx merged commit 9847f88 into main Mar 13, 2026
37 checks passed
@jdx jdx deleted the fix/redact-set-and-task-env branch March 13, 2026 14:51
mise-en-dev added a commit that referenced this pull request Mar 13, 2026
### 🚀 Features

- **(github)** use release latest endpoint to get latest release by
@roele in [#8516](#8516)
- **(install)** add shared and system install directories by @jdx in
[#8581](#8581)
- **(vfox)** add provenance metadata to lockfile for tool plugins by
@malept in [#8544](#8544)

### 🐛 Bug Fixes

- **(aqua)** expose main binary when files field is empty and
symlink_bins is enabled by @AlexanderTheGrey in
[#8550](#8550)
- **(env)** redact secrets in `mise set` listing and task-specific env
by @jdx in [#8583](#8583)
- **(prepare)** install config tools before running prepare steps by
@jdx in [#8582](#8582)
- **(task)** allow ctrl-c to interrupt tool downloads during `mise run`
by @jdx in [#8571](#8571)
- **(tasks)** add file task header parser support for spaces around = by
@roele in [#8574](#8574)

### 📚 Documentation

- **(task)** add property description for interactive by @roele in
[#8562](#8562)
- add missing `</bold>` closing tag by @muzimuzhi in
[#8564](#8564)
- rebrand site with new chef logo and warm culinary palette by @jdx in
[#8587](#8587)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:alpine docker digest to de4657e by
@renovate[bot] in [#8577](#8577)
- update ghcr.io/jdx/mise:copr docker digest to eef29a2 by
@renovate[bot] in [#8578](#8578)
- update ghcr.io/jdx/mise:rpm docker digest to 5a96587 by @renovate[bot]
in [#8580](#8580)
- update ghcr.io/jdx/mise:deb docker digest to 464cf7c by @renovate[bot]
in [#8579](#8579)

### 📦 Registry

- fix flatc version test mismatch by @jdx in
[#8588](#8588)

### Chore

- **(registry)** skip spark test-tool by @jdx in
[#8572](#8572)

### New Contributors

- @AlexanderTheGrey made their first contribution in
[#8550](#8550)

## 📦 Aqua Registry Updates

#### New Packages (6)

- [`bahdotsh/mdterm`](https://github.com/bahdotsh/mdterm)
-
[`callumalpass/mdbase-lsp`](https://github.com/callumalpass/mdbase-lsp)
- [`facebook/ktfmt`](https://github.com/facebook/ktfmt)
- [`gurgeous/tennis`](https://github.com/gurgeous/tennis)
-
[`tektoncd/pipelines-as-code`](https://github.com/tektoncd/pipelines-as-code)
- [`weedonandscott/trolley`](https://github.com/weedonandscott/trolley)

#### Updated Packages (2)

- [`apple/container`](https://github.com/apple/container)
- [`cocogitto/cocogitto`](https://github.com/cocogitto/cocogitto)
fragon10 pushed a commit to fragon10/mise that referenced this pull request Mar 27, 2026
…dx#8583)

## Summary
- `mise set` (no args) now redacts values marked with `redact = true` or
matching `redactions` patterns in the listing output. Added
`--no-redact` flag to show raw values when needed.
- Task-specific env redactions (e.g. from `env._.file` or `redact =
true` in `[tasks.*.env]`) are now registered with the global redactor,
fixing redaction in task output.

Closes jdx#5368

## Test plan
- [ ] Verify `mise set` redacts values for env vars with `redact = true`
- [ ] Verify `mise set --no-redact` shows raw values
- [ ] Verify task-specific `env._.file` with `redactions` patterns are
properly redacted in task output
- [ ] Verify existing `cargo test` passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes how environment values are displayed and how redaction
patterns are registered, which could unintentionally hide/show values in
CLI/task output. Core execution paths are mostly unchanged but touch
global redactor behavior in tasks.
> 
> **Overview**
> **Redacts secret env values in `mise set` output by default** when
listing variables, covering `redact = true`, age-encrypted entries
(default redacted), and config-level `redactions` patterns; adds
`--no-redact` to show raw values.
> 
> **Fixes task output redaction for task-scoped env vars** by
registering redactions resolved from task context (including
`env._.file` and task-level `redactions`) with the global redactor so
secrets are consistently masked in `mise run` output.
> 
> Docs/man/usage specs and shell completion metadata are updated, and
new e2e tests cover the redaction/override behavior for both `mise set`
and tasks.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
860282a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
fragon10 pushed a commit to fragon10/mise that referenced this pull request Mar 27, 2026
### 🚀 Features

- **(github)** use release latest endpoint to get latest release by
@roele in [jdx#8516](jdx#8516)
- **(install)** add shared and system install directories by @jdx in
[jdx#8581](jdx#8581)
- **(vfox)** add provenance metadata to lockfile for tool plugins by
@malept in [jdx#8544](jdx#8544)

### 🐛 Bug Fixes

- **(aqua)** expose main binary when files field is empty and
symlink_bins is enabled by @AlexanderTheGrey in
[jdx#8550](jdx#8550)
- **(env)** redact secrets in `mise set` listing and task-specific env
by @jdx in [jdx#8583](jdx#8583)
- **(prepare)** install config tools before running prepare steps by
@jdx in [jdx#8582](jdx#8582)
- **(task)** allow ctrl-c to interrupt tool downloads during `mise run`
by @jdx in [jdx#8571](jdx#8571)
- **(tasks)** add file task header parser support for spaces around = by
@roele in [jdx#8574](jdx#8574)

### 📚 Documentation

- **(task)** add property description for interactive by @roele in
[jdx#8562](jdx#8562)
- add missing `</bold>` closing tag by @muzimuzhi in
[jdx#8564](jdx#8564)
- rebrand site with new chef logo and warm culinary palette by @jdx in
[jdx#8587](jdx#8587)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:alpine docker digest to de4657e by
@renovate[bot] in [jdx#8577](jdx#8577)
- update ghcr.io/jdx/mise:copr docker digest to eef29a2 by
@renovate[bot] in [jdx#8578](jdx#8578)
- update ghcr.io/jdx/mise:rpm docker digest to 5a96587 by @renovate[bot]
in [jdx#8580](jdx#8580)
- update ghcr.io/jdx/mise:deb docker digest to 464cf7c by @renovate[bot]
in [jdx#8579](jdx#8579)

### 📦 Registry

- fix flatc version test mismatch by @jdx in
[jdx#8588](jdx#8588)

### Chore

- **(registry)** skip spark test-tool by @jdx in
[jdx#8572](jdx#8572)

### New Contributors

- @AlexanderTheGrey made their first contribution in
[jdx#8550](jdx#8550)

## 📦 Aqua Registry Updates

#### New Packages (6)

- [`bahdotsh/mdterm`](https://github.com/bahdotsh/mdterm)
-
[`callumalpass/mdbase-lsp`](https://github.com/callumalpass/mdbase-lsp)
- [`facebook/ktfmt`](https://github.com/facebook/ktfmt)
- [`gurgeous/tennis`](https://github.com/gurgeous/tennis)
-
[`tektoncd/pipelines-as-code`](https://github.com/tektoncd/pipelines-as-code)
- [`weedonandscott/trolley`](https://github.com/weedonandscott/trolley)

#### Updated Packages (2)

- [`apple/container`](https://github.com/apple/container)
- [`cocogitto/cocogitto`](https://github.com/cocogitto/cocogitto)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant