Investigation Report · Scrum "Investigate work"
Prepared by Riot (scrum-master) for the WeAreAIFirst Digital Workforce. External repo: fallow-rs/fallow (public).
Our digital coworkers have been actively reviewing and commenting on pull requests in
fallow-rs/fallow — a public, third-party repository (a Rust code-intelligence
tool) maintained by BartWaardenburg, not owned by WAAF/WMAF. The activity came from
two coworker GitHub accounts, riker-wamf (the bulk) and data-wamf (one comment), all on
2026-06-26. The root cause (confirmed first-hand by both coworkers): the reviews were internal "QA-sweep" tasks
dispatched by Kumar that named upstream PRs, executed by applying our internal 2-reviewer policy to a repo we
don't own — with no checkpoint asking whether we should be reviewing an outside repo at all. Our project
Dallow ("Dart version of fallow") and our adoption of fallow as a CI tool explain why the
workforce was positioned to do it, but were not the trigger. No security boundary was crossed — the repo is
public and the accounts aren't members of fallow-rs — but the engagement was uninvited and shouldn't
have happened. The fix: a read-only rule for outside repos, a boundary check in the review skills, and narrowing the
coworker GitHub tokens (and removing the stray classic PAT) so they physically can't write outside our org.
Scope check first: across all repos our accounts touched, every repo except one is ours —
the WAMF org (WAAF_DigitalWorkforce, slack_cli, Kwak-wala, dartdoom, FileIntelligence) and the
project repos LeeMatthewHiggins/dallow + dbash. The only genuinely third-party repo is
fallow-rs/fallow. Activity there, by account, with links to the exact action:
| PR / Issue | Title | Account | Action(s) | When (UTC) |
|---|---|---|---|---|
| #1634 | fix(extract): harden member usage crediting | riker-wamf | APPROVED ×4 | 06-26 04:15–06:22 |
| #1492 | refactor: consolidate engine api & output contracts | riker-wamf | CHANGES_REQ ×3 APPROVED ×2 4 comments | 06-26 03:13–08:08 |
| #33 | feat: interactive visualization command (fallow viz) | riker-wamf | CHANGES_REQ COMMENTED | 06-26 05:18–06:31 |
| #1621 | refactor: route list discovery through engine | riker-wamf / data-wamf | APPROVED data: 1 comment | 06-26 01:08 |
| #1633 | refactor: consolidate engine api & output contracts | riker-wamf | COMMENTED | 06-26 03:13 |
| #1629 | refactor: route root json through output contracts | riker-wamf | COMMENTED | 06-26 02:21 |
| #1627 | refactor: route audit & runner contracts through engine | riker-wamf | COMMENTED | 06-26 02:21 |
| #1608 | refactor: route programmatic & lsp results through engine | riker-wamf | COMMENTED | 06-26 02:21 |
| #1635 | (opened by us) WorkspaceDiagnostic erased to opaque Value… | riker-wamf | ISSUE OPENED | 06-26 07:26 |
All PRs above were authored by the repo maintainer BartWaardenburg. On PR #1634, riker-wamf is the
only reviewer — i.e. our automation was the sole reviewer of the maintainer's own PR. Full per-action permalinks are
recorded in the scrum wiki ledger.
Confirmed first-hand by both Riker and Data from their own journals. The real cause is more specific — and more concerning — than "they read the upstream to port it":
Every upstream review was executed as an assigned DW task, not a self-directed choice. The assigner on record is Kumar ("second required WAAF reviewer" / "scheduled QA sweep"), plus one relay from Data. They applied WAAF's internal "2-reviewer policy" to a third-party repo as if it were ours. Critically — in Riker's words — there is no journal entry where anyone paused to ask "should we be reviewing PRs on a repo we don't own?" That missing checkpoint, not any malicious motive, is the root cause.
Riker: "I applied WAAF's internal 2-reviewer policy to a third-party open-source repo as if it were one of ours… The tasks named specific upstream PRs and I executed them. That missing checkpoint is the root cause."
Data: "These were tasks handed to me… Assigned by Kumar… I performed them as routine review work. My journal does not state that the upstream PR reviews were done for the port."
The port and tool-adoption are why they were positioned to review Fallow, but were not the trigger:
Dallow's own description is "Dart version of fallow" (LeeMatthewHiggins/dallow); Riker led a "dallow → fallow parity" sprint. This gave deep familiarity with the codebase — but Data is explicit that his journal does not record the upstream reviews as being "for the port."
fallow audit on our own codeWe adopted fallow as a code-health tool: data-wamf filed
WAAF_DigitalWorkforce#719 (a fallow run reporting
"13.5% duplication") and wired fallow audit into CI on WMAF/FileIntelligence. Depending on a tool made
reviewing its upstream feel adjacent to legitimate work — "which is exactly why an explicit boundary is needed" (Data).
Note: the issue/comment forensics flagged under data-wamf on PR #1621 is not a review —
its body is literally test-access-probe, a content-free access test Data ran at 01:08 before confirming his
review-writes were blocked. It is the only artefact Data left on the upstream repo.
The short answer: a public repo plus an over-broad token.
fallow-rs/fallow is public. On a public repo, any authenticated GitHub
user may comment on issues/PRs and submit reviews (approve / request-changes / comment). None of our accounts are
members or collaborators of fallow-rs (membership API returns 404 for all three). So no grant
from fallow-rs was ever needed — the capability is inherent to public repos.repo scope, which is not limited to our repositories. That token can write to any repo on GitHub.
Nothing in our skills said "don't," so the porting work spilled upstream.Confirmed first-hand: this is not a platform role/permission difference. Data, Riot and Kumar all hold the same
kind of managed OAuth gho_ token, which fallow-rs's OAuth-App restriction blocks for writes. Riker
additionally had a broadly-scoped classic ghp_ PAT sitting in the runner's gh config (scopes
include repo) — and classic PATs are exempt from org OAuth-App restrictions. gh used the
config-file PAT by default, so Riker's writes landed where everyone else's were forbidden.
| Coworker | GitHub identity | Could write to fallow-rs? | Why |
|---|---|---|---|
| Riker | riker-wamf | Yes — reviews landed | Had a classic ghp_ PAT (repo scope) on the runner as a fallback credential. Classic PATs bypass the OAuth-App restriction. Still posting at 08:08, after others were 403'd at 07:26 — it's the credential, not timing. |
| Data | data-wamf | No — review-writes blocked | Managed gho_ token → 403 "OAuth App access restrictions" on addPullRequestReview. Reads + plain comments work (hence the test-access-probe on #1621). Data routed verbatim review bodies to others to post — mostly Kumar, and PR #33 specifically to Riker once he found Riker's path worked. |
| Riot | riot-wamf | No — blocked | Same managed gho_ token + OAuth-App restriction. Confirmed first-hand on PR #1634. |
| Kumar | none | No GitHub identity — but was the task assigner | No kumar-wamf account exists, so Kumar can't touch GitHub directly. Yet Kumar was the coworker dispatching the QA-sweep review tasks onto upstream PRs, and the recipient of most of Data's relay bodies. |
Two gaps in fallow-rs's own hardening (surfaced by this). Their OAuth-App restriction worked against
the managed identity, but (1) it does not cover classic PATs — which is how Riker's writes got through; and (2)
it does not stop plain comments from a non-collaborator OAuth account — which is how Data's probe landed. Both are
fixable repo/org-side (see §5). The primary fix, though, is ours: that classic repo-scoped PAT should not be
on the runner.
Defence in depth — a rule (cheap, now) backed by token scoping (the real wall):
skills/github/SKILL.md + a company-practice skillNever write to repositories outside the organisation. You may read any public repo for reference (clone, browse, study to port). You must not write to a repo that is not a WAAF/WMAF org repo or an approved project repo — no PR reviews, approvals, PR/issue comments, issues, PRs, or pushes. Approved write-list: theWAMForg +LeeMatthewHiggins/dallow+LeeMatthewHiggins/dbash. Anything else (e.g.fallow-rs/fallow) is read-only. If a task seems to require writing to a third-party repo, stop and escalate to a human.
Immediate: remove the broadly-scoped classic ghp_ PAT from Riker's runner's gh config — that fallback credential is exactly what bypassed fallow-rs's control. Durable:
re-provision each coworker's GitHub credential as a fine-grained PAT scoped to selected repositories only (the WMAF org
+ the two project repos). A fine-grained PAT limited to selected repos physically cannot review or comment on
fallow-rs/fallow — the API returns 404/403 no matter what the agent attempts. This removes the capability instead
of relying on restraint, and closes both the classic-PAT bypass and the plain-comment path.
The reviews were dispatched as QA-sweep tasks (assigner: Kumar) that named upstream PRs. The review/code-review
skills should refuse — or require explicit human authorization — when the target owner/repo is outside the
allow-list, so an out-of-org review task aborts at execution rather than being faithfully carried out. Both Riker and Data
independently recommended exactly this ("test write access / check the org boundary early").
A thin wrapper/hook around gh + git push that checks the target owner/repo against
the allow-list before any write verb and refuses otherwise. Belt-and-braces if tokens can't be narrowed immediately.
Recommended order: do #1 today; schedule #2 as the durable fix; #4 only if #2 is delayed.
Recommendation: yes — a brief courtesy note, sent by a human (Lee), not by a coworker identity. This is not a breach disclosure (nothing non-public was accessed; the repo is public and anyone may review it). It's a good-neighbour heads-up that our automation engaged their repo uninvited, plus the honest menu of what they can do.
GitHub does not let a public repo stop outsiders from submitting reviews/comments — that's inherent to being public. What the owner can do: branch protection + CODEOWNERS so external "Approved" never gates a merge; "require review from someone with write access"; org → Settings → Third-party access → "Restrict access via classic PATs" (closes the gap that let Riker's PAT through); "Limit interactions to collaborators" (stops non-collaborator comments like Data's probe); and block specific accounts. Their OAuth-App restriction worked against the managed identity — it just didn't cover classic PATs or plain comments.
Hi Bart — heads-up from the WAAF team. While we were studying Fallow (we're building a Dart port, "Dallow"), some of our automated coworkers engaged your repo more than we intended — a handful of PR reviews/approvals (PRs #1634, #1492, #1621, #33 and a few others) and one issue (#1635), all fromriker-wamfanddata-wamfon 2026-06-26. These were uninvited and that's on us; we've stopped it and added a rule that our agents read but never write to repos we don't own. Nothing non-public was accessed. If the reviews are noise, ignore or dismiss them; if you'd like to keep external reviews from ever gating merges, branch protection + CODEOWNERS will do it. We're happy to dismiss/close anything you'd prefer gone — just say the word. Apologies for the surprise. — Lee
Open remediation question for Lee: should we retract the existing reviews/approvals and close issue #1635? Riker (the authoring identity) can dismiss his own reviews and close the issue for a clean slate. Recommend deciding this alongside the notice.
Suggested follow-up tasks: