Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions .github/workflows/probe-cross-repo-token.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Throwaway probe (#238 Phase 0): can a workflow GITHUB_TOKEN read ANOTHER
# repository's Actions/Checks data when that repository is public?
#
# GitHub's docs never join the two axes this sits on. The installation-token
# side says the token is "limited to the repository that contains your
# workflow" and "cannot be granted access to repositories that the
# installation was not granted access to"; the endpoint side says each of
# these endpoints "can be used without authentication ... if only public
# resources are requested". Nothing states the evaluation order, so #238's
# receiver-side polling architecture rests on an unverified premise.
#
# A bare 200 is confounded: public Actions data is world-readable, so a 200
# alone cannot distinguish "the token authorized me" from "the token was
# ignored". Hence four arms, with a private-repo discriminator.
#
# Also captures x-ratelimit-remaining across two target repos, to settle
# whether the 1,000 req/hr bucket is per-workflow-repo or per-target-repo.
#
# Closed unmerged; deleted with the probe branch.
name: probe-cross-repo-token

on:
pull_request:
types: [opened, synchronize]

permissions: {}

jobs:
no-permissions:
name: GITHUB_TOKEN with permissions {}
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions: {}
steps:
- name: Probe cross-repo reads
shell: bash
env:
PROBE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -uo pipefail

BASE=https://api.github.com/repos/melodic-software
Q='actions/runs?per_page=1'

probe() {
local label="$1" auth="$2" url="$3"
local hdrs body code
hdrs="$(mktemp)"
body="$(mktemp)"
if [ "$auth" = yes ]; then
code="$(curl -sS -o "$body" -D "$hdrs" -w '%{http_code}' \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
-H "Authorization: Bearer ${PROBE_TOKEN}" \
"$url")" || code=curl-error
else
code="$(curl -sS -o "$body" -D "$hdrs" -w '%{http_code}' \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"$url")" || code=curl-error
fi
echo "=== ${label}"
echo " auth=${auth} http=${code}"
grep -iE '^(x-ratelimit-(limit|remaining|used|resource)|x-accepted-github-permissions):' \
"$hdrs" | tr -d '\r' | sed 's/^/ /' || true
if [ "$code" != 200 ]; then
echo " body: $(head -c 200 "$body" | tr -d '\n')" || true
fi
rm -f "$hdrs" "$body"
}

probe "ARM A unauth -> PUBLIC claude-code-plugins" no "${BASE}/claude-code-plugins/${Q}"
probe "ARM B GITHUB_TOKEN -> PUBLIC claude-code-plugins" yes "${BASE}/claude-code-plugins/${Q}"
probe "ARM B2 GITHUB_TOKEN -> PUBLIC standards" yes "${BASE}/standards/${Q}"
probe "ARM C GITHUB_TOKEN -> PRIVATE medley" yes "${BASE}/medley/${Q}"
probe "ARM D GITHUB_TOKEN -> OWN ci-workflows" yes "${BASE}/ci-workflows/${Q}"

echo "=== ARM E full detection chain -> PUBLIC claude-code-plugins"
RUN_ID="$(curl -sS \
-H 'Accept: application/vnd.github+json' \
-H "Authorization: Bearer ${PROBE_TOKEN}" \
"${BASE}/claude-code-plugins/${Q}" | jq -r '.workflow_runs[0].id // empty')" || true
echo " run_id=${RUN_ID:-<none>}"
if [ -n "${RUN_ID:-}" ]; then
CR_URL="$(curl -sS \
-H 'Accept: application/vnd.github+json' \
-H "Authorization: Bearer ${PROBE_TOKEN}" \
"${BASE}/claude-code-plugins/actions/runs/${RUN_ID}/jobs" \
| jq -r '.jobs[0].check_run_url // empty')" || true
echo " check_run_url=${CR_URL:-<none>}"
if [ -n "${CR_URL:-}" ]; then
probe "ARM E GITHUB_TOKEN -> PUBLIC check-run annotations" yes "${CR_URL}/annotations"
fi
fi

actions-checks-read:
name: GITHUB_TOKEN with actions+checks read
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
actions: read
checks: read
steps:
- name: Probe cross-repo reads
shell: bash
env:
PROBE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -uo pipefail

BASE=https://api.github.com/repos/melodic-software
Q='actions/runs?per_page=1'

probe() {
local label="$1" auth="$2" url="$3"
local hdrs body code
hdrs="$(mktemp)"
body="$(mktemp)"
if [ "$auth" = yes ]; then
code="$(curl -sS -o "$body" -D "$hdrs" -w '%{http_code}' \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
-H "Authorization: Bearer ${PROBE_TOKEN}" \
"$url")" || code=curl-error
else
code="$(curl -sS -o "$body" -D "$hdrs" -w '%{http_code}' \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"$url")" || code=curl-error
fi
echo "=== ${label}"
echo " auth=${auth} http=${code}"
grep -iE '^(x-ratelimit-(limit|remaining|used|resource)|x-accepted-github-permissions):' \
"$hdrs" | tr -d '\r' | sed 's/^/ /' || true
if [ "$code" != 200 ]; then
echo " body: $(head -c 200 "$body" | tr -d '\n')" || true
fi
rm -f "$hdrs" "$body"
}

probe "ARM A unauth -> PUBLIC claude-code-plugins" no "${BASE}/claude-code-plugins/${Q}"
probe "ARM B GITHUB_TOKEN -> PUBLIC claude-code-plugins" yes "${BASE}/claude-code-plugins/${Q}"
probe "ARM B2 GITHUB_TOKEN -> PUBLIC standards" yes "${BASE}/standards/${Q}"
probe "ARM C GITHUB_TOKEN -> PRIVATE medley" yes "${BASE}/medley/${Q}"
probe "ARM D GITHUB_TOKEN -> OWN ci-workflows" yes "${BASE}/ci-workflows/${Q}"

echo "=== ARM E full detection chain -> PUBLIC claude-code-plugins"
RUN_ID="$(curl -sS \
-H 'Accept: application/vnd.github+json' \
-H "Authorization: Bearer ${PROBE_TOKEN}" \
"${BASE}/claude-code-plugins/${Q}" | jq -r '.workflow_runs[0].id // empty')" || true
echo " run_id=${RUN_ID:-<none>}"
if [ -n "${RUN_ID:-}" ]; then
CR_URL="$(curl -sS \
-H 'Accept: application/vnd.github+json' \
-H "Authorization: Bearer ${PROBE_TOKEN}" \
"${BASE}/claude-code-plugins/actions/runs/${RUN_ID}/jobs" \
| jq -r '.jobs[0].check_run_url // empty')" || true
echo " check_run_url=${CR_URL:-<none>}"
if [ -n "${CR_URL:-}" ]; then
probe "ARM E GITHUB_TOKEN -> PUBLIC check-run annotations" yes "${CR_URL}/annotations"
fi
fi
Loading