fix: use original body from webhook payload for TOCTOU hardening#904
fix: use original body from webhook payload for TOCTOU hardening#904
Conversation
| it("should handle null originalBody by setting body to empty string", async () => { | ||
| const mockOctokits = { | ||
| graphql: jest.fn().mockResolvedValue({ | ||
| repository: { | ||
| issue: { | ||
| number: 123, | ||
| title: "Test Issue", | ||
| body: "Some body from GraphQL", | ||
| author: { login: "author" }, | ||
| createdAt: "2024-01-15T10:00:00Z", | ||
| state: "OPEN", | ||
| labels: { nodes: [] }, | ||
| comments: { nodes: [] }, | ||
| }, | ||
| }, | ||
| user: { login: "trigger-user" }, | ||
| }), | ||
| rest: jest.fn() as any, | ||
| }; | ||
|
|
||
| const result = await fetchGitHubData({ | ||
| octokits: mockOctokits as any, | ||
| repository: "test-owner/test-repo", | ||
| prNumber: "123", | ||
| isPR: false, | ||
| triggerUsername: "trigger-user", | ||
| originalBody: null, | ||
| }); | ||
|
|
||
| // null originalBody means the issue had no body at trigger time | ||
| expect(result.contextData.body).toBe(""); | ||
| }); |
There was a problem hiding this comment.
Test Coverage - Missing security-critical scenario
This test validates that null originalBody sets body to empty string, but doesn't test the security-critical scenario where:
- Webhook has
originalBody: null(no body at trigger time) - GraphQL data shows a body with
lastEditedAttimestamp after the trigger - We should use the empty string from webhook, not the potentially malicious GraphQL body
Consider adding triggerTime and lastEditedAt to this test to verify the webhook's null takes precedence even when timestamp validation would reject the GraphQL body.
Comprehensive Code ReviewI performed a thorough review using specialized agents for code quality, performance, test coverage, documentation, and security. Overall, this is a well-implemented security fix that effectively prevents TOCTOU attacks on issue/PR bodies. Summary✅ Security: The TOCTOU protection is sound and properly implemented. All event types are covered, null/undefined handling is correct, and fallback logic maintains backward compatibility. ✅ Performance: No issues. The changes are minimal (O(1) operations) and actually provide a slight performance benefit by short-circuiting timestamp validation when webhook data is available. ✅ Test Coverage: Excellent (9/10). Comprehensive tests cover all event types, TOCTOU scenarios, edge cases, and integration points. Noteworthy FeedbackI've posted inline comments for the following issues:
Security NoteThe security reviewer identified a pre-existing TOCTOU vulnerability in review comments/bodies (lines 372-429 in fetcher.ts) that is NOT introduced by this PR. Review comments are fetched from GraphQL without webhook-based protection. This should be addressed in a follow-up PR using the same pattern demonstrated here. RecommendationApprove and merge once the documentation and inconsistency issues are addressed. The test coverage gaps are minor but worth considering for completeness. |
Bumps the github-actions group with 2 updates: [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) and [github/codeql-action](https://github.com/github/codeql-action). Updates `anthropics/claude-code-action` from 1.0.43 to 1.0.46 Release notes *Sourced from [anthropics/claude-code-action's releases](https://github.com/anthropics/claude-code-action/releases).* > v1.0.46 > ------- > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.46> > > v1.0.45 > ------- > > What's Changed > -------------- > > * fix: use original body from webhook payload for TOCTOU hardening by [`@ddworken`](https://github.com/ddworken) in [anthropics/claude-code-action#904](https://redirect.github.com/anthropics/claude-code-action/pull/904) > * refactor: simplify mode system by removing Mode interface and registry by [`@ashwin-ant`](https://github.com/ashwin-ant) in [anthropics/claude-code-action#899](https://redirect.github.com/anthropics/claude-code-action/pull/899) > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.45> > > v1.0.44 > ------- > > What's Changed > -------------- > > * refactor: unify action into single composite step with run.ts entrypoint by [`@ashwin-ant`](https://github.com/ashwin-ant) in [anthropics/claude-code-action#898](https://redirect.github.com/anthropics/claude-code-action/pull/898) > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.44> Commits * [`6c61301`](anthropics/claude-code-action@6c61301) chore: bump Claude Code to 2.1.37 and Agent SDK to 0.2.37 * [`db38843`](anthropics/claude-code-action@db38843) chore: bump Claude Code to 2.1.36 and Agent SDK to 0.2.36 * [`b113f49`](anthropics/claude-code-action@b113f49) chore: bump Claude Code to 2.1.33 and Agent SDK to 0.2.33 * [`7057f33`](anthropics/claude-code-action@7057f33) refactor: simplify mode system by removing Mode interface and registry ([#899](https://redirect.github.com/anthropics/claude-code-action/issues/899)) * [`f09dc9a`](anthropics/claude-code-action@f09dc9a) fix: use original body from webhook payload for TOCTOU hardening ([#904](https://redirect.github.com/anthropics/claude-code-action/issues/904)) * [`006aaf2`](anthropics/claude-code-action@006aaf2) chore: bump Claude Code to 2.1.32 and Agent SDK to 0.2.32 * [`9a3c761`](anthropics/claude-code-action@9a3c761) refactor: unify action into single composite step with run.ts entrypoint ([#898](https://redirect.github.com/anthropics/claude-code-action/issues/898)) * See full diff in [compare view](anthropics/claude-code-action@6867bb3...6c61301) Updates `github/codeql-action` from 4.32.1 to 4.32.2 Release notes *Sourced from [github/codeql-action's releases](https://github.com/github/codeql-action/releases).* > v4.32.2 > ------- > > * Update default CodeQL bundle version to [2.24.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.1). [#3460](https://redirect.github.com/github/codeql-action/pull/3460) Changelog *Sourced from [github/codeql-action's changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md).* > CodeQL Action Changelog > ======================= > > See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. > > [UNRELEASED] > ------------ > > No user facing changes. > > 4.32.2 - 05 Feb 2026 > -------------------- > > * Update default CodeQL bundle version to [2.24.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.1). [#3460](https://redirect.github.com/github/codeql-action/pull/3460) > > 4.32.1 - 02 Feb 2026 > -------------------- > > * A warning is now shown in Default Setup workflow logs if a [private package registry is configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) using a GitHub Personal Access Token (PAT), but no username is configured. [#3422](https://redirect.github.com/github/codeql-action/pull/3422) > * Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. [#3421](https://redirect.github.com/github/codeql-action/pull/3421) > > 4.32.0 - 26 Jan 2026 > -------------------- > > * Update default CodeQL bundle version to [2.24.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.0). [#3425](https://redirect.github.com/github/codeql-action/pull/3425) > > 4.31.11 - 23 Jan 2026 > --------------------- > > * When running a Default Setup workflow with [Actions debugging enabled](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging), the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. [#3409](https://redirect.github.com/github/codeql-action/pull/3409) > * Improved error handling throughout the CodeQL Action. [#3415](https://redirect.github.com/github/codeql-action/pull/3415) > * Added experimental support for automatically excluding [generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github) from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. [#3318](https://redirect.github.com/github/codeql-action/pull/3318) > * The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. [#3403](https://redirect.github.com/github/codeql-action/pull/3403) > > 4.31.10 - 12 Jan 2026 > --------------------- > > * Update default CodeQL bundle version to 2.23.9. [#3393](https://redirect.github.com/github/codeql-action/pull/3393) > > 4.31.9 - 16 Dec 2025 > -------------------- > > No user facing changes. > > 4.31.8 - 11 Dec 2025 > -------------------- > > * Update default CodeQL bundle version to 2.23.8. [#3354](https://redirect.github.com/github/codeql-action/pull/3354) > > 4.31.7 - 05 Dec 2025 > -------------------- > > * Update default CodeQL bundle version to 2.23.7. [#3343](https://redirect.github.com/github/codeql-action/pull/3343) > > 4.31.6 - 01 Dec 2025 > -------------------- > > No user facing changes. > > 4.31.5 - 24 Nov 2025 > -------------------- ... (truncated) Commits * [`45cbd0c`](github/codeql-action@45cbd0c) Merge pull request [#3461](https://redirect.github.com/github/codeql-action/issues/3461) from github/update-v4.32.2-7aee93297 * [`cb528be`](github/codeql-action@cb528be) Update changelog for v4.32.2 * [`7aee932`](github/codeql-action@7aee932) Merge pull request [#3460](https://redirect.github.com/github/codeql-action/issues/3460) from github/update-bundle/codeql-bundle-v2.24.1 * [`b5f028a`](github/codeql-action@b5f028a) Merge pull request [#3457](https://redirect.github.com/github/codeql-action/issues/3457) from github/dependabot/npm\_and\_yarn/npm-minor-4c1fc3... * [`9702c27`](github/codeql-action@9702c27) Merge branch 'main' into dependabot/npm\_and\_yarn/npm-minor-4c1fc3d0aa * [`c36c948`](github/codeql-action@c36c948) Add changelog note * [`3d03318`](github/codeql-action@3d03318) Update default bundle to codeql-bundle-v2.24.1 * [`77591e2`](github/codeql-action@77591e2) Merge pull request [#3459](https://redirect.github.com/github/codeql-action/issues/3459) from github/copilot/fix-github-actions-workflow-again * [`7a44a9d`](github/codeql-action@7a44a9d) Fix Rebuild Action workflow by adding --no-edit flag to git merge --continue * [`e2ac371`](github/codeql-action@e2ac371) Initial plan * Additional commits viewable in [compare view](github/codeql-action@6bc82e0...45cbd0c) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- Dependabot commands and options You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Use the original issue/PR body from the webhook payload instead of fetching it via GraphQL, matching the existing approach used for titles (
extractOriginalTitle). This hardens against the case where the body is edited between event time and when the action reads it.Changes:
extractOriginalBody()to extract body from webhook payload at event timecontextData.bodywith the webhook body infetchGitHubData()