DEV Community

Atsushi Suzuki
Atsushi Suzuki

Posted on

Enhance Code Security with GitHub Actions: Automatically Commenting PRs with Docker Scans

To raise the security awareness of our development team, we've integrated a mechanism into our CI using GitHub Actions to conduct security scans on Docker images and automatically add those results as comments to pull requests (PRs).

Screenshot 2024-07-14 9.23.34.png

Overview of the scan-and-comment Job

This job automates a series of steps: checking out the code, building the Docker image, performing the security scan, formatting the results, and finally, posting comments to the PR. We use Trivy for scanning vulnerabilities in Docker images. More details about Trivy can be found in a separate article.

Read about Trivy's vulnerability scanning

Details of the scan-and-comment Job

Below is the complete CI workflow after adding the scan-and-comment job:

name: backend-ci
on:
  push:
    branches:
      - main
      - staging
      - develop
  pull_request:
    types:
      - opened
    paths:
      - "backend/**"
  workflow_dispatch: # For manual execution

jobs:
  setup:
    # Details omitted for brevity

  test:
    # Details omitted for brevity

  lint:
    # Details omitted for brevity

  tsc:
    # Details omitted for brevity

  scan-and-comment:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request' && github.event.action == 'opened'
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build Docker Image
        run: docker build --build-arg ENV=prod -t local-image:latest -f ./backend/Dockerfile.ecs ./backend

      - name: Scan image with Trivy
        uses: aquasecurity/trivy-action@0.24.0
        with:
          image-ref: local-image:latest
          format: "table"
          severity: "CRITICAL,HIGH"
          output: trivy-result.txt

      - name: Check Trivy result file
        run: cat trivy-result.txt

      - name: Format Trivy Scan Result
        run: |
          if [ -s trivy-result.txt ]; then
            echo -e "## Vulnerability Scan Results\n<details><summary>Details</summary>\n\n\`\`\`\n$(cat trivy-result.txt)\n\`\`\`\n</details>" > formatted-trivy-result.md
          else
            echo -e "## Vulnerability Scan Results\nNo vulnerabilities were detected." > formatted-trivy-result.md
          fi

      - name: Comment PR with Trivy scan results
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          path: formatted-trivy-result.md

      - name: Clean up Trivy result file
        run: rm -f trivy-result.txt formatted-trivy-result.md
Enter fullscreen mode Exit fullscreen mode

1. Code Checkout

This job is executed only when a PR is newly created (if: github.event_name == 'pull_request' && github.event.action == 'opened'), ensuring that it does not trigger on syncs or reopens.

scan-and-comment:
  runs-on: ubuntu-latest
  if: github.event_name == 'pull_request' && github.event.action == 'opened'
  steps:
    - name: Checkout code
      uses: actions/checkout@v4
Enter fullscreen mode Exit fullscreen mode

2. Docker Image Build

The Docker image is built using the same settings as the production environment, enhancing the precision of the security scans.

- name: Build Docker Image
  run: docker build --build-arg ENV=prod -t local-image:latest -f ./backend/Dockerfile.ecs ./backend
Enter fullscreen mode Exit fullscreen mode

Below is the Dockerfile used for the build. It's configured for production builds, specifying the ENV=prod parameter to improve security scan accuracy.

FROM node:20.15.0 AS builder

WORKDIR /app

COPY package*.json ./
COPY yarn.lock ./

# Install dependencies ignoring Husky
# Do not use production mode here for yarn build
RUN yarn install --frozen-lockfile --ignore-scripts

COPY . .

RUN yarn build

ARG ENV

# If staging or production environment, remove node_modules and reinstall in production mode
RUN if [ "$ENV" = "prod" ] || [ "$ENV" = "stg" ]; then \
        rm -rf node_modules && yarn install --frozen-lockfile --ignore-scripts --production; \
    fi

FROM node:20.15.0-slim

WORKDIR /app

COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

EXPOSE 8080

CMD ["node", "dist/main"]
Enter fullscreen mode Exit fullscreen mode

3. Image Scan with Trivy

Trivy is used to perform the security scan, and the results are saved in a text file.

- name: Scan image with Trivy
  uses: aquasecurity/trivy-action@0.24.0
  with:
    image-ref: local-image:latest
    format: "table"
    severity: "CRITICAL,HIGH"
    output: trivy-result.txt

- name: Check Trivy result file
  run: cat trivy-result.txt
Enter fullscreen mode Exit fullscreen mode

https://github.com/aquasecurity/trivy-action/tree/master/

4. Format Trivy Scan Results

Based on the scan results, a detailed comment format is created.

- name: Format Trivy Scan Result
  run: |
    if [ -s trivy-result.txt ]; then
      echo -e "## Vulnerability Scan Results\n<details><summary>Details</summary>\n\n\`\`\`\n$(cat trivy-result.txt)\n\`\`\`\n</details>" > formatted-trivy-result.md
    else
      echo -e "## Vulnerability Scan Results\nNo vulnerabilities were detected." > formatted-trivy-result.md
    fi
Enter fullscreen mode Exit fullscreen mode

5. Comment on PR with Trivy Scan Results

The formatted scan results are posted as a comment on the PR.

- name: Comment PR with Trivy scan results
  uses: marocchino/sticky-pull-request-comment@v2
  with:
    path: formatted-trivy-result.md
Enter fullscreen mode Exit fullscreen mode

6. Cleanup

Finally, the used files are deleted to maintain a clean environment.

- name: Clean up Trivy result file
  run: rm -f trivy-result.txt formatted-trivy-result.md
Enter fullscreen mode Exit fullscreen mode

Conclusion

In conclusion, integrating the scan-and-comment job within our CI pipeline using GitHub Actions enhances our security posture by ensuring Docker images are scanned for vulnerabilities at every critical PR juncture. This automation not only streamlines our security checks but also fosters an environment where security consciousness is an integral part of the development process, maintaining high standards across all deployments.

Top comments (0)