-
Notifications
You must be signed in to change notification settings - Fork 0
155 lines (132 loc) · 5.21 KB
/
template-security.yml
File metadata and controls
155 lines (132 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
name: Template Security Scan
on:
pull_request:
branches: [ "main" ]
push:
branches: [ "main" ]
jobs:
template-security:
name: Template Security
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Install WASM workloads
run: dotnet workload install wasm-experimental wasm-tools
- name: Pack framework packages to local feed
run: |
LOCAL_FEED=$(pwd)/local-packages
mkdir -p "$LOCAL_FEED"
PACK_VERSION="1.0.0-ci"
for project in \
Picea.Abies/Picea.Abies.csproj \
Picea.Abies.Browser/Picea.Abies.Browser.csproj \
Picea.Abies.Server/Picea.Abies.Server.csproj \
Picea.Abies.Server.Kestrel/Picea.Abies.Server.Kestrel.csproj; do
dotnet pack "$project" -c Release -o "$LOCAL_FEED" \
-p:Version="$PACK_VERSION" \
-p:PackageVersion="$PACK_VERSION"
done
env:
DOTNET_NUGET_AUDIT: "false"
- name: Create NuGet config for template builds
run: |
cat > /tmp/template-security-nuget.config <<EOF
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="local" value="$(pwd)/local-packages" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
EOF
- name: Install template pack from source
run: dotnet new install Picea.Abies.Templates/
- name: Scaffold templates for security scanning
run: |
OUT_ROOT="$(pwd)/template-security-out"
rm -rf "$OUT_ROOT"
mkdir -p "$OUT_ROOT"
dotnet new abies-browser -o "$OUT_ROOT/abies-browser"
dotnet new abies-browser-empty -o "$OUT_ROOT/abies-browser-empty"
dotnet new abies-server -o "$OUT_ROOT/abies-server"
- name: Build and SCA scan scaffolded templates
run: |
OUT_ROOT="$(pwd)/template-security-out"
for project in \
"$OUT_ROOT/abies-browser" \
"$OUT_ROOT/abies-browser-empty" \
"$OUT_ROOT/abies-server"; do
echo "🔨 Restoring $project"
dotnet restore "$project" --configfile /tmp/template-security-nuget.config
echo "🔨 Building $project"
dotnet build "$project" --no-restore
echo "🔍 Running SCA for $project"
report="$project/vulnerability-report.txt"
dotnet list "$project" package --vulnerable --include-transitive 2>&1 | tee "$report"
if grep -qi "critical\|high" "$report"; then
echo "❌ High/Critical vulnerabilities found in scaffolded template project: $project"
exit 1
fi
done
- name: Trivy scan scaffolded templates
uses: aquasecurity/trivy-action@v0.35.0
with:
scan-type: fs
scan-ref: template-security-out
format: table
severity: HIGH,CRITICAL
ignore-unfixed: true
scanners: vuln,misconfig,secret
exit-code: '1'
- name: Install Semgrep CLI
run: python3 -m pip install --user semgrep
- name: Semgrep scan scaffolded template output
run: |
export PATH="$HOME/.local/bin:$PATH"
if ! semgrep scan \
--config .semgrep/rules/template-security.yml \
--json \
--output template-security-out/semgrep-template-output.json \
template-security-out; then
code=$?
# Semgrep may return 2 for non-fatal warnings; findings are enforced below via JSON parsing.
if [ "$code" -ne 2 ]; then
exit "$code"
fi
fi
- name: Enforce no ERROR findings in scaffolded output
run: |
python3 - <<'PY'
import json
from pathlib import Path
report = Path("template-security-out/semgrep-template-output.json")
if not report.exists():
raise SystemExit("Semgrep report not found")
data = json.loads(report.read_text())
errors = [r for r in data.get("results", []) if r.get("extra", {}).get("severity") == "ERROR"]
if errors:
print(f"Found {len(errors)} ERROR-level Semgrep findings in scaffolded output")
for finding in errors[:20]:
path = finding.get("path")
check = finding.get("check_id")
msg = finding.get("extra", {}).get("message")
print(f"- {check} :: {path} :: {msg}")
raise SystemExit(1)
print("No ERROR-level Semgrep findings in scaffolded output")
PY
- name: Upload template security artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: template-security-artifacts
path: |
template-security-out/**/vulnerability-report.txt
template-security-out/semgrep-template-output.json