@@ -47,20 +47,31 @@ concurrency:
4747jobs :
4848 # Which Windows runner this run is allowed to use.
4949 #
50- # The self-hosted Windows box is a maintainer's PERSONAL machine on a home
51- # network, reachable over Tailscale. Anything that runs on it runs as a local
52- # user with that user's filesystem and LAN in reach, so the only question that
53- # matters is whether the commit is trusted BEFORE a runner ever sees it.
50+ # READ THIS BEFORE TREATING IT AS A SECURITY BOUNDARY: it is not one.
5451 #
55- # `push` on dev/main/preview is trusted: reaching those branches requires the
56- # push permission, which only the maintainers in MAINTAINERS.md hold.
57- # `pull_request` is NOT trusted, and no author check can make it so — the
58- # workflow file itself comes from the PR head, so any `if:` guard written here
59- # is deleted by the same patch it is meant to stop. Fork PRs therefore stay on
60- # GitHub-hosted runners, unconditionally.
52+ # On `pull_request` this workflow is loaded from the PR head, so the `case`
53+ # below is owned by the proposed patch exactly like an `if:` guard would be.
54+ # A hostile PR can delete the branch and hardcode the self-hosted labels into
55+ # `$GITHUB_OUTPUT`, and `runs-on` will honour it. That this job runs on
56+ # `ubuntu-latest` changes nothing — the untrusted part is its OUTPUT, not its
57+ # host. `.github/workflows/ci.yml` is in this workflow's `pull_request.paths`,
58+ # so such an edit triggers its own run.
6159 #
62- # `workflow_dispatch` is the maintainer escape hatch: dispatch requires write
63- # access, so a maintainer can deliberately aim a branch at the home box.
60+ # What actually keeps untrusted code off a self-hosted runner lives OUTSIDE
61+ # this file, where a PR cannot reach it: the fork-PR approval policy
62+ # (`all_external_contributors`) and the judgement of whoever clicks approve.
63+ # Runner groups would be the other lever, but they are an organisation
64+ # feature and this repository is user-owned, so the approval policy is the
65+ # only one available here. GitHub's own guidance is to avoid self-hosted
66+ # runners on public repositories for this reason.
67+ #
68+ # So read the routing below as a COST control that keeps honest pull requests
69+ # on GitHub-hosted runners, not as a guarantee about hostile ones.
70+ #
71+ # `push` on dev/main/preview requires the push permission, and
72+ # `workflow_dispatch` requires write access, so both carry a trusted author.
73+ # A trusted author is not audited code: merging a contributor PR into `dev`
74+ # fires `push`, and its dependencies and postinstall hooks then run here.
6475 select-windows-runner :
6576 name : select windows runner
6677 runs-on : ubuntu-latest
@@ -85,10 +96,12 @@ jobs:
8596 push|workflow_dispatch) trusted=yes ;;
8697 esac
8798
88- # Repository variable OCX_SELF_HOSTED_WINDOWS acts as a kill switch. When
89- # it is anything other than `1` — including unset, which is the state
90- # before the runner exists — every job falls back to windows-latest and
91- # CI keeps working with the box powered off.
99+ # Repository variable OCX_SELF_HOSTED_WINDOWS is an OPERATIONAL switch,
100+ # not a security control: a PR that rewrites this script ignores it for
101+ # the same reason it ignores the event check above. Its job is to keep CI
102+ # working when the box is off or busy. Anything other than `1` —
103+ # including unset, the state before a runner exists — falls back to
104+ # windows-latest.
92105 if [ "$trusted" = "yes" ] && [ "${USE_SELF_HOSTED:-}" = "1" ]; then
93106 echo 'runner=["self-hosted","Windows","X64","ocx-home"]' >> "$GITHUB_OUTPUT"
94107 echo 'label=self-hosted (ocx-home)' >> "$GITHUB_OUTPUT"
0 commit comments