Skip to content

ci: prevent script injection in comment workflow#48

Merged
Marukome0743 merged 1 commit into
OpenUp-LabTakizawa:mainfrom
Marukome0743:pr48
May 9, 2026
Merged

ci: prevent script injection in comment workflow#48
Marukome0743 merged 1 commit into
OpenUp-LabTakizawa:mainfrom
Marukome0743:pr48

Conversation

@Marukome0743

@Marukome0743 Marukome0743 commented May 9, 2026

Copy link
Copy Markdown
Member

Read PR number and comment body via fs.readFileSync inside actions/github-script
instead of piping artifact contents through GITHUB_ENV in shell. The previous
'Setup Environment' step was flagged by GitHub security review for potential
injection of attacker-controlled data (PR title) from the workflow_run trigger.

Match old comments by github.event.workflow_run.name (workflow YAML, trusted)
instead of the user-supplied PR title from the artifact.

Summary by Sourcery

スクリプトインジェクションに対して GitHub Actions のコメント用ワークフローを強化しつつ、プルリクエストへのコメント投稿方法を簡素化します。

CI:

  • GITHUB_ENV へのシェルコマンドによるエクスポートではなく、actions/github-script の中でワークフローアーティファクトから直接プルリクエスト番号とコメント本文を読み取るように変更。
  • アーティファクト由来のユーザー入力である PR タイトルではなく、信頼できる workflow_run.name を使って既存のボットコメントを検出・置換し、コメントを作成する条件分岐ロジックを簡素化。
Original summary in English

Summary by Sourcery

Harden the GitHub Actions comment workflow against script injection while simplifying how comments are posted to pull requests.

CI:

  • Read the pull request number and comment body from workflow artifacts directly within actions/github-script instead of exporting them via GITHUB_ENV shell commands.
  • Match and replace existing bot comments using the trusted workflow_run.name rather than a user-supplied PR title from artifacts, and streamline the logic for when comments are created.

Read PR number and comment body via fs.readFileSync inside actions/github-script
instead of piping artifact contents through GITHUB_ENV in shell. The previous
'Setup Environment' step was flagged by GitHub security review for potential
injection of attacker-controlled data (PR title) from the workflow_run trigger.

Match old comments by github.event.workflow_run.name (workflow YAML, trusted)
instead of the user-supplied PR title from the artifact.
@github-actions github-actions Bot added the ♻️ci Changes to CI configuration files and scripts label May 9, 2026
@sourcery-ai

sourcery-ai Bot commented May 9, 2026

Copy link
Copy Markdown
レビュアー向けガイド(小さな PR では折りたたみ)

レビュアー向けガイド

PR コメント用ワークフローをリファクタリングし、github-script ステップ内でアーティファクトを直接読み込むことで、シェルベースの環境変数セットアップと潜在的なスクリプトインジェクションを排除し、ユーザーが制御できる PR タイトルではなく、信頼できるワークフローファイル名を使って既存コメントを突き合わせるようにします。

更新後の PR コメント用ワークフローのやり取りのシーケンス図

sequenceDiagram
    actor GitHub as GitHub
    participant WorkflowRun as CI_workflow_run
    participant CommentWorkflow as Comment_workflow
    participant DownloadArtifacts as Download_artifacts_action
    participant GithubScript as Github_script_action
    participant GitHubAPI as GitHub_issues_API

    GitHub->>WorkflowRun: Execute CI workflow
    WorkflowRun-->>GitHub: status, artifacts, conclusion
    GitHub-->>CommentWorkflow: Trigger on workflow_run (completed)

    CommentWorkflow->>DownloadArtifacts: actions/download-artifact with run-id
    DownloadArtifacts-->>CommentWorkflow: pr_number.txt, comment.txt artifacts

    CommentWorkflow->>GithubScript: Run actions/github-script
    GithubScript->>GithubScript: Read pr_number/pr_number.txt via fs.readFileSync
    GithubScript->>GithubScript: Sanitize to numeric prNumber
    GithubScript->>GithubScript: Read comment/comment.txt via fs.readFileSync

    GithubScript->>GitHubAPI: issues.listComments(owner, repo, issue_number = prNumber)
    GitHubAPI-->>GithubScript: Existing PR comments

    GithubScript->>GithubScript: Find oldComment where user.type == Bot and body includes WORKFLOW_NAME
    GithubScript->>GithubScript: shouldComment = oldComment OR CONCLUSION == failure
    alt shouldComment is false
        GithubScript-->>CommentWorkflow: Exit without commenting
    else shouldComment is true
        alt oldComment exists
            GithubScript->>GitHubAPI: issues.deleteComment(comment_id = oldComment.id)
            GitHubAPI-->>GithubScript: Comment deleted
        end
        GithubScript->>GitHubAPI: issues.createComment(issue_number = prNumber, body = comment)
        GitHubAPI-->>GithubScript: Comment created
    end

    GithubScript-->>CommentWorkflow: Step completes
    CommentWorkflow-->>GitHub: Workflow completed
Loading

GitHub Actions ワークフローにおける新しいコメント投稿判定ロジックのフローチャート

flowchart TD
    A["Start github-script step"] --> B["Read pr_number/pr_number.txt as prNumber and sanitize to digits"]
    B --> C["Read comment/comment.txt as comment"]
    C --> D["List PR comments via GitHub API using prNumber"]
    D --> E["Find oldComment where user.type is Bot and body includes WORKFLOW_NAME"]
    E --> F["Compute shouldComment = oldComment exists OR CONCLUSION equals failure"]

    F -->|"shouldComment is false"| G["Return without creating a comment"]
    F -->|"shouldComment is true"| H{"Does oldComment exist"}

    H -->|"Yes"| I["Delete oldComment via issues.deleteComment"]
    H -->|"No"| J["Skip deletion"]

    I --> K["Create new comment with body comment via issues.createComment"]
    J --> K

    K --> L["End github-script step"]
Loading

ファイル単位の変更内容

変更点 詳細 ファイル
シェルベースの環境セットアップを削除し、アーティファクトの内容を GITHUB_ENV にパイプしていた処理をやめて、インジェクションリスクを避けるために github-script ステップ内でアーティファクトを読み込むように変更。
  • PR 番号・タイトル・コメント本文を echo と UUID ベースの EOF デリミタで GITHUB_ENV に書き出していた「Setup Environment」ステップを削除する。
  • github-script ステップ内で Node.js の fs をインポートし、スクリプト内から pr_number/pr_number.txtcomment/comment.txt を直接読み込む。
  • アーティファクトから読み込んだ PR 番号について、数字以外の文字を取り除いてサニタイズする。
.github/workflows/comment.yml
既存のボットコメントの特定方法と新しいコメントを投稿する条件を変更し、ユーザーが入力する PR タイトルではなく信頼できるデータに基づいて判断。
  • github.event.workflow_run.nameWORKFLOW_NAME として github-script ステップに渡し、PR タイトルではなくコメント本文にこのワークフロー名が含まれているかどうかで、以前のボットコメントを特定する。
  • 古いボットコメントの有無、または結論が failure であるかに基づいて shouldComment フラグを計算し、それが偽の場合は早期リターンするようにコメント投稿ロジックをリファクタリングする。
  • サニタイズ済みの PR 番号とファイルから読み込んだコメント本文を常に使って新しいコメントを作成し、古いボットコメントが存在する場合は新しいコメントを投稿する前に削除する。
.github/workflows/comment.yml

Tips やコマンド

Sourcery とのやり取り

  • 新しいレビューをトリガーする: プルリクエストに @sourcery-ai review とコメントします。
  • 議論を続ける: Sourcery のレビューコメントに直接返信します。
  • レビューコメントから GitHub Issue を作成する: レビューコメントに返信して、そこから Issue を作成するよう Sourcery に依頼します。あるいは、レビューコメントに @sourcery-ai issue と返信して、そのコメントから Issue を作成できます。
  • プルリクエストタイトルを生成する: プルリクエストのタイトルのどこかに @sourcery-ai と書くと、いつでもタイトルを生成できます。プルリクエストに @sourcery-ai title とコメントして、いつでもタイトルを(再)生成することもできます。
  • プルリクエストのサマリを生成する: プルリクエスト本文の任意の場所に @sourcery-ai summary と書くと、その場所に PR サマリをいつでも生成できます。プルリクエストに @sourcery-ai summary とコメントして、サマリをいつでも(再)生成することもできます。
  • レビュアー向けガイドを生成する: プルリクエストに @sourcery-ai guide とコメントして、レビュアー向けガイドをいつでも(再)生成できます。
  • すべての Sourcery コメントを解決済みにする: プルリクエストに @sourcery-ai resolve とコメントすると、すべての Sourcery コメントを解決済みとして扱います。すでにすべてのコメントへ対応済みで、もう表示したくないときに便利です。
  • すべての Sourcery レビューを却下する: プルリクエストに @sourcery-ai dismiss とコメントすると、既存のすべての Sourcery レビューを却下します。新しいレビューでやり直したいときに特に便利です。その後、新しいレビューをトリガーするのを忘れずに @sourcery-ai review とコメントしてください。

