Repository navigation
156 lines (139 loc) · 4.56 KB
/
Copy pathsecurity.yml
File metadata and controls
156 lines (139 loc) · 4.56 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
156
name: Security Scan
on:
pull_request:
branches: [main]
jobs:
contract-audit:
name: Rust / Soroban Audit
runs-on: ubuntu-latest
permissions:
issues: write # Required to comment on issues
pull-requests: write
defaults:
run:
working-directory: contracts
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: contracts
- name: clippy
run: cargo clippy --all-targets -- -D warnings
- name: cargo audit
run: |
cargo install cargo-audit --locked --quiet
cargo audit 2>&1 | tee /tmp/audit-output.txt
exit ${PIPESTATUS[0]}
- name: Soroban pattern check
run: node ../scripts/soroban-security-check.mjs 2>&1 | tee /tmp/soroban-output.txt
- name: Post contract audit summary
if: always()
# Fork PRs get a read-only token; the summary is best-effort.
continue-on-error: true
uses: actions/github-script@v7
with:
script: |
const fs = require('fs')
const audit = fs.existsSync('/tmp/audit-output.txt')
? fs.readFileSync('/tmp/audit-output.txt', 'utf8').trim()
: '(no output)'
const soroban = fs.existsSync('/tmp/soroban-output.txt')
? fs.readFileSync('/tmp/soroban-output.txt', 'utf8').trim()
: '(no output)'
const body = [
'## 🔐 Contract Security Scan',
'',
'<details><summary>cargo audit</summary>',
'',
'```',
audit,
'```',
'',
'</details>',
'',
'<details><summary>Soroban pattern check</summary>',
'',
'```',
soroban,
'```',
'',
'</details>',
].join('\n')
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
})
frontend-audit:
name: Frontend Audit
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- name: npm audit
# Fail on high/critical issues in shipped (production) dependencies, and
# on critical issues anywhere. Dev-only tooling currently carries a high
# advisory (braces) with no patched release upstream.
run: |
set -o pipefail
npm audit --omit=dev --audit-level=high 2>&1 | tee /tmp/npm-audit.txt
npm audit --audit-level=critical 2>&1 | tee -a /tmp/npm-audit.txt
- name: ESLint security
run: npm run lint 2>&1 | tee /tmp/eslint-output.txt; exit ${PIPESTATUS[0]}
- name: Check for hardcoded secrets
run: |
node scripts/check-secrets.mjs 2>&1 | tee /tmp/secrets-output.txt
exit ${PIPESTATUS[0]}
- name: Post frontend audit summary
if: always()
# Fork PRs get a read-only token; the summary is best-effort.
continue-on-error: true
uses: actions/github-script@v7
with:
script: |
const fs = require('fs')
const read = (p) => fs.existsSync(p) ? fs.readFileSync(p, 'utf8').trim() : '(no output)'
const body = [
'## 🛡️ Frontend Security Scan',
'',
'<details><summary>npm audit</summary>',
'',
'```',
read('/tmp/npm-audit.txt'),
'```',
'',
'</details>',
'',
'<details><summary>ESLint</summary>',
'',
'```',
read('/tmp/eslint-output.txt'),
'```',
'',
'</details>',
'',
'<details><summary>Hardcoded secrets check</summary>',
'',
'```',
read('/tmp/secrets-output.txt'),
'```',
'',
'</details>',
].join('\n')
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
})