Skip to content

docs(security): document zizmor.yml disabled-rule rationale and audit if any can be re-enabled #184

@devantler

Description

@devantler

🤖 Generated by the Daily AI Assistant

Part of #181.

Problem

zizmor.yml disables three security rules with no explanation:

rules:
  unpinned-uses:
    config:
      policies:
        actions/*: any
        github/*: any
        devantler-tech/*: any
        "*": hash-pin
  excessive-permissions:
    disable: true
  secrets-inherit:
    disable: true
  secrets-outside-env:
    disable: true

Each disablement is wholesale rather than per-job, and the reasoning isn't captured anywhere — not in the file, not in AGENTS.md, not in commit history of zizmor.yml. The file lives in a CI building-block library that every downstream repo transitively inherits the philosophy of (these are the same rules our consumers will or won't enable for their workflows). Two operational risks:

  1. Drift over time. Whoever set the disablements knew why; six months from now, a contributor (human or AI) reading zizmor.yml cannot tell whether each is a deliberate, defensible trade-off or a leftover from an early-days workaround that no longer applies.
  2. Re-enable opportunities go unsurveyed. As the library has matured (per-job permissions are now explicitly scoped in ci.yaml, secrets passing has been audited during the agent-skills rename), one or more of these may now be safe to re-enable, possibly with a narrow per-workflow override list instead of a global disable.

Proposed direction

Two-part change in one focused PR:

  1. Document each disablement in-line in zizmor.yml with a one-sentence rationale + a pointer to the workflow / step that motivates it. Example shape (illustrative — actual rationale must come from auditing the live workflows):

    # excessive-permissions: disabled wholesale because the test workflows in
    # ci.yaml legitimately request `pull-requests: write` (test-approve-pr),
    # `issues: write` (test-create-issues-from-todos, test-upsert-issue), and
    # `code-quality: write` (test-run-dotnet-tests, test-upload-coverage).
    # Per-job overrides would be longer than this comment without changing
    # anything — see ci.yaml for the actual permission grants which are
    # already minimal per job.
    excessive-permissions:
      disable: true
  2. Audit whether any disabled rule can now be re-enabled — possibly with a per-workflow ignore list — and either re-enable in the same PR (if low risk) or recommend in the PR body, deferring to a follow-up.

Acceptance criteria

  • Each of the three disablements in zizmor.yml carries a comment explaining the rationale, written against the live state of the workflows.
  • PR body documents whether each rule was re-enabled, kept-disabled-with-rationale, or recommended-to-revisit-as-follow-up.
  • zizmor still passes (🔒 Run zizmor job in CI).
  • If any rule is re-enabled, the recommendation is justified by reading the actual workflow files — not generic security best-practice text.

Out of scope

  • Tightening the unpinned-uses policy (the actions/* / github/* / devantler-tech/* any carve-outs are already a deliberate, sensible choice for first-party / verified-publisher actions).
  • Adding step-security harden-runner audit / audit-log egress-policy hardening — that's a separate hardening pass against the workflows themselves, not the zizmor config.
  • Migrating to a different scanner.

Labels

documentation + security (the change is documentation-led but security-meaningful).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions