microsoft / microsoft/hve-core
Run a full Poutine scan of main and address findings
@WilliamBerryiii is already working on this.
Since Jul 28, 2026.
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 301
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 92
Description
## Context
Poutine runs today only via `pr-validation.yml`, which triggers on `pull_request` and `workflow_dispatch` — never on `push` to `main`. It therefore only ever analyzes PR merge refs, and its findings live and die with the PR.
Consequence: we have **no standing Poutine coverage of `main`**. Anything already merged has never been scanned. At time of writing, `main` has 3 open code scanning alerts, all from Scorecard, and zero from Poutine — not because `main` is clean, but because Poutine has never looked at it.
This was discovered while triaging code scanning alert #348 (`default_permissions_on_risky_events` on `.github/workflows/pr-review.lock.yml`), which was dismissed as a false positive: that file declares workflow-level `permissions: {}` (zero scopes) inherited by every job, but Poutine's `utils.empty()` helper cannot distinguish an empty permissions map from an absent one.
## Scope
1. Run a full Poutine scan against `main` (`poutine analyze_local .` or a one-off `workflow_dispatch` run) and capture the complete finding set.
2. Triage each finding: genuine issue, false positive, or accepted risk.
3. Address genuine findings in a follow-up PR.
4. Record false positives as scoped `skip` entries in `.poutine.yml` with written justification, or dismiss with a documented reason.
5. Decide whether Poutine should gain standing coverage of `main` — e.g. a scheduled run in `weekly-security-maintenance.yml` — so findings on merged code surface without waiting for an unrelated PR to touch them.
## Notes
- Poutine is advisory by design here: `poutine-soft-fail: true` is set in `pr-validation.yml`, so it cannot block a merge. The homegrown template-injection gate remains the only hard gate. See [docs/security/dangerous-workflow-detection.md](docs/security/dangerous-workflow-detection.md).
- The action is SHA-pinned (`boostsecurityio/poutine-action@e240ebd3eff8b2db5a8e5f6b28f58739d7db2247`, v1.1.4), so the rule set only changes when that pin is bumped.
- `skip` entries in `.poutine.yml` match on fields the rule actually emits. `default_permissions_on_risky_events` emits only `path` and `event_triggers` — not `job` — so suppression for that rule cannot be scoped narrower than an entire file. Prefer fixing or dismissing over broad skips.
## Related follow-up
`scripts/security/Test-WorkflowPermissions.ps1` currently only greps for a top-level `^permissions:` block, so it scores 100% while individual jobs carry no declaration. Teaching it to walk jobs — and to distinguish workflow-level `{}` (provably zero) from an absent block (inherits repo/org defaults) — would enforce the job-level convention in `.github/instructions/workflows.instructions.md` as a hard gate. Worth pairing with this work or splitting into its own issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.