Skip to content

Commit c617068

Browse files
authored
Add security auditing workflow (#526)
1 parent 9cc7760 commit c617068

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
name: Security Audit
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
security-audit:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
steps:
13+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
14+
with:
15+
fetch-depth: 0
16+
17+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
18+
with:
19+
node-version: "20"
20+
21+
- name: Install Claude Code
22+
run: npm install -g @anthropic-ai/claude-code
23+
24+
- name: Generate diff
25+
run: git diff ${{ github.event.before }}...${{ github.sha }} > /tmp/changes.diff
26+
27+
- name: Run security audit
28+
id: audit
29+
env:
30+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
31+
run: |
32+
{
33+
cat <<'PROMPT'
34+
You are a senior security engineer performing a penetration-test-style review of a
35+
change that just landed on the main branch of the kernels project — a mixed Nix/Python/
36+
Rust project for building, fetching and loading compute kernels. The kernels library
37+
downloads, loads, and runs code an user's computers, so treat the attack surface
38+
accordingly.
39+
40+
A brief overiew of the most important project directories:
41+
42+
* `kernel-abi-check`: the ABI check parses kernel binaries and checks that they are ABI3
43+
and manylinux-compliant.
44+
* `kernel-builder`: this is the main user interface for building and uploading kernels,
45+
though it also generates CMake/pyproject files which are used by the NIx builder.
46+
* `kernels`: Python package that can download and load kernels from Hugging Face Hub.
47+
* `kernels-data`: data structures shared by `kernel-builder` and `kernels`.
48+
* `nix-builder`: Nix code that drives kernel building, also contains Nix derivations for
49+
some dependencies.
50+
51+
The diff of the change follows below. You also have access to the full repository —
52+
explore it when the diff alone is not sufficient to assess impact (e.g. to check whether
53+
a removed guard is relied upon elsewhere, or to understand the data flow around a
54+
changed function).
55+
56+
Think like an attacker. Consider how the `kernels` package could be abused to load
57+
malicious code on a user's computer or how tests could fetch untrusted code that could
58+
compromise CI. Evaluate how an attacker could slip backdoors into the builder that would
59+
add malicious code to kernels that are built. Of course, also evaluate for other possible
60+
vulnerabilities.
61+
62+
63+
Focus on:
64+
- **Remote code execution and trust model:** The system's core purpose is to fetch and
65+
execute native code from the Hub. Review changes to trust gates (`trust_remote_code`,
66+
the trusted-org allowlist, signing identity verification stubs), redirect resolution
67+
in `kernel-status.toml`, and any path that allows bypassing the trust check — especially
68+
environment variable overrides that substitute a local path without re-checking trust.
69+
- **Build artifact integrity:** Review the full chain from build → lockfile → runtime hash
70+
verification. Look for gaps where downloaded content is executed without being validated
71+
against a lock (e.g. when `variant_locks` is not threaded through), weakening of the hash
72+
algorithm or comparison, and whether symlink-only hashing creates blind spots for injected
73+
files.
74+
- **Path traversal and injection via metadata:** Kernel metadata fields (names, IDs, variant
75+
strings) flow from Hub-served JSON into filesystem path construction. Check for unsanitized
76+
use of these values to traverse outside expected directories, and for module name fields
77+
that could shadow Python standard library or third-party modules via `sys.modules`.
78+
- **Binary parsing safety in kernel-abi-check:** The checker parses untrusted ELF and Mach-O
79+
binaries with the `object` crate. Review for memory safety issues, panics on malformed inputs,
80+
integer overflows in offset/size calculations, and whether a crafted binary could produce a
81+
false-clean result and slip through the ABI gate.
82+
- **ABI and symbol allowlist bypass:** The manylinux and Python ABI checks define what symbols a
83+
kernel is allowed to export or import. Look for logic errors that could allow a malicious or
84+
malformed kernel to pass the check despite using forbidden symbols, and for coverage gaps in
85+
the allowlist itself (new symbol versions, new platforms, tvm-ffi vs. Torch paths).
86+
- **Nix build sandbox integrity:** Kernel builds are isolated via Nix sandboxing. Review changes
87+
that weaken sandbox settings (`sandbox = relaxed`, `sandbox = false`), that add network access
88+
or impure inputs to build derivations, or that allow build-time code to write output outside
89+
the declared store path.
90+
- **Supply chain: pinned dependencies and lockfiles:** Review changes to `flake.lock`,
91+
`Cargo.lock`, `uv.lock`, `python_depends.json`, and pinned GitHub Actions SHAs. Unpinned or
92+
updated dependencies — especially C/C++ CUDA toolchain packages, PyTorch, or Hub client
93+
libraries — are high-impact supply chain risk.
94+
- **CI/CD security:** Workflow permission scopes (`contents: write`, `id-token: write`), secret
95+
exposure in run steps, script injection via PR-controlled strings interpolated into `run:`
96+
blocks, and whether untrusted PR code can reach jobs that hold publishing or signing credentials.
97+
- **Credential and token handling:** The Rust builder and Python loader both interact with the
98+
Hugging Face API using user tokens. Review for token leakage into logs, user-agent strings,
99+
error messages, or artifact metadata, and for changes that widen the set of operations performed
100+
with elevated credentials.
101+
- **Denial of service:** Algorithmic complexity in variant resolution and ABI symbol scanning,
102+
unbounded downloads or memory allocation when processing Hub responses or binary files, and
103+
zip/archive expansion if any archive formats are introduced.
104+
- **Information disclosure:** System details (glibc version, CUDA version, platform, Python
105+
version) emitted in telemetry or user-agent strings; kernel metadata or error messages that
106+
leak internal paths, cache layout, or token scopes.
107+
108+
For each finding, assess exploitability — not just theoretical presence.
109+
110+
If you find security issues, output your report formatted for Slack using mrkdwn syntax.
111+
Use this structure:
112+
113+
*[SEVERITY]* `file:lines` — Title
114+
Description of the vulnerability and how it could be exploited.
115+
_Suggestion:_ How to fix.
116+
117+
Separate multiple findings with blank lines. Be concise but specific.
118+
119+
If no security issues are found, output exactly: NO_FINDINGS
120+
121+
=== DIFF ===
122+
PROMPT
123+
cat /tmp/changes.diff
124+
} | claude -p --model claude-opus-4-6 > /tmp/audit_result.txt
125+
126+
if grep -q "NO_FINDINGS" /tmp/audit_result.txt; then
127+
echo "has_findings=false" >> "$GITHUB_OUTPUT"
128+
echo "Security audit complete — no findings."
129+
else
130+
echo "has_findings=true" >> "$GITHUB_OUTPUT"
131+
echo "Security audit complete — findings detected, notifying Slack."
132+
fi
133+
134+
- name: Notify Slack
135+
if: steps.audit.outputs.has_findings == 'true'
136+
env:
137+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_SECURITY }}
138+
COMMIT_URL: ${{ github.event.head_commit.url }}
139+
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
140+
COMMIT_AUTHOR: ${{ github.event.head_commit.author.username || github.event.head_commit.author.name }}
141+
run: |
142+
FINDINGS=$(cat /tmp/audit_result.txt)
143+
COMMIT_TITLE=$(printf '%s\n' "$COMMIT_MESSAGE" | head -n1)
144+
145+
printf -v HEADER '*Security Audit Finding*\n*Commit:* <%s|%s>\n*Author:* %s\n\n---\n\n' \
146+
"$COMMIT_URL" "$COMMIT_TITLE" "$COMMIT_AUTHOR"
147+
148+
jq -n \
149+
--arg text "${HEADER}${FINDINGS}" \
150+
'{"text": $text}' > /tmp/slack_payload.json
151+
152+
curl -sf -X POST "$SLACK_WEBHOOK_URL" \
153+
-H 'Content-Type: application/json' \
154+
-d @/tmp/slack_payload.json

0 commit comments

Comments
 (0)