Skip to content

v0.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 23 Jul 14:00

[0.2.0] - Security hardening (pentest remediation)

Changed (upgrade impact)

  • A policy file with an unknown or misspelled key now fails to load instead of
    silently ignoring it. If you were relying on a key that was quietly dropped
    (e.g. a typo'd allow-endpoints), the run now errors until you correct it -
    this is intentional: a silently-ignored key meant the rule was never in effect.
  • The Action installer verifies the release signature when cosign is present.
    On a runner that already has cosign, a release whose SHA256SUMS.bundle
    signature doesn't verify is now rejected (fail closed). The new
    require-signature input additionally makes cosign's absence a hard failure.
  • The report directory may no longer be a symlink, and a local extends: ref
    may no longer resolve (via symlink or ..) outside the policy directory.

Security

  • Report artifacts are now tamper-resistant. report.json / .md / .sarif
    are written atomically (temp file + rename), and the build's descendants are
    reaped (the whole build cgroup in block mode, the command's process group in
    audit mode) BEFORE the report is written - so a process the build detaches can
    no longer race and overwrite the report that the SARIF upload, PR comment, and
    dashboard issue are generated from.
  • Report cells can no longer be forged via hostile filenames. mdEscape now
    strips CR/LF (and caps cell length), so a captured filename like
    evil\n\n## No violations can't inject fake rows/headers into the Markdown
    report or job summary.
  • Protected-path matching is canonicalized. File/process policy now resolves
    .. and symlinks on both sides before matching, closing the traversal and
    symlink-through bypasses. (Relative-path writes remain best-effort pending
    capture-time cwd resolution - documented in SECURITY.md.)
  • extends: is confined to the policy directory. A local extends ref can
    no longer escape its base directory via .., an absolute path, or a symlink
    (containment is enforced on the symlink-resolved real path), so a crafted policy
    can't pull an arbitrary local file in as its base - which on a root-privileged
    runner would be an arbitrary file read.
  • The report directory can't be a symlink. Egret refuses to write reports
    through a symlinked output-dir, so the monitored build can't swap the report
    directory for a symlink to an attacker-chosen location right before exiting.
  • Policy files are strict-decoded. An unknown or misspelled key (e.g.
    allow-endpoints) now fails fast instead of silently disabling the intended
    rule.
  • The DNS proxy refuses multi-question packets, closing a path where a denied
    name could ride along in a second question past the allowlist check.
  • The Action installer verifies the release cosign signature. When cosign
    is present, SHA256SUMS.bundle is verified (fail closed) before trusting the
    checksum; a new require-signature input makes its absence a hard failure.
  • CI/CD hardening: concurrency + per-job timeout-minutes across CI/Security
    workflows, zizmor tool-failure no longer hidden behind || true, and action.yml
    uses $GITHUB_ACTION_PATH instead of interpolating github.action_path into run:.

Documentation

  • SECURITY.md gains a "Trust boundaries and known limitations" section: the
    policy file is read from the checked-out ref (attacker-editable on
    pull_request unless loaded from the base branch), and file/process policy is
    best-effort detection, not an enforcement boundary.
  • Usage examples pin the Action to a commit SHA (floating tags noted as the
    convenience alternative).