Skip to content

attempt to improve security #2

attempt to improve security

attempt to improve security #2

Workflow file for this run

name: Check and update workflow action references
on:
schedule:
- cron: '0 0 * * 1' # Run weekly on Mondays
workflow_dispatch: # Allow manual trigger
jobs:
check-and-update-workflows:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Python
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0

Check failure on line 19 in .github/workflows/sha-pins.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/sha-pins.yml

Invalid workflow file

You have an error in your yaml syntax on line 19
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install PyGithub pyyaml
- name: Check workflows and update action references
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python - <<'EOF'
import os
import re
import yaml
import requests
from github import Github
# Initialize GitHub client
g = Github(os.environ["GITHUB_TOKEN"])
repo = g.get_repo(os.environ["GITHUB_REPOSITORY"])
def get_latest_sha(action_owner, action_name, version):
# Get the latest SHA for the given action and version
url = f"https://api.github.com/repos/{action_owner}/{action_name}/commits/{version}"
headers = {"Accept": "application/vnd.github.v3+json"}
if "GITHUB_TOKEN" in os.environ:
headers["Authorization"] = f"token {os.environ['GITHUB_TOKEN']}"
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()["sha"]
return None
# Get all workflow files
workflow_dir = ".github/workflows"
updates = {}
for filename in os.listdir(workflow_dir):
if filename.endswith((".yml", ".yaml")) and filename != "sha.yml":
filepath = os.path.join(workflow_dir, filename)
with open(filepath, 'r') as f:
content = f.read()
# Look for uses: statements that don't include SHA
lines = content.split('\n')
updated_lines = lines.copy()
needs_update = False
for i, line in enumerate(lines):
# Match pattern like: uses: actions/checkout@v3 or uses: owner/repo@v1.2.3
matches = re.search(r'^\s*uses:\s+([a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+)@(v\d+[^\s#]*)(?:\s+#.*)?$', line)
if matches:
action = matches.group(1)
version = matches.group(2)
# Skip if line already has SHA comment
if not re.search(r'#\s*[a-f0-9]{40}', line):
sha = get_latest_sha(action.split('/')[0], action.split('/')[1], version)
if sha:
# Update line with SHA as comment
updated_line = re.sub(r'@(v\d+[^\s#]*)(?:\s+#.*)?$', f'@{sha[:40]} # {version}', line)
updated_lines[i] = updated_line
needs_update = True
print(f"Updating {filename}: {line.strip()} -> {updated_line.strip()}")
if needs_update:
updates[filepath] = '\n'.join(updated_lines)
if updates:
branch_name = f"action-sha-updates-{os.environ.get('GITHUB_RUN_ID', '')}"
default_branch = repo.default_branch
# Create a new branch
ref = f"refs/heads/{branch_name}"
try:
repo.create_git_ref(ref=ref, sha=repo.get_branch(default_branch).commit.sha)
except Exception as e:
print(f"Error creating branch: {e}")
exit(1)
# Update files
commit_message = "chore: update GitHub Action references with SHA pins"
for filepath, content in updates.items():
try:
file = repo.get_contents(filepath, ref=branch_name)
repo.update_file(filepath, commit_message, content, file.sha, branch=branch_name)
except Exception as e:
print(f"Error updating {filepath}: {e}")
# Create PR
try:
pr = repo.create_pull(
title="Update GitHub Action references with SHA pins",
body="This PR updates GitHub Action references to include SHA pins for better security and reproducibility.",
head=branch_name,
base=default_branch
)
print(f"Created PR #{pr.number}: {pr.html_url}")
except Exception as e:
print(f"Error creating PR: {e}")
else:
print("No updates needed - all action references already use SHA pins.")
EOF