-
Notifications
You must be signed in to change notification settings - Fork 0
cast init generate devsecops.yml but has syntax error #5
Copy link
Copy link
Closed
Description
I used cast init and select the 2 then generate
[Invalid workflow file: .github/workflows/devsecops.yml#L163](https://github.com/castops/tests/actions/runs/23688702679/workflow)
You have an error in your yaml syntax on line 163here are the devsecops.yml
# CAST — DevSecOps Pipeline for Node.js
# https://github.com/castops/cast
#
# Includes:
# 1. Secrets Detection — Gitleaks
# 2. SAST — Semgrep
# 3. SCA — npm audit
# 4. Container Security — Trivy (skipped if no Dockerfile)
# 5. Code Quality — ESLint
# 6. Security Gate — conftest policy evaluation on SARIF findings
name: CAST DevSecOps
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:
permissions:
contents: read
security-events: write # required for SARIF upload to GitHub Security tab
actions: read
jobs:
# ── 1. Secrets Detection ───────────────────────────────────────────────────
secrets:
name: Secrets Detection
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so Gitleaks can scan all commits
- name: Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ── 2. SAST ────────────────────────────────────────────────────────────────
sast:
name: SAST
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- name: Semgrep scan
run: semgrep ci --sarif --output=semgrep.sarif || true
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- name: Upload to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: semgrep.sarif
- name: Upload SARIF artifact
uses: actions/upload-artifact@v4
if: always()
with:
name: cast-sarif-sast
path: semgrep.sarif
# ── 3. SCA — Dependency Audit ──────────────────────────────────────────────
sca:
name: SCA
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: npm
- name: Install dependencies
run: npm ci --prefer-offline
- name: npm audit
run: npm audit --audit-level=high
# ── 4. Container Security ──────────────────────────────────────────────────
container:
name: Container Security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for Dockerfile
id: check_dockerfile
run: |
if [ -f Dockerfile ]; then
echo "found=true" >> $GITHUB_OUTPUT
else
echo "No Dockerfile found — skipping container scan"
echo "found=false" >> $GITHUB_OUTPUT
fi
- name: Build image
if: steps.check_dockerfile.outputs.found == 'true'
run: docker build -t cast-scan:${{ github.sha }} .
- name: Trivy scan
if: steps.check_dockerfile.outputs.found == 'true'
uses: aquasecurity/trivy-action@master
with:
image-ref: cast-scan:${{ github.sha }}
format: sarif
output: trivy.sarif
severity: CRITICAL,HIGH
exit-code: "0" # gate handles blocking, not trivy directly
- name: Upload to GitHub Security tab
if: steps.check_dockerfile.outputs.found == 'true'
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy.sarif
- name: Upload SARIF artifact
if: steps.check_dockerfile.outputs.found == 'true'
uses: actions/upload-artifact@v4
with:
name: cast-sarif-container
path: trivy.sarif
# ── 5. Code Quality ────────────────────────────────────────────────────────
quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: npm
- name: Install dependencies
run: npm ci --prefer-offline
- name: ESLint
run: npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0
# ── 6. Security Gate ───────────────────────────────────────────────────────
gate:
name: Security Gate
runs-on: ubuntu-latest
needs: [secrets, sast, sca, container, quality]
if: always()
steps:
- uses: actions/checkout@v4
- name: Download SARIF results
uses: actions/download-artifact@v4
with:
pattern: cast-sarif-*
path: sarif-results/
merge-multiple: true
continue-on-error: true
- name: Install conftest
run: |
curl -fsSL -o conftest.tar.gz \
https://github.com/open-policy-agent/conftest/releases/download/v0.50.0/conftest_0.50.0_Linux_x86_64.tar.gz
tar xzf conftest.tar.gz conftest
chmod +x conftest && sudo mv conftest /usr/local/bin/
- name: Write default policy
run: |
# Use local policy/ directory if present; otherwise write the built-in default.
# For strict/permissive mode, copy the desired .rego from:
# https://github.com/castops/cast/tree/main/policy
if [ ! -d policy ] || [ -z "$(ls -A policy/*.rego 2>/dev/null)" ]; then
mkdir -p policy
cat > policy/active.rego << 'REGO'
package main
import future.keywords.if
import future.keywords.in
deny[msg] if {
run := input.runs[_]
result := run.results[_]
result.level == "error"
tool := run.tool.driver.name
msg := sprintf("[CRITICAL] %s — %s (rule: %s)", [tool, result.message.text, result.ruleId])
}
REGO
fi
- name: Evaluate policy
run: |
GATE_FAILED=0
# Run conftest on any SARIF files collected
if compgen -G "sarif-results/*.sarif" > /dev/null 2>&1; then
conftest test sarif-results/*.sarif --policy policy/ \
|| GATE_FAILED=1
fi
# Check job results for non-SARIF tools
if [[ "${{ needs.secrets.result }}" == "failure" ]]; then
echo "❌ Secrets Detection failed"
GATE_FAILED=1
fi
if [[ "${{ needs.sca.result }}" == "failure" ]]; then
echo "❌ SCA (npm audit) failed"
GATE_FAILED=1
fi
if [ "$GATE_FAILED" -eq 1 ]; then
echo "❌ Security gate blocked merge"
exit 1
fi
echo "✅ All security checks passed — safe to merge"Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels