theam / theam/facility

Agent triggers do work for senders without write access: refused requests still provision, and prose fails the run

Open
#218 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
71
Forks
64
Avg merge
15h 38m
Merged PRs (30d)
66

Description

Summary

Two defects in the Resolve requested agent step region of facility-crew.yml and
facility-codex.yml. Both let a GitHub account with read permission only cause work on a
public repository that has Facility's repo lane installed.

  1. A refused request still checks out the repository and installs dependencies. The job reports
    success.
  2. A comment that merely mentions a command fails the run before the permission gate is
    consulted. The job reports failure.

The authorization gate itself is correct and does refuse the request. The problem is what
happens around it.

1. A refused request still provisions, and reports success

The toolchain steps rendered by {{TOOLCHAIN_STEPS}} carry no if:, while the steps on either
side of them do:

      - name: Start agent receipt clock
        if: steps.requested-agent.outputs.run == 'true'      # guarded
        ...
      - uses: pnpm/action-setup@…                            # NOT guarded
      - uses: actions/setup-node@…                           # NOT guarded
      - run: pnpm install --frozen-lockfile                  # NOT guarded

      - name: Provision environment
        if: steps.requested-agent.outputs.run == 'true'      # guarded

actions/checkout in facility-crew.yml is likewise unguarded.

An account with read commented /architect. The gate refused it, and the job then did the
work anyway:

##[warning]Skipping crew: @cdottaaux has repository permission 'read',
          but /builder and /architect require write access.
...
Run pnpm/action-setup            → Done in 749ms
Run pnpm install --frozen-lockfile → Progress: resolved …

Step outcomes for that run:

job: success
  success  Resolve requested agent
  success  Run actions/checkout@…
  skipped  Start agent receipt clock
  success  Run pnpm/action-setup@…
  success  Run actions/setup-node@…
  success  Run pnpm install --frozen-lockfile
  skipped  Provision environment
  skipped  Run /builder
  skipped  Run /architect

Run: https://github.com/cdotta/remote-mcp-starter/actions/runs/33229949990

No agent runs and no model spend occurs, which is the important boundary and it holds. But any
account on the internet can trigger a full checkout, toolchain setup, and dependency install on
demand, repeatedly, and every one of those runs is green. On a repository with a real provision
command the same path would also execute that command — for a request that was explicitly
refused.

facility-codex.yml guards its checkout but not its toolchain block, so the same event fails
instead: no checkout means no package.json, and pnpm/action-setup dies with
Error: No pnpm version is specified.
Run: https://github.com/cdotta/remote-mcp-starter/actions/runs/33229801124

2. Command-shape validation runs before the permission gate

In facility-crew.yml the resolve step validates shape first and exits non-zero:

  • line 110 — ::error::No supported agent command found.exit 1
  • line 160 — gh api …/collaborators/$sender/permission

Fifty lines apart, in that order. The job-level prefilter matches /architect anywhere in a
comment body, so any sender reaches this step. The same read-only account commented
ask /architect about it before you start:

##[error]No supported agent command found. Use /builder or /architect at the start of a line.
##[error]Process completed with exit code 1.

Run: https://github.com/cdotta/remote-mcp-starter/actions/runs/33229955947

This also affects maintainers: writing about the commands in an issue turns the repository's
checks red. The step's own comment says the line-anchored pattern "ignores prose examples
(ask /architect about it)"
— it does ignore them for dispatch, but the run still fails loudly
rather than skipping.

facility-codex.yml already handles this case the way I would expect:

##[notice]No Codex command starts a line; treating the mention as prose.

so the two sibling workflows disagree about identical input. That is what makes this look like
an oversight rather than a deliberate choice.

Suggested direction

Two independent changes, and I would value your view before opening a PR — the second is more
opinionated than the first:

  1. Guard the toolchain and checkout steps on the resolve step's run output, so a refused
    or skipped request does no work. toolchainSteps() already takes a conditional option, but
    it guards on steps.workflow-change.outputs.changed, so it is not a drop-in; the crew and
    codex lanes need a guard on their own resolve output.

  2. Move the authorization gate above the command-shape checks, and make "no command at the
    start of a line" a run=false skip rather than exit 1 — matching what facility-codex.yml
    already does. Then no sender without write access can produce a red run regardless of what
    they type. The genuinely ambiguous case (both /builder and /architect line-anchored from
    an authorized user) can stay a hard error.

I have both changes written with tests that execute the rendered workflow rather than asserting
on its text, and can open a PR if you want them.

Environment

  • Facility main @ ca1c9df, repo lane installed via facility init
  • Public repository, GitHub-hosted ubuntu-latest
  • Workflows byte-identical to what init generated, except for the block-scalar fix from issue A
    (without it neither workflow parses at all)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Resolve requested agent regions in facility-crew.yml and facility-codex.yml, then inspect toolchainSteps() and the rendered-workflow tests mentioned in the issue. Verify refused requests skip checkout, toolchain setup, and dependency installation, while prose mentions skip without failing; authorized ambiguous commands should retain their existing hard error.

Written by the indexing model from the issue text.

Assessment

Tech stack
github-actions
Domain
ci-cd
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.