📄 View my Resume · Online Preview
- Telegram (fastest) — @vuln7_lab
- Email —
18617339965@163.com - Resume — github.com/li-jin-quan/resume (PDF + online preview)
Building something in AI security, or need a second pair of eyes on a Rust / ML supply-chain issue? DM me on Telegram — I read everything, and I answer security reports first.
Offensive-security-minded engineer who builds and breaks systems for a living — then ships the fixes.
- 🕵️ Security researcher — independent audits of the Rust AI/ML supply chain: 24 upstream PRs submitted (CWE-770 / CWE-190 / CWE-248 class), of which 7 are merged — 4 in
sonos/tract, 1 inhuggingface/hf-hub, 1 inzip-rs/zip2, 1 intracel-ai/burn— and 14 are under review (four are non-security: one feature, two test-only changes, one documentation-only). Every one is a substantive change to upstream code, not a typo fix — see the list below. - 🌐 International bounty experience — registered researcher on HackerOne (
0xNuoyaArk) and Immunefi (Web3 / smart-contract security); familiar with report writing and triage workflows end to end. - 🦀 Rust deep-diver — using Rust since 2016; strong on ownership, borrowing,
unsafe, FFI, and system-level security. - 🤖 AI-native — private LLM deployment, AI coding assistants, RAG-based customer service, DevSecOps.
- 🏗️ 10+ years experience since 2016: chip test systems, security tooling, microservices architecture.
- 🌱 Building an AI Security venture — guardrails, red-team automation, secure-by-design AI products.
- 💬 Ask me about Rust · Web3 security · AI security · DevSecOps · Reverse engineering.
| PR | What it fixes |
|---|---|
| #202 | huggingface/hf-hub — download_file_to_bytes pre-allocated its buffer from the server-declared Content-Length / X-Linked-Size header before reading a single body byte, so an untrusted endpoint could drive the allocation (CWE-770). Merged 2026-09-16 — my first merged PR in HuggingFace |
| #2766 | Harden read_tensor against untrusted NNEF string lengths — untrusted length fields drove unchecked allocations (CWE-770) |
| #2795 | fix(data): check tensor shape arithmetic before allocation — overflow in shape math before the allocation (CWE-190 / CWE-770) |
| #2796 | fix(tensorflow): return errors instead of panicking — malformed TensorProto panicked instead of erroring (CWE-248) |
| #2814 | Add missing sign checks on loader dims casts (onnx / tflite) — negative dims became huge usize after the cast |
| #984 | zip-rs/zip2 — a symlink entry with a huge declared size drove with_capacity before a single byte was read (CWE-770). Merged through GitHub's merge queue on 2026-09-14; not in a release yet |
| #5667 | tracel-ai/burn — a sparse file reported a 3.4 TB size, bypassing the metadata-based length check and driving a multi-TB allocation in the MNIST reader; item counts are now capped at the split size (CWE-770). Merged 2026-09-14; not in a release yet |
GHSA-6ffw-f7m6-gpxj — I'm credited as the reporter. The advisory is currently in draft upstream (CVE requested, not yet assigned); draft advisories aren't public, so the GHSA link will 404 until the maintainers publish it.
Under review — 14 PRs across upstream projects (click to expand)
| Repo | PR | What it fixes | Size |
|---|---|---|---|
| huggingface/candle | #3970 | ggml: unbounded allocations from untrusted values | +126 |
| huggingface/candle | #3962 | npy: unbounded allocation when reading arrays | +38 |
| huggingface/candle | #3961 | pickle: unbounded allocation in binary protocol | +53 |
| daac-tools/vibrato | #167 | dictionary: connection matrix allocation | +66 |
| not-fl3/nanoserde | #172 | DeBin vs untrusted length prefixes |
+110 |
| finalfusion/finalfusion-rust | #203 | format readers vs untrusted length prefixes | +272 |
| ExpHP/npyz | #84 | read_header vs untrusted header_size |
+16 |
| contentauth/c2pa-rs | #2664 | OCSP good response outside its validity window was reported as revoked |
+31 / −8 |
| contentauth/c2pa-rs | #2662 | regression test for a signing cert with no Organization attribute | +116 |
| contentauth/c2pa-rs | #2665 | documentation follow-up requested in maintainer review — not a security fix | +5 |
| zurawiki/tiktoken-rs | #166 | _decode_native_and_split out-of-bounds |
+62 |
| jturner314/ndarray-npy | #106 | bound allocations by data actually present | +262 |
| KeeperHub/agentic-wallet | #40 | feature work (MCP pre-execution tool), not a security fix | +202 |
| KeeperHub/cli | #114 | test fix (Windows HOME / USERPROFILE isolation), not a security fix |
+31 / −13 |
These are all awaiting maintainer review — none has been merged yet.
One PR was closed without merging: zip2#992 (legacy decoders reserved from the declared uncompressed size). The maintainer preferred #991, which caps the pre-allocation rather than removing it, for performance. Fair call — #991 is the better fix.
I found a panic in rustsec_refs_imported(): malformed OSV reference URLs hit a hard-coded
byte-slice plus .expect(), crashing cargo-audit / cargo-deny for downstream users.
My fix (#1686) replaced it with
strip_prefix() + filter_map() and added unit tests (+79 / −5, no behaviour change for
valid input).
A community fix (#1683) had already been filed, so mine was closed as a duplicate — it was never merged. #1683 is still open upstream, so the bug itself remains unfixed today.
Listed for the record. The merged work is the PRs listed above.
crackmes-writeups — crackmes.one
challenges (Windows x86-64 Rust binaries) solved by static analysis with pefile +
capstone.
- 1 ✅ solved · 1 ✅ proven unsolvable-as-shipped (AES-256-GCM container fully recovered and documented) · 1 ⏳ in progress
I publish the unsolved one on purpose. A portfolio that only shows wins is not a portfolio, it's marketing.
An AI Security venture — guardrails, red-team automation, and secure-by-design AI products.
I think like an attacker (white-hat) and build like an engineer — the combination AI security actually needs.
Security isn't a feature — it's a mindset.
