-
Notifications
You must be signed in to change notification settings - Fork 18
108 lines (99 loc) · 5.11 KB
/
Copy pathformat-suggest.yaml
File metadata and controls
108 lines (99 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# Workflow derived from https://github.com/posit-dev/setup-air/tree/main/examples
on:
# We keep `pull_request_target` (rather than `pull_request`) so that this job
# can post review suggestions on pull requests that come from forks, which is
# our main use case. A fork's `pull_request` run only gets a read-only token,
# so it cannot comment; `pull_request_target` runs with the base repository's
# token and can be granted `pull-requests: write`.
#
# SECURITY -- this is a classic "pwn request" surface, so the fork's code is
# treated strictly as *data to be formatted*, never as code to run:
#
# 1. The formatter tooling (the `style` action and the air / clang-format
# binaries) is never loaded from the PR checkout. This is the critical
# point. The naive pattern
# - uses: actions/checkout@v6 # ref: fork head
# - uses: ./.github/workflows/style
# resolves `./...style` from the *checked-out fork*, so an attacker only
# has to edit their fork's `style/action.yml` to run arbitrary commands
# with our token and secrets. A `owner/repo/path@ref` reference is
# fetched from that repository instead of from the workspace, so the
# fork controls only the input files, not the code that executes.
# 2. air and clang-format merely parse and re-print source; they do not
# evaluate it. No build / install / test step ever runs the fork's code.
# 3. The PR is checked out with `persist-credentials: false`, so the token
# is not written to disk alongside untrusted files.
# 4. Permissions are reduced to `pull-requests: write` only, and
# `harden-runner` observes (and can block) network egress.
#
# https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
# https://gh.io/securely-using-pull_request_target
pull_request_target:
name: format-suggest.yaml
# Deny everything by default; the job below opts back into the single scope it
# needs. This caps the blast radius of the elevated `pull_request_target` token.
permissions: {}
jobs:
format-suggest:
name: format-suggest
runs-on: ubuntu-26.04
timeout-minutes: 15 # longest run seen: 1 min
# Only run this job if changes come from a fork.
# We commit changes directly on the main repository.
if: github.event.pull_request.head.repo.full_name != github.repository
permissions:
# Required to push suggestion comments to the PR
pull-requests: write
steps:
# Defense in depth: block all outbound network traffic except the
# endpoints the formatters legitimately need. Even if a formatter ever
# mishandled attacker-controlled input, it could not exfiltrate the token
# or fetch a second-stage payload.
#
# The GitHub endpoints below were confirmed from a harden-runner `audit`
# run of this workflow (git checkout, setup-air / reviewdog binary
# downloads, reviewdog posting via the API). The apt.llvm.org / Ubuntu
# archive endpoints are only hit when a package ships a `.clang-format`
# file and the `style` action installs clang-format; they are included so
# C++ consumers of this template are not broken, even though a pure-R
# package never contacts them.
#
# If a run is ever blocked, harden-runner reports the denied endpoint in
# the job's "Harden Runner" step summary (and the StepSecurity insights
# for the run) -- add it here and re-run. See the note in the PR for the
# audit -> block workflow.
- name: Harden runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2
with:
egress-policy: block
allowed-endpoints: >
github.com:443
api.github.com:443
release-assets.githubusercontent.com:443
objects.githubusercontent.com:443
codeload.github.com:443
apt.llvm.org:443
azure.archive.ubuntu.com:80
# The untrusted PR code, checked out at the workspace root. It is DATA
# only -- nothing below executes it. `allow-unsafe-pr-checkout` is required
# by actions/checkout@v6 for a fork ref under pull_request_target; it is
# safe here specifically because the code that runs is fetched from
# `cynkra/cynkratemplate`, never from this checkout. See the notes above.
- name: Check out PR code (treated as data)
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
allow-unsafe-pr-checkout: true
# Runs the trusted `style` action against the PR code at the workspace
# root. Because the action is fetched from `cynkra/cynkratemplate` rather
# than resolved out of the workspace, the fork controls only the files
# being formatted, not the code that runs.
- name: Format
uses: cynkra/cynkratemplate/.github/actions/style@main
- name: Suggest
uses: reviewdog/action-suggester@2558ba17e65a9039e73764a73009fc05fef28a46 # v1
with:
level: error
fail_level: error
tool_name: air-and-clang-format