体験のカスタマイズ

ダッシュボード にアクセスして以下を行えます:

  • Sourcery が生成するプルリクエストサマリ、レビュアー向けガイドなどのレビュー機能を有効化/無効化する。
  • レビュー言語を変更する。
  • カスタムレビュー指示を追加・削除・編集する。
  • その他のレビュー設定を調整する。

ヘルプを得る

Original review guide in English
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refactors the PR comment workflow to eliminate shell-based environment setup and potential script injection by reading artifacts directly in the github-script step and matching existing comments using the trusted workflow name instead of a user-controlled PR title.

Sequence diagram for updated PR comment workflow interaction

sequenceDiagram
    actor GitHub as GitHub
    participant WorkflowRun as CI_workflow_run
    participant CommentWorkflow as Comment_workflow
    participant DownloadArtifacts as Download_artifacts_action
    participant GithubScript as Github_script_action
    participant GitHubAPI as GitHub_issues_API

    GitHub->>WorkflowRun: Execute CI workflow
    WorkflowRun-->>GitHub: status, artifacts, conclusion
    GitHub-->>CommentWorkflow: Trigger on workflow_run (completed)

    CommentWorkflow->>DownloadArtifacts: actions/download-artifact with run-id
    DownloadArtifacts-->>CommentWorkflow: pr_number.txt, comment.txt artifacts

    CommentWorkflow->>GithubScript: Run actions/github-script
    GithubScript->>GithubScript: Read pr_number/pr_number.txt via fs.readFileSync
    GithubScript->>GithubScript: Sanitize to numeric prNumber
    GithubScript->>GithubScript: Read comment/comment.txt via fs.readFileSync

    GithubScript->>GitHubAPI: issues.listComments(owner, repo, issue_number = prNumber)
    GitHubAPI-->>GithubScript: Existing PR comments

    GithubScript->>GithubScript: Find oldComment where user.type == Bot and body includes WORKFLOW_NAME
    GithubScript->>GithubScript: shouldComment = oldComment OR CONCLUSION == failure
    alt shouldComment is false
        GithubScript-->>CommentWorkflow: Exit without commenting
    else shouldComment is true
        alt oldComment exists
            GithubScript->>GitHubAPI: issues.deleteComment(comment_id = oldComment.id)
            GitHubAPI-->>GithubScript: Comment deleted
        end
        GithubScript->>GitHubAPI: issues.createComment(issue_number = prNumber, body = comment)
        GitHubAPI-->>GithubScript: Comment created
    end

    GithubScript-->>CommentWorkflow: Step completes
    CommentWorkflow-->>GitHub: Workflow completed
Loading

Flow diagram for new comment decision logic in GitHub Actions workflow

flowchart TD
    A["Start github-script step"] --> B["Read pr_number/pr_number.txt as prNumber and sanitize to digits"]
    B --> C["Read comment/comment.txt as comment"]
    C --> D["List PR comments via GitHub API using prNumber"]
    D --> E["Find oldComment where user.type is Bot and body includes WORKFLOW_NAME"]
    E --> F["Compute shouldComment = oldComment exists OR CONCLUSION equals failure"]

    F -->|"shouldComment is false"| G["Return without creating a comment"]
    F -->|"shouldComment is true"| H{"Does oldComment exist"}

    H -->|"Yes"| I["Delete oldComment via issues.deleteComment"]
    H -->|"No"| J["Skip deletion"]

    I --> K["Create new comment with body comment via issues.createComment"]
    J --> K

    K --> L["End github-script step"]
Loading

File-Level Changes

Change Details Files
Remove shell-based environment setup that piped artifact contents into GITHUB_ENV and move artifact reading into the github-script step to avoid injection risks.
  • Delete the 'Setup Environment' step that exported PR number, title, and comment body into GITHUB_ENV via echo and UUID-based EOF delimiters.
  • In the github-script step, add a Node.js fs import and read pr_number/pr_number.txt and comment/comment.txt directly within the script.
  • Sanitize the PR number by stripping non-digit characters after reading it from the artifact.
.github/workflows/comment.yml
Change how existing bot comments are identified and when new comments are posted, using trusted data instead of user-supplied PR titles.
  • Expose github.event.workflow_run.name to the github-script step as WORKFLOW_NAME and use it to identify previous bot comments by checking comment bodies for this workflow name instead of the PR title.
  • Refactor the comment-posting logic to compute a shouldComment flag based on presence of an old bot comment or a failure conclusion and early-return otherwise.
  • Always create a new comment using the sanitized PR number and file-read comment body; if an old bot comment exists, delete it before posting the new one.
.github/workflows/comment.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - いくつか高レベルなフィードバックを残しました:

  • prNumber のパースまわりに簡単なガードを追加することを検討してください(例: 空や数値以外になった場合は例外を投げる、もしくは早期リターンするなど)。そうすることで、無効な issue 番号で GitHub API を呼び出すのではなく、早い段階で失敗させられます。
  • fs.readFileSync の読み取り失敗を扱うことを検討してもよいかもしれません(例: try/catch で明確なエラーメッセージを出すなど)。そうすることで、成果物が存在しない、あるいは壊れている場合に、ワークフローがより原因を特定しやすい形で失敗するようになります。
  • 古い bot コメントを見つけるのに c.body.includes(process.env.WORKFLOW_NAME) に依存する方法は、同じワークフロー名を含むコメントが複数ある場合に脆くなり得ます。置き換える対象のコメントを識別するために、より固有なマーカー(例: 非表示の HTML コメントや固定のプレフィックス)を使うことを検討してください。
AI エージェント向けプロンプト
Please address the comments from this code review:

## Overall Comments
- Consider adding a simple guard around the `prNumber` parsing (e.g., throw or early return if it ends up empty or non-numeric) so we fail fast instead of making a GitHub API call with an invalid issue number.
- It might be worth handling read failures from `fs.readFileSync` (e.g., try/catch with a clear error message) so the workflow fails in a more diagnosable way if the artifacts are missing or malformed.
- Relying on `c.body.includes(process.env.WORKFLOW_NAME)` to find the old bot comment could be brittle if multiple comments contain the same workflow name; consider using a more specific marker (e.g., a hidden HTML comment or a fixed prefix) to identify the comment to replace.

Sourcery はオープンソースなら無料です - レビューが気に入ったらぜひシェアを検討してください ✨
もっと役立てるように手助けしてください!各コメントに 👍 または 👎 を押していただけると、そのフィードバックをもとにレビューの質を改善していきます。
Original comment in English

Hey - I've left some high level feedback:

  • Consider adding a simple guard around the prNumber parsing (e.g., throw or early return if it ends up empty or non-numeric) so we fail fast instead of making a GitHub API call with an invalid issue number.
  • It might be worth handling read failures from fs.readFileSync (e.g., try/catch with a clear error message) so the workflow fails in a more diagnosable way if the artifacts are missing or malformed.
  • Relying on c.body.includes(process.env.WORKFLOW_NAME) to find the old bot comment could be brittle if multiple comments contain the same workflow name; consider using a more specific marker (e.g., a hidden HTML comment or a fixed prefix) to identify the comment to replace.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider adding a simple guard around the `prNumber` parsing (e.g., throw or early return if it ends up empty or non-numeric) so we fail fast instead of making a GitHub API call with an invalid issue number.
- It might be worth handling read failures from `fs.readFileSync` (e.g., try/catch with a clear error message) so the workflow fails in a more diagnosable way if the artifacts are missing or malformed.
- Relying on `c.body.includes(process.env.WORKFLOW_NAME)` to find the old bot comment could be brittle if multiple comments contain the same workflow name; consider using a more specific marker (e.g., a hidden HTML comment or a fixed prefix) to identify the comment to replace.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Marukome0743 Marukome0743 merged commit 5475b5a into OpenUp-LabTakizawa:main May 9, 2026
10 checks passed
@Marukome0743 Marukome0743 deleted the pr48 branch May 9, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

♻️ci Changes to CI configuration files and scripts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant