Enable Factory Droid @droid tag responses#189
Conversation
Contributor License AgreementAll contributors are covered by a CLA. |
|
Droid finished @HeyGarrison's task —— View job The workflow change is small and aligns with enabling @droid responses, but it would benefit from hardening: restrict triggering to trusted sources to avoid noisy failing runs and potential re-triggers from untrusted issue/PR bodies, and pin the third-party action to a commit SHA since it runs with secrets and write permissions. |
| if: | | ||
| (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@droid')) || | ||
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@droid')) || | ||
| (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@droid')) || | ||
| (github.event_name == 'issues' && (contains(github.event.issue.body, '@droid') || contains(github.event.issue.title, '@droid'))) || | ||
| (github.event_name == 'pull_request' && (contains(github.event.pull_request.body, '@droid') || contains(github.event.pull_request.title, '@droid'))) |
There was a problem hiding this comment.
[P1] Gate @droid runs to avoid noisy failures and wasted CI
As written, any issue/PR comment (or issue/PR body) containing @droid will start the workflow even when the mention comes from an untrusted source, which can lead to avoidable failing runs (the action later rejects non-write actors) and, for issues/pull_request events, can allow an untrusted @droid mention in the entity body to be re-triggered later by a maintainer action like assignment; also, coercing *.body/*.title to '' avoids potential expression errors when those fields are null.
| if: | | |
| (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@droid')) || | |
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@droid')) || | |
| (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@droid')) || | |
| (github.event_name == 'issues' && (contains(github.event.issue.body, '@droid') || contains(github.event.issue.title, '@droid'))) || | |
| (github.event_name == 'pull_request' && (contains(github.event.pull_request.body, '@droid') || contains(github.event.pull_request.title, '@droid'))) | |
| if: | | |
| (github.event_name == 'issue_comment' && (github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR') && contains(github.event.comment.body || '', '@droid')) || | |
| (github.event_name == 'pull_request_review_comment' && (github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR') && contains(github.event.comment.body || '', '@droid')) || | |
| (github.event_name == 'pull_request_review' && (github.event.review.author_association == 'OWNER' || github.event.review.author_association == 'MEMBER' || github.event.review.author_association == 'COLLABORATOR') && contains(github.event.review.body || '', '@droid')) || | |
| (github.event_name == 'issues' && (github.event.issue.author_association == 'OWNER' || github.event.issue.author_association == 'MEMBER' || github.event.issue.author_association == 'COLLABORATOR') && (contains(github.event.issue.body || '', '@droid') || contains(github.event.issue.title || '', '@droid'))) || | |
| (github.event_name == 'pull_request' && (github.event.pull_request.author_association == 'OWNER' || github.event.pull_request.author_association == 'MEMBER' || github.event.pull_request.author_association == 'COLLABORATOR') && (contains(github.event.pull_request.body || '', '@droid') || contains(github.event.pull_request.title || '', '@droid'))) |
| with: | ||
| fetch-depth: 1 | ||
| - name: Run Droid Exec | ||
| uses: Factory-AI/droid-action@main |
There was a problem hiding this comment.
[P1] Pin Factory-AI/droid-action to a commit SHA
Using Factory-AI/droid-action@main means each run executes mutable code from that branch; since this workflow provides a long-lived API key secret and write permissions for issues/PRs, pinning to a specific commit SHA (or a release tag that is itself pinned) reduces supply-chain risk and makes executions reproducible.
| uses: Factory-AI/droid-action@main | |
| uses: Factory-AI/droid-action@7c7bfea2aa3bb7ea87579402cc1d89dbcf6b13b3 |
| with: | ||
| fetch-depth: 1 | ||
| - name: Run Droid Exec | ||
| uses: Factory-AI/droid-action@main |
There was a problem hiding this comment.
P1: Workflow uses unpinned third-party action with mutable main reference
Unpinned third-party action Factory-AI/droid-action@main receives a long-lived API key and write permissions.
Pin the action to a specific commit SHA to prevent supply-chain attacks.
AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.
<file name=".github/workflows/droid.yml">
<violation number="1" location=".github/workflows/droid.yml:30">
<priority>P1</priority>
<title>Workflow uses unpinned third-party action with mutable `main` reference</title>
<evidence>The step at line 30 references `Factory-AI/droid-action@main`. A branch reference can point to different commits over time without review by this repository's maintainers. Because this workflow passes a sensitive `FACTORY_API_KEY` secret and grants write permissions (`issues: write`, `pull-requests: write`), using a mutable reference exposes the repository to supply-chain compromise if the upstream repository is compromised.</evidence>
<recommendation>Pin `Factory-AI/droid-action` to a specific commit SHA or a verified, immutable release tag.</recommendation>
</violation>
</file>
|
|
||
| jobs: | ||
| droid: | ||
| if: | |
There was a problem hiding this comment.
P1: Workflow triggers on untrusted issue comments without author validation
Untrusted users can trigger third-party action runs by posting @droid in public issue comments.
Add author_association checks to the if condition to only run for trusted collaborators.
AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.
<file name=".github/workflows/droid.yml">
<violation number="1" location=".github/workflows/droid.yml:13">
<priority>P1</priority>
<title>Workflow triggers on untrusted issue comments without author validation</title>
<evidence>The workflow fires on `issue_comment` events without checking the comment author's trust level. Any GitHub user can create an issue comment on a public repository containing `@droid`, causing this workflow to run a third-party action with access to repository secrets (`FACTORY_API_KEY`) and write permissions (`issues: write`, `pull-requests: write`). The `if` block only checks for the `@droid` string but does not verify `github.event.comment.author_association`.</evidence>
<recommendation>Restrict the `issue_comment` trigger to trusted authors by checking `github.event.comment.author_association` (e.g., OWNER, MEMBER, COLLABORATOR) before running the third-party action.</recommendation>
</violation>
</file>
| contents: read | ||
| pull-requests: write | ||
| issues: write | ||
| id-token: write |
There was a problem hiding this comment.
P2: Overly broad workflow permissions include id-token: write and actions: read
Job grants id-token: write and actions: read, neither of which is needed for a comment-responding bot.
Remove unnecessary permissions and use least-privilege access.
AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.
<file name=".github/workflows/droid.yml">
<violation number="1" location=".github/workflows/droid.yml:22">
<priority>P2</priority>
<title>Overly broad workflow permissions include `id-token: write` and `actions: read`</title>
<evidence>The workflow grants `id-token: write` (line 22) and `actions: read` (line 23). The `id-token: write` permission allows generation of OIDC ID tokens that can be exchanged for cloud credentials. The `actions: read` permission enables reading workflow runs and artifacts. Neither permission is required for a commenting bot that receives an explicit API key. These permissions expand the blast radius if the third-party action is compromised.</evidence>
<recommendation>Remove `id-token: write` and `actions: read` from the job permissions, or document why they are necessary. Apply least-privilege permissions.</recommendation>
</violation>
</file>
| @@ -0,0 +1,38 @@ | |||
| name: Droid Tag | |||
There was a problem hiding this comment.
P2: Workflow lacks top-level permissions block to restrict default GITHUB_TOKEN scope
No top-level permissions block means default token permissions depend on repo settings.
Add permissions: {} at the workflow level for defense-in-depth.
AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.
<file name=".github/workflows/droid.yml">
<violation number="1" location=".github/workflows/droid.yml:1">
<priority>P2</priority>
<title>Workflow lacks top-level permissions block to restrict default GITHUB_TOKEN scope</title>
<evidence>The workflow does not declare a top-level permissions block, so any additional jobs added later would inherit the repository's default GITHUB_TOKEN permissions, which may be broader than intended. The single job in this workflow does have explicit job-level permissions, but adding permissions: {} at the workflow level is a defense-in-depth measure recommended by GitHub and the OpenSSF.</evidence>
<recommendation>Add permissions: {} at the top level of the workflow (before or after the on: block) so that the default token scope is empty and every job must explicitly declare its own permissions.</recommendation>
</violation>
</file>
This PR adds the Factory Droid
@droidtag response workflow. When someone mentions@droidin an issue or PR comment, Droid will respond automatically.The workflow uses the
Factory-AI/droid-action@mainGitHub Action and authenticates with theFACTORY_API_KEYorg secret (already configured for thecomputesdkorg).Learn more at https://docs.factory.ai
Generate an API key at https://app.factory.ai/settings/api-keys