From 74fdc71bcfd5ed2c8f3e41a864898554905826bd Mon Sep 17 00:00:00 2001 From: dymoo <60218243+dymoo@users.noreply.github.com> Date: Wed, 22 Jul 2026 15:06:52 +0100 Subject: [PATCH 1/2] Add a security policy States the threat model explicitly: what reaches the model, why pull_request_target is safe here and the one thing that would make it unsafe, who can spend the key, and that there is no dist/ to audit. --- SECURITY.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..e96186d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,56 @@ +# Security + +## Reporting a vulnerability + +Open a [private security advisory](https://github.com/dymoo/commitreview/security/advisories/new). +Please do not open a public issue for anything exploitable. + +## Threat model + +commitreview runs inside your GitHub Actions runner. There is no hosted service, +no telemetry and no third party. It makes network requests to exactly two places: +the GitHub API, and the `base-url` you configure. + +**Your API key** is registered with the runner's secret masker on the first line +of execution, before any other work happens, so it cannot appear in logs. It is +sent only to `base-url`, in an `Authorization` header. + +**What is sent to the model:** the changed hunks, surrounding source from the +changed files, and the pull request title and description. Nothing else from the +repository. Paths matching `ignore` are never read. If a path must never leave +the repository, add it to `ignore` — the default list covers lockfiles, build +output and vendored code, not secrets. + +**The diff is untrusted input.** A pull request author controls the code, the +comments and the file names that reach the model. Prompts label the diff as data +and instruct the model to report injection attempts rather than follow them, but +no such instruction is a guarantee. Treat findings as advice from an untrusted +source: read them, do not automate merges on them. + +**No code from the pull request is executed or checked out.** The action reads +the diff and file contents through the GitHub API. This is why +`pull_request_target` is safe with commitreview specifically — but only as long +as your workflow does not also check out the head ref. Do not add +`actions/checkout` with `ref: ${{ github.event.pull_request.head.sha }}` to a +`pull_request_target` workflow. + +**Who can spend your key.** Comment triggers are restricted to the author +associations in `allowed-associations`, which defaults to owners, members and +collaborators; a `pr-number` input cannot bypass that gate. The automatic +`pull_request` / `pull_request_target` trigger is deliberately not gated — on a +public repository, anyone who opens a pull request causes a review. See +[Security in the README](README.md#security) for how to gate it. + +**Permissions.** The action needs `contents: read` and `pull-requests: write`. +It never writes to the repository contents, never pushes, and never approves or +requests changes on a review — reviews are always submitted as `COMMENT`. + +## Supply chain + +There are no runtime dependencies and no bundled `dist/` — `action.yml` runs +`src/index.js` directly, so the code you audit is the code that runs. Pin to a +release tag, or to a commit SHA if you want the strongest guarantee: + +```yaml +- uses: dymoo/commitreview@v1.0.0 +``` From e6fc0b2df3ec816ca308c4abb6fca970c8b9de32 Mon Sep 17 00:00:00 2001 From: dymoo <60218243+dymoo@users.noreply.github.com> Date: Wed, 22 Jul 2026 15:07:49 +0100 Subject: [PATCH 2/2] Skip the self-review when no key is configured A fork PR, or a clone without LLM_API_KEY, was failing the check rather than skipping it. The secrets context is not available in a job-level if:, so gate the step on an env expression instead. --- .github/workflows/commitreview.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/commitreview.yml b/.github/workflows/commitreview.yml index a82445c..6fce36b 100644 --- a/.github/workflows/commitreview.yml +++ b/.github/workflows/commitreview.yml @@ -24,7 +24,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + # The secrets context is not available in an if:, but the env context is — + # so a fork PR or a clone without a key skips instead of failing red. - uses: ./ + if: env.HAS_KEY == 'true' + env: + HAS_KEY: ${{ secrets.LLM_API_KEY != '' }} with: api-key: ${{ secrets.LLM_API_KEY }} base-url: ${{ vars.LLM_BASE_URL || 'https://openrouter.ai/api/v1' }}