Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CLA_SIGNATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ julien-boost - Julien Champoux
GuillaumeRoss - Guillaume Ross
c0tton-fluff - Michal Ambrozkiewicz
tveronezi - Thiago Veronezi
stlef14 - Stephan Lefrancois
stlef14 - Stephan Lefrancois
smithjw - James Smith
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ Each probe declares its scope (user/system), paths touched, env vars read, and r
| `jetbrains` | JetBrains IDE configuration | JetBrains IDE workspace files and configuration for embedded secrets |
| `gh` | GitHub CLI | GitHub CLI authentication tokens and configuration |
| `ai_cli` | AI CLI tools | Credential files and chat logs for Gemini, Codex, Claude, and OpenCode |
| `mise` | [`mise`](https://mise.jdx.dev) configuration files | Plaintext secrets in `[env]` tables, `[[env]]` array-of-tables, and `[tasks.*]` env/run blocks |
| `mise_tasks` | `mise` file-task scripts | Plaintext secrets in script bodies and in `#MISE env={...}` / `# [MISE] env=` / `//MISE env=` header directives |

### Current Detectors

Expand Down
26 changes: 26 additions & 0 deletions bagel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,32 @@ probes:
# max_file_size: maximum bytes to read from a chat file before skipping it.
# Prevents scan hangs on large conversation histories. Default: 1048576 (1 MB).
# max_file_size: 1048576
mise:
# Scans mise (https://mise.jdx.dev) configuration files for plaintext
# secrets in [env] tables AND in inline [tasks.*] env/run blocks.
# Covers global config plus the mise.toml family (mise.toml, .mise.toml,
# mise.local.toml, env-specific variants like mise.production.toml, idiomatic
# dir forms, and legacy .rtx.toml). The `redact = true` table form is reported
# as a finding (only suppresses output; the secret is still plaintext on disk).
enabled: true
flags:
# max_file_size: maximum bytes to read from a mise config before
# skipping it. Mise configs are typically <100KB. Default: 4194304 (4 MB).
# max_file_size: 4194304
mise_tasks:
# Scans mise file-task scripts under mise-tasks/, .mise-tasks/,
# mise/tasks/, .mise/tasks/, and .config/mise/tasks/ (at up to 3
# levels of sub-directory depth). Each script is line-scanned for
# plaintext secrets and its `#MISE env={...}` (or `# [MISE] env=`,
# `//MISE env=`) header directives are decoded as inline TOML and
# scanned the same way the config probe handles [env] tables.
# Findings are tagged `mise_task_file: true` and carry the derived
# task name (e.g. `test:units` for `mise-tasks/test/units`).
enabled: true
flags:
# max_file_size: maximum bytes to read from a mise file-task
# script before skipping it. Default: 4194304 (4 MB).
# max_file_size: 4194304
privacy:
redact_paths: []
exclude_env_prefixes: []
Expand Down
13 changes: 13 additions & 0 deletions cmd/bagel/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,5 +217,18 @@ func initializeProbes(cfg *models.Config) []probe.Probe {
probes = append(probes, probe.NewContextProbe(cfg.Probes.AIContext, registry))
}

// mise probe - plaintext secrets in mise.toml [env] tables and
// inline [tasks.*] blocks.
if cfg.Probes.Mise.Enabled {
probes = append(probes, probe.NewMiseProbe(cfg.Probes.Mise, registry))
}

// mise_tasks probe - plaintext secrets in file-task scripts
// under mise-tasks/, .mise-tasks/, mise/tasks/, .mise/tasks/,
// and .config/mise/tasks/.
if cfg.Probes.MiseTasks.Enabled {
probes = append(probes, probe.NewMiseTasksProbe(cfg.Probes.MiseTasks, registry))
}

return probes
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/google/uuid v1.6.0
github.com/mattn/go-isatty v0.0.20
github.com/olekukonko/tablewriter v1.1.0
github.com/pelletier/go-toml/v2 v2.2.4
github.com/rs/zerolog v1.34.0
github.com/schollz/progressbar/v3 v3.19.0
github.com/spf13/cobra v1.10.1
Expand All @@ -29,7 +30,6 @@ require (
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.0.9 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
Expand Down
75 changes: 75 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ func setDefaults(v *viper.Viper) {
v.SetDefault("probes.iac.enabled", true)
v.SetDefault("probes.ai_mcp.enabled", true)
v.SetDefault("probes.ai_context.enabled", true)
v.SetDefault("probes.mise.enabled", true)
v.SetDefault("probes.mise_tasks.enabled", true)
v.SetDefault("output.include_file_hashes", false)
v.SetDefault("output.include_file_content", false)

Expand Down Expand Up @@ -414,6 +416,79 @@ func setDefaults(v *viper.Viper) {
// macOS
"Library/Preferences/helm/repositories.yaml",
}, "type": "glob"},

// mise (https://mise.jdx.dev) - polyglot tool / version /
// env manager. The [env] table sets shell env vars and is a
// common landing site for plaintext tokens.
//
// Pattern set tracks `LOCAL_CONFIG_FILENAMES` in mise's
// src/config/mod.rs plus the env-specific variants enumerated
// in `DEFAULT_CONFIG_FILENAMES`. The probe classifies each
// matched file at runtime (global vs project, local-override,
// env-specific) based on its path and basename.
//
// `.rtx.*` are mise's legacy (pre-rename) names; mise still
// reads them, so we include them here.
{"name": "mise_config", "patterns": []string{
// Project-level basenames (match at any depth)
"mise.toml",
".mise.toml",
"mise.*.toml", // mise.local.toml, mise.production.toml, mise.production.local.toml
".mise.*.toml", // .mise.local.toml, .mise.production.toml, etc.
".rtx.toml",
".rtx.*.toml",
// Idiomatic-dir forms (Unix + project-nested copies)
"mise/config.toml",
"mise/config.*.toml",
".mise/config.toml",
".mise/config.*.toml",
".config/mise.toml",
".config/mise.*.toml",
".config/mise/config.toml",
".config/mise/config.*.toml",
".config/mise/mise.toml",
".config/mise/mise.*.toml",
".config/mise/conf.d/*.toml",
// Windows: %APPDATA%\mise\...
"AppData/Roaming/mise/config.toml",
"AppData/Roaming/mise/config.*.toml",
"AppData/Roaming/mise/conf.d/*.toml",
}, "type": "glob"},

// mise file-task scripts. Each entry is a directory whose
// files are the task scripts (shell, python, node, deno, ...).
// Sub-directories are valid — mise composes the task name
// from the path. We enumerate 1-3 levels deep, which covers
// the typical `mise-tasks/<category>/<subcategory>/<task>`
// shape; deeper nesting is unusual.
//
// Windows: the docs don't mention Windows-specific paths
// for file tasks. Since these are user-authored scripts
// kept inside repos, the Unix paths apply via WSL or as
// repo-relative paths on plain Windows too.
{"name": "mise_task_file", "patterns": []string{
// mise-tasks/
"mise-tasks/*",
"mise-tasks/*/*",
"mise-tasks/*/*/*",
// .mise-tasks/
".mise-tasks/*",
".mise-tasks/*/*",
".mise-tasks/*/*/*",
// mise/tasks/
"mise/tasks/*",
"mise/tasks/*/*",
"mise/tasks/*/*/*",
// .mise/tasks/
".mise/tasks/*",
".mise/tasks/*/*",
".mise/tasks/*/*/*",
// .config/mise/tasks/ (covers ~/.config/mise/tasks/ when
// the home dir is walked + project-nested copies)
".config/mise/tasks/*",
".config/mise/tasks/*/*",
".config/mise/tasks/*/*/*",
}, "type": "glob"},
})
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/models/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type ProbeConfig struct {
IaC ProbeSettings `yaml:"iac" mapstructure:"iac"`
AIMCP ProbeSettings `yaml:"ai_mcp" mapstructure:"ai_mcp"`
AIContext ProbeSettings `yaml:"ai_context" mapstructure:"ai_context"`
Mise ProbeSettings `yaml:"mise" mapstructure:"mise"`
MiseTasks ProbeSettings `yaml:"mise_tasks" mapstructure:"mise_tasks"`
}

// ProbeSettings contains settings for a specific probe
Expand Down
Loading