Skip to content

Conversation

@jordan-dr
Copy link
Contributor

No description provided.

@dryrunsecurity
Copy link

dryrunsecurity bot commented Aug 4, 2025

DryRun Security

🔴 Risk threshold exceeded.

This pull request contains multiple security vulnerabilities in the GitHub Actions workflow, including command injection risks, potential information disclosure of AWS secrets, hardcoded credentials, and insecure GitHub Action configurations that could lead to unauthorized access or remote code execution.

🔴 Code Policy: GitHub Action Policy Rails
Policy GitHub Action Policy Rails
Result Several security risks were identified in the GitHub Actions workflow: 1) The workflow logs sensitive AWS credentials with 'echo "AWS secret key is ${{ secrets.AWS_SECRET_ACCESS_KEY }}"' which exposes secrets in logs. 2) The 'git checkout ${{ github.event.inputs.tag }}' command uses an unsanitized user input that could enable command injection. 3) Third-party actions are used without pinned commit hashes: actions/checkout@v4, ruby/setup-ruby@v1, actions/cache@v3, aws-actions/configure-aws-credentials@v2, and slackapi/slack-github-action@v1, which could be compromised if the latest version is malicious. 4) The workflow uses workflow_dispatch with a user-provided tag input that could be used to execute arbitrary git commands.
🟡 Code Policy: hardcoded-creds
Policy hardcoded-creds
Result Yes, the changes include hard-coded credentials in the postgres service configuration where POSTGRES_USER is set to 'postgres' and POSTGRES_PASSWORD is set to 'postgres'. Additionally, these values are used in the DATABASE_URL environment variable. While these appear to be test environment credentials, they are still hard-coded values in the workflow file. Guidance: refer issues to the security team
Command Injection in CI/CD Pipeline in .github/workflows/main.yaml
Vulnerability Command Injection in CI/CD Pipeline
Description The GitHub Actions workflow in .github/workflows/main.yaml is vulnerable to command injection. The deploy-dev job, which can be triggered manually via workflow_dispatch, directly uses the user-provided github.event.inputs.tag input within a git checkout shell command without any sanitization or validation. This allows an attacker to inject arbitrary shell commands by crafting a malicious tag value, leading to remote code execution on the GitHub Actions runner.

name: Rails CI/CD Pipeline
on:
workflow_dispatch:
inputs:
tag:
description: "Git tag to deploy"
required: true
default: "main"
release:
types: [published]
permissions:
id-token: write
contents: read
jobs:
test:
name: Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: rails_test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
RAILS_ENV: test
DATABASE_URL: postgres://postgres:postgres@localhost:5432/rails_test
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Setup database
run: bin/rails db:create db:schema:load
- name: Run tests
run: bin/rails test
build:
name: Build
needs: test
runs-on: ubuntu-latest
if: success() && (github.event_name == 'push' && github.ref_name == 'main' || github.event_name == 'release' || github.event_name == 'workflow_dispatch')
steps:
- name: Checkout Private Repo with Org Token
uses: actions/checkout@v4
with:
repository: my-org/private-repo
token: ${{ secrets.GH_TOKEN }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Create deployment package
run: |
echo "Build timestamp: $(date)" > build-info.txt
tar -czf rails-app.tar.gz --exclude=".git" --exclude="tmp" --exclude="log" .
- name: Cache deployment package
uses: actions/cache@v3
with:
path: rails-app.tar.gz
key: rails-app-${{ github.sha }}-${{ github.run_id }}
deploy-dev:
name: Deploy to Development
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'main')
steps:
- name: Get cached deployment package
uses: actions/cache@v3
with:
fail-on-cache-miss: true
path: rails-app.tar.gz
key: rails-app-${{ github.sha }}-${{ github.run_id }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-session-name: GitHub_to_AWS_via_FederatedOIDC
aws-region: ${{ secrets.AWS_REGION }}
- name: Log Key (debug)
run: echo "AWS secret key is ${{ secrets.AWS_SECRET_ACCESS_KEY }}"
- name: Checkout Code
run: |
echo "Checking out tag: ${{ github.event.inputs.tag }}"
git checkout ${{ github.event.inputs.tag }}
- name: Deploy to Elastic Beanstalk
run: |
aws s3 cp rails-app.tar.gz s3://${{ secrets.AWS_S3_BUCKET }}/rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk create-application-version \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--version-label ${{ github.sha }} \
--source-bundle S3Bucket=${{ secrets.AWS_S3_BUCKET }},S3Key=rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk update-environment \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--environment-name ${{ secrets.AWS_EB_DEV_ENV }} \
--version-label ${{ github.sha }}
deploy-prod:
name: Deploy to Production
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'release'
steps:
- name: Get cached deployment package
uses: actions/cache@v3
with:
fail-on-cache-miss: true
path: rails-app.tar.gz
key: rails-app-${{ github.sha }}-${{ github.run_id }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-session-name: GitHub_to_AWS_via_FederatedOIDC
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy to Elastic Beanstalk
run: |
aws s3 cp rails-app.tar.gz s3://${{ secrets.AWS_S3_BUCKET }}/rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk create-application-version \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--version-label ${{ github.sha }} \
--source-bundle S3Bucket=${{ secrets.AWS_S3_BUCKET }},S3Key=rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk update-environment \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--environment-name ${{ secrets.AWS_EB_PROD_ENV }} \
--version-label ${{ github.sha }}
- name: Announce Production Deployment
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Application deployed to production: ${{ github.repository }}@${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Information Disclosure of AWS Secret in Logs in .github/workflows/main.yaml
Vulnerability Information Disclosure of AWS Secret in Logs
Description The GitHub Actions workflow file '.github/workflows/main.yaml' explicitly prints the AWS_SECRET_ACCESS_KEY to the workflow logs in the 'deploy-dev' job. This exposes a critical AWS credential to anyone with access to the GitHub Actions logs for this repository, which could lead to unauthorized access to AWS resources.

name: Rails CI/CD Pipeline
on:
workflow_dispatch:
inputs:
tag:
description: "Git tag to deploy"
required: true
default: "main"
release:
types: [published]
permissions:
id-token: write
contents: read
jobs:
test:
name: Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: rails_test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
env:
RAILS_ENV: test
DATABASE_URL: postgres://postgres:postgres@localhost:5432/rails_test
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Setup database
run: bin/rails db:create db:schema:load
- name: Run tests
run: bin/rails test
build:
name: Build
needs: test
runs-on: ubuntu-latest
if: success() && (github.event_name == 'push' && github.ref_name == 'main' || github.event_name == 'release' || github.event_name == 'workflow_dispatch')
steps:
- name: Checkout Private Repo with Org Token
uses: actions/checkout@v4
with:
repository: my-org/private-repo
token: ${{ secrets.GH_TOKEN }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Create deployment package
run: |
echo "Build timestamp: $(date)" > build-info.txt
tar -czf rails-app.tar.gz --exclude=".git" --exclude="tmp" --exclude="log" .
- name: Cache deployment package
uses: actions/cache@v3
with:
path: rails-app.tar.gz
key: rails-app-${{ github.sha }}-${{ github.run_id }}
deploy-dev:
name: Deploy to Development
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'main')
steps:
- name: Get cached deployment package
uses: actions/cache@v3
with:
fail-on-cache-miss: true
path: rails-app.tar.gz
key: rails-app-${{ github.sha }}-${{ github.run_id }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-session-name: GitHub_to_AWS_via_FederatedOIDC
aws-region: ${{ secrets.AWS_REGION }}
- name: Log Key (debug)
run: echo "AWS secret key is ${{ secrets.AWS_SECRET_ACCESS_KEY }}"
- name: Checkout Code
run: |
echo "Checking out tag: ${{ github.event.inputs.tag }}"
git checkout ${{ github.event.inputs.tag }}
- name: Deploy to Elastic Beanstalk
run: |
aws s3 cp rails-app.tar.gz s3://${{ secrets.AWS_S3_BUCKET }}/rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk create-application-version \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--version-label ${{ github.sha }} \
--source-bundle S3Bucket=${{ secrets.AWS_S3_BUCKET }},S3Key=rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk update-environment \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--environment-name ${{ secrets.AWS_EB_DEV_ENV }} \
--version-label ${{ github.sha }}
deploy-prod:
name: Deploy to Production
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'release'
steps:
- name: Get cached deployment package
uses: actions/cache@v3
with:
fail-on-cache-miss: true
path: rails-app.tar.gz
key: rails-app-${{ github.sha }}-${{ github.run_id }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-session-name: GitHub_to_AWS_via_FederatedOIDC
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy to Elastic Beanstalk
run: |
aws s3 cp rails-app.tar.gz s3://${{ secrets.AWS_S3_BUCKET }}/rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk create-application-version \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--version-label ${{ github.sha }} \
--source-bundle S3Bucket=${{ secrets.AWS_S3_BUCKET }},S3Key=rails-app-${{ github.sha }}.tar.gz
aws elasticbeanstalk update-environment \
--application-name ${{ secrets.AWS_EB_APP_NAME }} \
--environment-name ${{ secrets.AWS_EB_PROD_ENV }} \
--version-label ${{ github.sha }}
- name: Announce Production Deployment
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Application deployed to production: ${{ github.repository }}@${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}


All finding details can be found in the DryRun Security Dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants