Adds support for mise.toml files and mise Tasks#57
Conversation
- Introduced a new test file `mise_test.go` to cover various scenarios for the `MiseProbe`. - Implemented tests for: - Probe name and enabled state. - Execution without a file index and with an empty index. - Handling of missing files and invalid TOML lines. - Extraction of environment values and detection of plaintext secrets. - Classification of file types and handling of nested subtables. - Ensured that findings are correctly annotated and deduplicated between structured and line scans. - Added tests for task environment blocks and run strings to verify proper detection of secrets.
There was a problem hiding this comment.
Pull request overview
This PR adds two new probes to Bagel to detect plaintext secrets in the mise ecosystem: TOML configuration files (mise.toml family + legacy .rtx.*) and mise “file task” scripts. It extends the config/file-index defaults so these files are discovered during scans, and documents the new probes in the README and sample config.
Changes:
- Introduces
miseprobe to parse/walk mise TOML ([env],[[env]], and[tasks.*]env/run) with a line-scan fallback and richer per-finding metadata. - Introduces
mise_tasksprobe to scan mise task scripts, including parsing#MISE env=...headers and line-scanning bodies with dedup. - Wires both probes into configuration defaults, scanning initialization, and documentation (README +
bagel.yaml), and adds comprehensive tests.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents the two new probes in the probe table. |
| pkg/probe/mise.go | Implements the mise TOML config probe with structured parsing + line-scan dedup. |
| pkg/probe/mise_common.go | Shared helpers: file classification, bounded reads, env-value extraction, finding annotation. |
| pkg/probe/mise_tasks.go | Implements the mise_tasks probe for script headers + body line scanning. |
| pkg/probe/mise_test.go | Extensive unit + fuzz coverage for mise TOML classification and scanning behaviors. |
| pkg/probe/mise_tasks_test.go | Unit coverage for task-name derivation, header parsing, and scanning behaviors. |
| pkg/models/config.go | Adds mise and mise_tasks probe settings to the config model. |
| pkg/config/config.go | Adds defaults enabling the probes and adds file-index patterns for mise config/task files. |
| cmd/bagel/scan.go | Registers the new probes in the scan initialization pipeline. |
| go.mod | Adds github.com/pelletier/go-toml/v2 as a direct dependency. |
| bagel.yaml | Documents configuration for the new probes. |
| CLA_SIGNATURES.md | Adds a CLA signature entry and fixes formatting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var miseTaskHeaderEnvRe = regexp.MustCompile( | ||
| `(?m)^\s*(?://|#)\s*(?:MISE|\[MISE\])\s+env\s*=\s*(.+?)\s*$`, | ||
| ) |
There was a problem hiding this comment.
I believe this comment is incorrect and RE2 does support lazy quantifiers. .+? compiles fine, MustCompile doesn't panic, and the tests/fuzz pass.
| if err := toml.Unmarshal(doc, &parsed); err != nil { | ||
| log.Ctx(ctx).Debug().Err(err).Str("file", path).Bytes("header_value", m[1]). | ||
| Msg("Cannot parse #MISE env header value as TOML") | ||
| continue | ||
| } |
There was a problem hiding this comment.
Good catch, this is fixed in d10fb26. Dropped the header value and the parse error from the log (kept just the path + byte length), since go-toml errors can echo an input byte too.
The debug log on a failed TOML parse wrote the raw header value, which
can hold a plaintext secret (e.g. #MISE env={ TOKEN = "ghp_..." }).
go-toml parse errors also interpolate the offending input byte (%c/%#U),
so the error string can leak a character too. bagel never logs secret
material, so log only the file path and the value's byte length.
Addresses Copilot review on PR boostsecurityio#57. The companion Copilot finding about
RE2 rejecting the .+? lazy quantifier is incorrect — RE2 supports lazy
quantifiers, MustCompile does not panic, and the suite/fuzz pass.
Summary
Adds two probes for mise (jdx/mise), the polyglot tool-version + env-var + task manager:
mise: scans foir mise config files (mise.toml family, .config/mise/..., legacy .rtx.) for plaintext secrets in [env] / [[env]] tables and in inline [tasks.] env/run blocks.mise_tasks: scans mise file-task scripts under mise-tasks/, .mise-tasks/, mise/tasks/, .mise/tasks/, .config/mise/tasks/. Parses#MISE env={...}headers (also# [MISE]and//MISEvariants) and line-scans the script body.Both probes share
pkg/probe/mise_common.go(file classifier, env-value extractor, scan-context type) - matching theai_common.goprecedent. Findings carry amise_*metadata vocabulary so consumers can locate the offending env var / task / file role.Motivation
mise's
redact = truetable form only suppresses values frommise envoutput at runtime - the secret itself sits in plaintext on disk. We tested this against a real workstation and immediately caught aghp_*PAT in~/.config/mise/config.tomlthat no other bagel probe surfaces.