github-actions — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited github-actions (Agent Skill) and scored it 91/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} is the classic direct prompt-injection phrasing. Placed in a skill body that the agent reads as trusted instructions, it tries to make the agent abandon its prior rules and follow whatever comes next — a full system-prompt override.
ignore/disregard/forget … previous instructions sentence.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
All workflows live in .github/workflows/ as YAML files.
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
name: Test
runs-on: ubuntu-latest # or: ubuntu-22.04, windows-latest, macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run lint
run: npm run lint
- name: Run tests
run: npm test -- --coverage - name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install dependencies
run: pip install -r requirements.txt -r requirements-dev.txt
- name: Lint with ruff
run: ruff check .
- name: Type check with mypy
run: mypy .
- name: Run tests
run: pytest --cov=. --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }} - name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- name: Download dependencies
run: go mod download
- name: Run vet
run: go vet ./...
- name: Run tests
run: go test -race -coverprofile=coverage.out ./...Test across multiple versions simultaneously:
jobs:
test:
strategy:
fail-fast: false # don't cancel others if one fails
matrix:
node-version: ['18', '20', '22']
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test# Node.js - built into setup-node
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # or 'yarn', 'pnpm'
# Python - built into setup-python
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
# Manual cache for arbitrary files
- uses: actions/cache@v4
with:
path: |
~/.cache/pip
~/.cargo/registry
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
restore-keys: |
${{ runner.os }}-pip-jobs:
deploy:
environment: production # uses GitHub Environment protection rules
steps:
- name: Deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
NODE_ENV: production
run: ./scripts/deploy.shSecret management rules:
Pinning third-party actions:
(e.g. uses: some/action@<40-char-sha> # v3.1.0). A mutable tag like @v3 can be force-pushed to point at malicious code, so a SHA is the only immutable reference.
actions/* pinned to a major tag (@v4) is the common, acceptable baseline;pin to SHAs when your threat model requires strict supply-chain guarantees.
name: Build and Push Docker Image
on:
push:
branches: [main]
tags: ['v*']
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} # built-in, no setup needed
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha,prefix=,suffix=,format=short
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=maxname: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# ─── CI: Test and Lint ──────────────────────────────────────────────────────
ci:
name: Test and Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test -- --coverage
# ─── CD: Deploy to Staging ─────────────────────────────────────────────────
deploy-staging:
name: Deploy to Staging
needs: ci
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: staging
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
env:
DEPLOY_KEY: ${{ secrets.STAGING_DEPLOY_KEY }}
run: ./scripts/deploy.sh staging
# ─── CD: Deploy to Production (manual approval required) ───────────────────
deploy-production:
name: Deploy to Production
needs: deploy-staging
runs-on: ubuntu-latest
environment: production # has required reviewers configured
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to production
env:
DEPLOY_KEY: ${{ secrets.PROD_DEPLOY_KEY }}
run: ./scripts/deploy.sh productionname: Release
on:
push:
tags: ['v*']
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # for changelog generation
- name: Build
run: npm ci && npm run build
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
dist/*.zip
dist/*.tar.gz# .github/workflows/reusable-test.yml
on:
workflow_call:
inputs:
node-version:
type: string
default: '20'
secrets:
CODECOV_TOKEN:
required: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci && npm test
# ─── Call from another workflow ───────────────────────────────────────────────
# .github/workflows/ci.yml
jobs:
test:
uses: ./.github/workflows/reusable-test.yml
with:
node-version: '20'
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}pull_request for untrusted codeactions/checkout@v4npm ci (not npm install) in CI for reproducible installs${{ secrets.NAME }}fail-fast: false for visibility~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.