NO-ISSUE: Add tofu plan and validate workflows for pull requests#132
NO-ISSUE: Add tofu plan and validate workflows for pull requests#132rccrdpccl wants to merge 1 commit into
Conversation
WalkthroughAdds OpenTofu validation and planning workflows for Terraform and CSV pull request changes, including detailed plan reporting through pull request comments. Existing workflows pin actions to commits, and three repositories remove obsolete required status checks. ChangesTerraform/OpenTofu CI and repository policy
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant PullRequest
participant GitHubActions
participant OpenTofu
participant AWS
participant GitHubAPI
PullRequest->>GitHubActions: trigger plan workflow
GitHubActions->>OpenTofu: initialize, validate, and plan
OpenTofu->>AWS: access authenticated infrastructure data
AWS-->>OpenTofu: return infrastructure data
GitHubActions->>GitHubAPI: create or update plan comment
Possibly related PRs
Suggested reviewers: Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error)
✅ Passed checks (10 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/plan.yaml:
- Line 29: Pin every third-party action to an immutable full commit SHA instead
of a mutable tag: update actions/checkout at .github/workflows/plan.yaml lines
29-29, actions/create-github-app-token at lines 35-35, opentofu/setup-opentofu
at lines 42-42, and actions/github-script at lines 67-67, preserving each
action’s existing version.
- Around line 3-4: Replace the credentialed pull_request_target workflow trigger
with a pull_request-based flow for untrusted PR execution, and ensure checkout
and OpenTofu planning use the repository’s trusted ref rather than the PR head.
Keep AWS credentials and the GitHub App token out of all jobs that execute
attacker-controlled code, including the referenced environment approval and
planning steps.
In @.github/workflows/validate.yaml:
- Around line 3-7: Add a workflow-level concurrency configuration to the
validation workflow, using a pull-request-scoped group and setting
cancel-in-progress to true so superseded runs are cancelled while separate pull
requests remain isolated.
- Around line 19-24: Replace the mutable version tags in the workflow steps
using actions/checkout and opentofu/setup-opentofu with full immutable commit
SHAs corresponding to the intended v7 and v2 releases, respectively. Preserve
the existing action configuration, including tofu_wrapper: false.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 830ec18b-26af-4a90-8fef-de61cf36174e
📒 Files selected for processing (2)
.github/workflows/plan.yaml.github/workflows/validate.yaml
2cbb365 to
6d72c28
Compare
6d72c28 to
577851f
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/apply.yaml:
- Line 41: Replace the hardcoded client ID in the workflow’s client-id
configuration with the established environment-variable reference used by
workflows such as plan.yaml, preserving the existing authentication behavior and
variable naming convention.
In @.github/workflows/plan.yaml:
- Around line 84-93: Review the plan output handling in the workflow’s
plan-comment generation and ensure sensitive Terraform values cannot be
published verbatim in the PR comment. Audit the providers and resources used by
this repository’s Terraform configuration for correctly marked sensitive
attributes, and add or apply redaction before the `<pre>` content is constructed
for any values not protected by provider schemas.
- Around line 28-31: Update the “Checkout PR” actions/checkout step to disable
credential persistence by setting persist-credentials to false, ensuring the
checkout token is not retained before OpenTofu execution; leave the existing ref
unchanged.
- Around line 33-39: Update the “Generate a token” step using
actions/create-github-app-token so it scopes the installation token to the
specific repository required by this job via repositories, rather than relying
only on owner. Add the minimum required permission, including
permission-contents: read, and preserve the existing client-id and private-key
inputs.
- Around line 100-105: Update the comment lookup around listComments to use
github.paginate with the existing issues.listComments request, so all pages of
comments are retrieved before searching. Keep the existing marker-based
comments.find logic and ensure it operates on the complete paginated result.
In @.github/workflows/validate.yaml:
- Line 23: Set persist-credentials to false on each actions/checkout step in
.github/workflows/validate.yaml (23-23), .github/workflows/apply.yaml (36-36),
and .github/workflows/pre-commit.yaml (16-16); no other checkout behavior should
change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 9bedb393-5288-4282-bd35-0fff3c4e4ec3
📒 Files selected for processing (5)
.github/workflows/apply.yaml.github/workflows/plan.yaml.github/workflows/pre-commit.yaml.github/workflows/validate.yamlrepositories.tf
💤 Files with no reviewable changes (1)
- repositories.tf
| - name: Generate a token | ||
| id: generate-token | ||
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 | ||
| with: | ||
| client-id: ${{ env.CONFIG_APP_CLIENT_ID }} | ||
| private-key: ${{ secrets.CONFIG_APP_SECRET }} | ||
| owner: ${{ github.repository_owner }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== workflow excerpt ==\n'
nl -ba .github/workflows/plan.yaml | sed -n '1,140p'
printf '\n== usages of generate-token / CONFIG_APP ==\n'
rg -n "generate-token|CONFIG_APP|create-github-app-token|permission-contents|repositories:" .github/workflows . -g '!**/node_modules/**' || trueRepository: osac-project/github-config
Length of output: 228
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== workflow excerpt ==\n'
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/plan.yaml')
for i, line in enumerate(p.read_text().splitlines(), 1):
if 1 <= i <= 140:
print(f"{i:4d}: {line}")
PY
printf '\n== relevant occurrences ==\n'
rg -n "generate-token|CONFIG_APP|create-github-app-token|permission-contents|repositories:" .github/workflows . -g '!**/node_modules/**' || trueRepository: osac-project/github-config
Length of output: 5767
🌐 Web query:
actions/create-github-app-token v3 repositories owner permissions input documentation
💡 Result:
The actions/create-github-app-token action (version 3) uses the owner, repositories, and permission-prefixed inputs to control the scope and capabilities of the generated installation access token [1][2][3]. Owner and Repository Scoping - owner: Specifies the organization or user account where the GitHub App is installed [3][4]. If left empty, it defaults to the current repository owner [1][3]. - repositories: A comma or newline-separated list of repository names [1][2]. If owner is provided but repositories is empty, the token is scoped to all repositories in that owner's installation [1][3]. If both owner and repositories are empty, the token is scoped only to the current repository [1][3]. Repository names can include the owner (e.g., owner/repo1) [1][2]. Permission Inputs - The action supports granular control via inputs prefixed with permission- (e.g., permission-pull-requests, permission-contents) [3][4]. - By default, if no specific permissions are provided, the generated token inherits all permissions currently granted to the GitHub App installation [1][2][3]. - It is recommended to explicitly list only the permissions required for your specific use case, following GitHub's principle of least privilege for GITHUB_TOKEN [1][3]. - Note: If you request a permission via an input that the GitHub App installation does not actually possess, the action will fail with an error [3][4]. Installation permissions are managed at the account level; if the app requests new permissions after installation, an administrator must approve them before they are available to the action [1][2][3].
Citations:
- 1: https://github.com/actions/create-github-app-token?tab=readme-ov-file
- 2: https://github.com/actions/create-github-app-token/blob/main/README.md
- 3: https://github.com/actions/create-github-app-token/tree/refs/heads/main
- 4: https://deepwiki.com/actions/create-github-app-token/4.1-action-inputs
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/plan.yaml')
for i, line in enumerate(p.read_text().splitlines(), 1):
if 25 <= i <= 50:
print(f"{i:4d}: {line}")
PY
printf '\n== file names ==\n'
git ls-files '.github/workflows/*'Repository: osac-project/github-config
Length of output: 1291
Scope the GitHub App token to the repo(s) this job actually needs. owner alone widens the installation token to every repository the app can access; add repositories and request only the minimum permissions, e.g. permission-contents: read, to reduce the blast radius if later steps expose the token.
🧰 Tools
🪛 zizmor (1.26.1)
[error] 39-39: dangerous use of GitHub App tokens (github-app): token granted access to all repositories for this owner's app installation
(github-app)
[error] 35-35: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions
(github-app)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/plan.yaml around lines 33 - 39, Update the “Generate a
token” step using actions/create-github-app-token so it scopes the installation
token to the specific repository required by this job via repositories, rather
than relying only on owner. Add the minimum required permission, including
permission-contents: read, and preserve the existing client-id and private-key
inputs.
Sources: Path instructions, Linters/SAST tools
| const marker = '<!-- tofu-plan -->'; | ||
| const body = [ | ||
| marker, | ||
| `### OpenTofu Plan`, | ||
| '', | ||
| summary, | ||
| '', | ||
| '<details><summary>Show plan output</summary>', | ||
| '', | ||
| `<pre>${plan.substring(0, 60000)}</pre>`, |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial
Full plan output is posted to a public-ish PR comment verbatim.
HTML-escaping protects rendering, but it doesn't redact attribute values — that relies entirely on the underlying provider schemas marking fields sensitive. Worth double-checking that all providers/resources touched by this repo's .tf correctly mark sensitive attributes, since anything unmarked will land in the PR comment as plaintext.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/plan.yaml around lines 84 - 93, Review the plan output
handling in the workflow’s plan-comment generation and ensure sensitive
Terraform values cannot be published verbatim in the PR comment. Audit the
providers and resources used by this repository’s Terraform configuration for
correctly marked sensitive attributes, and add or apply redaction before the
`<pre>` content is constructed for any values not protected by provider schemas.
Source: Path instructions
| TF_CLI_ARGS: "-no-color" | ||
| TF_IN_AUTOMATION: "true" | ||
| steps: | ||
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify action versions and the pinned commit SHA.
echo "Latest actions/checkout release:"
gh api repos/actions/checkout/releases --jq '.[0].tag_name'
echo "Latest actions/setup-python release:"
gh api repos/actions/setup-python/releases --jq '.[0].tag_name'
echo "Checking if the pinned SHA exists in actions/checkout:"
gh api repos/actions/checkout/commits/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 --jq '"Found commit authored by: " + .commit.author.name' || echo "Error: Commit not found in actions/checkout!"Repository: osac-project/github-config
Length of output: 340
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== validate.yaml ==\n'
sed -n '1,120p' .github/workflows/validate.yaml
printf '\n== apply.yaml ==\n'
sed -n '1,140p' .github/workflows/apply.yaml
printf '\n== pre-commit.yaml ==\n'
sed -n '1,120p' .github/workflows/pre-commit.yamlRepository: osac-project/github-config
Length of output: 4154
Disable persist-credentials on checkout. actions/checkout writes the workflow token into git config by default; these three jobs don't need that access, so set persist-credentials: false on each step in .github/workflows/validate.yaml, .github/workflows/apply.yaml, and .github/workflows/pre-commit.yaml.
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 23-23: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
📍 Affects 3 files
.github/workflows/validate.yaml#L23-L23(this comment).github/workflows/apply.yaml#L36-L36.github/workflows/pre-commit.yaml#L16-L16
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/validate.yaml at line 23, Set persist-credentials to false
on each actions/checkout step in .github/workflows/validate.yaml (23-23),
.github/workflows/apply.yaml (36-36), and .github/workflows/pre-commit.yaml
(16-16); no other checkout behavior should change.
Sources: Path instructions, Linters/SAST tools
577851f to
de9ff84
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
.github/workflows/plan.yaml (1)
34-41: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winApp token still inherits all installation permissions.
repositories: github-confignarrows the token to this repo (fix applied from earlier review), but nopermission-*input is set, so the token still carries every permission the app installation has been granted for this repo (peractions/create-github-app-tokendocs: "By default, the token inherits all of the installation's permissions... We recommend to explicitly list the permissions that are required"). Since this step only needs the token fortofu plan, add e.g.permission-contents: readto cap the blast radius if the token is ever exposed.🔒 Proposed fix
- name: Generate a token id: generate-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: client-id: ${{ env.CONFIG_APP_CLIENT_ID }} private-key: ${{ secrets.CONFIG_APP_SECRET }} owner: ${{ github.repository_owner }} repositories: github-config + permission-contents: readAs per path instructions, "Least privilege: minimize GITHUB_TOKEN permissions." This is the still-open half of a previously flagged concern (the
repositoriesscoping was addressed, permission scoping wasn't).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/plan.yaml around lines 34 - 41, Restrict the token created by the generate-token step to the permissions required by tofu plan by adding an explicit read-only contents permission input, such as permission-contents: read, alongside the existing repository scope. Do not broaden the token or change the client, owner, or repository settings.Sources: Path instructions, Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/apply.yaml:
- Around line 40-46: Update the “Generate a token” step using
actions/create-github-app-token to set its repositories input to the current
repository, matching the least-privilege configuration in plan.yaml while
preserving the existing owner and credential inputs.
In @.github/workflows/plan.yaml:
- Around line 1-123: Add a Terraform-focused SAST/SCA validation step to the
plan job before TF init and any tofu plan execution, using an approved scanner
such as tfsec, checkov, or tflint. Configure it to analyze the checked-out
Terraform changes and fail the workflow on detected violations, ensuring
untrusted PR infrastructure is scanned before credentials are used.
---
Duplicate comments:
In @.github/workflows/plan.yaml:
- Around line 34-41: Restrict the token created by the generate-token step to
the permissions required by tofu plan by adding an explicit read-only contents
permission input, such as permission-contents: read, alongside the existing
repository scope. Do not broaden the token or change the client, owner, or
repository settings.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: c833bd07-df59-44ca-a06c-6f5e6a8fbc4a
📒 Files selected for processing (5)
.github/workflows/apply.yaml.github/workflows/plan.yaml.github/workflows/pre-commit.yaml.github/workflows/validate.yamlrepositories.tf
💤 Files with no reviewable changes (1)
- repositories.tf
| - name: Generate a token | ||
| id: generate-token | ||
| uses: actions/create-github-app-token@v3 | ||
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 | ||
| with: | ||
| client-id: Iv23lipEOAvwk5QqNUie | ||
| client-id: ${{ env.CONFIG_APP_CLIENT_ID }} | ||
| private-key: ${{ secrets.CONFIG_APP_SECRET }} | ||
| owner: ${{ github.repository_owner }} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Restrict GitHub App token scope to the current repository.
The actions/create-github-app-token step currently omits the repositories input, which causes the generated token to inherit access to all repositories the GitHub App is installed in. For least privilege, restrict the token to the current repository (consistent with the configuration in plan.yaml).
🛡️ Proposed fix to limit token scope
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
with:
client-id: ${{ env.CONFIG_APP_CLIENT_ID }}
private-key: ${{ secrets.CONFIG_APP_SECRET }}
owner: ${{ github.repository_owner }}
+ repositories: ${{ github.event.repository.name }}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Generate a token | |
| id: generate-token | |
| uses: actions/create-github-app-token@v3 | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 | |
| with: | |
| client-id: Iv23lipEOAvwk5QqNUie | |
| client-id: ${{ env.CONFIG_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CONFIG_APP_SECRET }} | |
| owner: ${{ github.repository_owner }} | |
| - name: Generate a token | |
| id: generate-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 | |
| with: | |
| client-id: ${{ env.CONFIG_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CONFIG_APP_SECRET }} | |
| owner: ${{ github.repository_owner }} | |
| repositories: ${{ github.event.repository.name }} |
🧰 Tools
🪛 zizmor (1.26.1)
[error] 46-46: dangerous use of GitHub App tokens (github-app): token granted access to all repositories for this owner's app installation
(github-app)
[error] 42-42: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions
(github-app)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/apply.yaml around lines 40 - 46, Update the “Generate a
token” step using actions/create-github-app-token to set its repositories input
to the current repository, matching the least-privilege configuration in
plan.yaml while preserving the existing owner and credential inputs.
| name: Plan | ||
|
|
||
| on: | ||
| pull_request_target: | ||
| paths: | ||
| - "**/*.tf" | ||
| - "**/*.csv" | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| plan: | ||
| runs-on: ubuntu-latest | ||
| environment: plan | ||
| env: | ||
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||
| CONFIG_APP_CLIENT_ID: Iv23lipEOAvwk5QqNUie | ||
| TF_CLI_ARGS: "-no-color" | ||
| TF_IN_AUTOMATION: "true" | ||
| steps: | ||
| - name: Checkout PR | ||
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha }} | ||
| persist-credentials: false | ||
|
|
||
| - name: Generate a token | ||
| id: generate-token | ||
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 | ||
| with: | ||
| client-id: ${{ env.CONFIG_APP_CLIENT_ID }} | ||
| private-key: ${{ secrets.CONFIG_APP_SECRET }} | ||
| owner: ${{ github.repository_owner }} | ||
| repositories: github-config | ||
|
|
||
| - name: Setup OpenTofu | ||
| uses: opentofu/setup-opentofu@a1320f892987e89d278cc92dc5adc984fb93aca4 # v2 | ||
| with: | ||
| tofu_wrapper: false | ||
|
|
||
| - name: TF init | ||
| run: tofu init | ||
|
|
||
| - name: TF Validate | ||
| run: tofu validate | ||
|
|
||
| - name: TF Plan | ||
| id: plan | ||
| run: | | ||
| set +e | ||
| tofu plan -detailed-exitcode 2>&1 | tee plan_output.txt | ||
| exitcode=${PIPESTATUS[0]} | ||
| echo "exitcode=$exitcode" >> "$GITHUB_OUTPUT" | ||
| if [ "$exitcode" -eq 1 ]; then | ||
| exit 1 | ||
| fi | ||
| env: | ||
| GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} | ||
|
|
||
| - name: Comment plan on PR | ||
| if: always() && steps.plan.outcome != 'skipped' | ||
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 | ||
| with: | ||
| script: | | ||
| const fs = require('fs'); | ||
| const raw = fs.readFileSync('plan_output.txt', 'utf8'); | ||
| const plan = raw.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); | ||
| const exitcode = '${{ steps.plan.outputs.exitcode }}'; | ||
|
|
||
| let summary; | ||
| if (exitcode === '0') { | ||
| summary = 'No changes. Infrastructure is up-to-date.'; | ||
| } else if (exitcode === '2') { | ||
| summary = 'Changes detected. Review the plan below.'; | ||
| } else { | ||
| summary = 'Plan failed. See details below.'; | ||
| } | ||
|
|
||
| const marker = '<!-- tofu-plan -->'; | ||
| const body = [ | ||
| marker, | ||
| `### OpenTofu Plan`, | ||
| '', | ||
| summary, | ||
| '', | ||
| '<details><summary>Show plan output</summary>', | ||
| '', | ||
| `<pre>${plan.substring(0, 60000)}</pre>`, | ||
| '', | ||
| '</details>', | ||
| '', | ||
| `*Commit: ${context.payload.pull_request.head.sha}*`, | ||
| ].join('\n'); | ||
|
|
||
| const comments = await github.paginate(github.rest.issues.listComments, { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.issue.number, | ||
| }); | ||
| const existing = comments.find(c => c.body.includes(marker)); | ||
|
|
||
| if (existing) { | ||
| await github.rest.issues.updateComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| comment_id: existing.id, | ||
| body, | ||
| }); | ||
| } else { | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: context.issue.number, | ||
| body, | ||
| }); | ||
| } |
There was a problem hiding this comment.
🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win
No SAST/SCA scan for the Terraform/CSV changes before they're planned with real credentials.
This pipeline runs tofu plan against untrusted PR diffs with AWS credentials and an App token, but there's no tfsec/checkov/tflint-style static analysis step to catch obviously malicious or misconfigured Terraform before a human approves the plan environment gate.
As per path instructions, ".github/workflows/**/*" changes should include "SAST/SCA steps in pipeline."
🧰 Tools
🪛 zizmor (1.26.1)
[error] 11-11: overly broad permissions (excessive-permissions): pull-requests: write is overly broad at the workflow level
(excessive-permissions)
[error] 3-7: use of fundamentally insecure workflow trigger (dangerous-triggers): pull_request_target is almost always used insecurely
(dangerous-triggers)
[info] 75-75: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[warning] 11-11: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
[info] 18-18: workflow or action definition without a name (anonymous-definition): this job
(anonymous-definition)
[error] 36-36: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions
(github-app)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/plan.yaml around lines 1 - 123, Add a Terraform-focused
SAST/SCA validation step to the plan job before TF init and any tofu plan
execution, using an approved scanner such as tfsec, checkov, or tflint.
Configure it to analyze the checked-out Terraform changes and fail the workflow
on detected violations, ensuring untrusted PR infrastructure is scanned before
credentials are used.
Source: Path instructions
Split into two workflows: - validate.yaml: runs on pull_request (no secrets needed), does tofu init -backend=false + tofu validate for immediate feedback on syntax/config errors. - plan.yaml: runs on pull_request_target with a required "plan" environment gate, so a maintainer must approve before secrets (AWS creds, GitHub App token) are exposed to the PR's code. Posts the plan output as a PR comment. The environment gate mitigates the Pwn Request risk inherent in pull_request_target + checkout PR head: external data sources and provider binaries execute during plan, so untrusted code must not run without human review of the diff. Also: - Pin all third-party actions to immutable commit SHAs - Set persist-credentials: false on all checkout steps - Paginate listComments to handle PRs with 30+ comments - Extract CONFIG_APP_CLIENT_ID env var in apply.yaml - Remove stale Prow required status checks (ci/prow/temp, ci/prow/unit) from fulfillment-service, osac-operator, osac-aap Note: the GitHub App token is intentionally NOT scoped to a single repository — the Terraform GitHub provider manages all repos in the org, so both plan and apply need org-wide access. Assisted-by: Claude Code <noreply@anthropic.com> Signed-off-by: Riccardo Piccoli <rpiccoli@redhat.com>
de9ff84 to
754e3a2
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (4)
.github/workflows/apply.yaml (1)
40-46: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winRestrict GitHub App token scope to the current repository.
The
actions/create-github-app-tokenstep omits therepositoriesinput, causing the generated token to inherit access to all repositories the GitHub App is installed in. For least privilege, restrict the token to the current repository.🛡️ Proposed fix
- name: Generate a token id: generate-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: client-id: ${{ env.CONFIG_APP_CLIENT_ID }} private-key: ${{ secrets.CONFIG_APP_SECRET }} owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/apply.yaml around lines 40 - 46, Update the “Generate a token” step using actions/create-github-app-token to set its repositories input to the current repository, preserving the existing owner and credential configuration while limiting the token to this repository only..github/workflows/plan.yaml (3)
34-40: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winApp token still scoped to the whole owner installation.
repositoriesandpermission-*inputs are still missing;owneralone grants the generated token access to every repo the App installation can reach. This was flagged previously and not yet addressed in this diff.🔒 Proposed fix
- name: Generate a token id: generate-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 with: client-id: ${{ env.CONFIG_APP_CLIENT_ID }} private-key: ${{ secrets.CONFIG_APP_SECRET }} - owner: ${{ github.repository_owner }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + permission-contents: read🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/plan.yaml around lines 34 - 40, Update the “Generate a token” step using the actions/create-github-app-token configuration to restrict the token to the intended repository and explicitly declare the required permission-* inputs, rather than relying on owner-only installation scope. Preserve the existing client-id, private-key, and owner settings while adding repository and least-privilege permission configuration.Sources: Path instructions, Linters/SAST tools
50-53: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick winNo SAST/SCA scan before credentialed plan runs.
Still no
tfsec/checkov/tflint-style static analysis beforetofu planexecutes with AWS credentials and an App token against untrusted PR diffs. Previously flagged, still absent.As per path instructions, ".github/workflows/**/*" changes require "SAST/SCA steps in pipeline."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/plan.yaml around lines 50 - 53, Add a SAST/SCA static-analysis step to the workflow between the “TF Validate” and “TF Plan” steps, using an approved Terraform scanner such as tfsec, checkov, or tflint. Ensure the scan runs before the credentialed “TF Plan” step and analyzes the untrusted PR Terraform changes.Source: Path instructions
85-99: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick winFull plan output still posted verbatim to a public-ish PR comment.
HTML-escaping guards rendering but doesn't redact attribute values — that depends entirely on every touched provider/resource marking sensitive fields correctly. Any unmarked attribute lands in plaintext in the PR comment. This was raised previously and is unchanged.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/plan.yaml around lines 85 - 99, Update the body construction around the `plan` interpolation so the PR comment no longer embeds raw OpenTofu plan output. Remove the `<pre>` plan section or replace it with a trusted redacted artifact/link, ensuring unmarked sensitive provider or resource attributes cannot appear in the public comment while preserving the summary and commit metadata.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In @.github/workflows/apply.yaml:
- Around line 40-46: Update the “Generate a token” step using
actions/create-github-app-token to set its repositories input to the current
repository, preserving the existing owner and credential configuration while
limiting the token to this repository only.
In @.github/workflows/plan.yaml:
- Around line 34-40: Update the “Generate a token” step using the
actions/create-github-app-token configuration to restrict the token to the
intended repository and explicitly declare the required permission-* inputs,
rather than relying on owner-only installation scope. Preserve the existing
client-id, private-key, and owner settings while adding repository and
least-privilege permission configuration.
- Around line 50-53: Add a SAST/SCA static-analysis step to the workflow between
the “TF Validate” and “TF Plan” steps, using an approved Terraform scanner such
as tfsec, checkov, or tflint. Ensure the scan runs before the credentialed “TF
Plan” step and analyzes the untrusted PR Terraform changes.
- Around line 85-99: Update the body construction around the `plan`
interpolation so the PR comment no longer embeds raw OpenTofu plan output.
Remove the `<pre>` plan section or replace it with a trusted redacted
artifact/link, ensuring unmarked sensitive provider or resource attributes
cannot appear in the public comment while preserving the summary and commit
metadata.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 10513d7b-e79d-4d57-a5ba-1132c158e5c5
📒 Files selected for processing (5)
.github/workflows/apply.yaml.github/workflows/plan.yaml.github/workflows/pre-commit.yaml.github/workflows/validate.yamlrepositories.tf
💤 Files with no reviewable changes (1)
- repositories.tf
Split into two workflows:
validate.yaml: runs on pull_request (no secrets needed), does tofu init -backend=false + tofu validate for immediate feedback on syntax/config errors. Here a potential attacker could technically download a new
tofubinary but with no access to the secrets, the risk should be minimalplan.yaml: runs on pull_request_target with a required "plan" environment gate, so a maintainer must approve before secrets (AWS creds, GitHub App token) are exposed to the PR's code. Posts the plan output as a PR comment.
The environment gate mitigates the Pwn Request risk inherent in pull_request_target + checkout PR head: external data sources and provider binaries execute during plan, so untrusted code must not run without human review of the diff.
Assisted-by: Claude Code noreply@anthropic.com
Summary by CodeRabbit