Skip to content
View tritsystem's full-sized avatar

Block or report tritsystem

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
tritsystem/README.md

Hi, I'm Gavin 👋

I research ML security and low-level systems security. I find memory-safety, correctness and isolation bugs in machine-learning libraries and in the native code underneath them, reproduce each one through the real target, fix it upstream, and build the tools and study material that make the next one faster to find and easier to check.

Portfolio: the work, how I learn, and how it all connects · Security track record · The Method · LinkedIn

The record

As of 2026-11-04, from a snapshot of every pull request I've authored in other people's repositories (98 across 54 repos):

  • 35 merged fixes and features across 16 projects. That's 71% of the 49 that have been decided (95% interval 58–82%), with a median of 3.4 days from opening to merge. The other 49 are still open, and I count them as undecided, not failed.
  • 1 published security advisory: GHSA-gvp8-978c-rx2q / CVE-2026-103001. PyJWT.decode() mutated the caller's options dict, so a reused dict could silently switch off claim verification.
  • Memory safety and systems: use-after-free and double free in cfengine, a leak and NULL dereference in DeepSpeed's native shared-memory init, allocation-failure and nftables/netlink fixes in miniupnp, and an authorization-boundary fix in Woodpecker CI.
  • ML correctness: silent precision loss, broken gradients, cross-sample leakage and state that doesn't follow .to(), in kornia, MONAI, timm, transformers, NVIDIA Model-Optimizer, llm-compressor, librosa, snntorch and SpikingJelly.
  • In review: GPU out-of-bounds write and read in bitsandbytes' 4-bit path, shown with compute-sanitizer, with the severity measured rather than assumed (write-up).

Only merged work counts. The table below is regenerated daily from the GitHub API by a workflow: it finds every merged PR I've authored and re-verifies each one before listing it.

35 merged · 7 reported & fixed upstream · refreshed 2026-11-04 10:31 UTC

Repo # What Status
miniupnp #941 netfilter_nft: keep the netlink socket in sync when a rule-cache re... Merged 2026-11
miniupnp #942 upnphttp: check malloc() when sending the 100 Continue response Merged 2026-11
miniupnp #923 miniupnpd/netfilter: create DNAT rules with the kernel's highest re... Merged 2026-11
miniupnp #925 miniupnpd/nftables: keep the remote host of IPv4 port mappings Merged 2026-10
miniupnp #922 miniupnpd/netfilter: check calloc() results in iptables rule builders Merged 2026-10
woodpecker #7365 Harden store scoping for org-level secret and registry retrieval Merged 2026-10
transformers #49767 Fix background_color handling across DeepSeek-VL and Janus image pr... Merged 2026-10
pytorch-image-models #2849 Fix features_only backward with grad checkpointing for in-place ste... Merged 2026-10
llm-compressor #3252 [Quantization] Flag layers narrower than group_size in the early gr... Merged 2026-10
MONAI #9104 fix(networks): AffineHead follows the module's dtype, not just device Merged 2026-10
pytorch-image-models #2848 Fix GCViT global query mixing images within a batch Merged 2026-10
Model-Optimizer #2651 Export unquantized FP8Linear layers in the export dtype, not fp32 Merged 2026-10
MONAI #9103 fix(losses): BarlowTwinsLoss preserves float16/bfloat16 input dtype Merged 2026-10
librosa #2106 Preserve float32 in spectral features; add dtype= to frequency cons... Merged 2026-09
snntorch #454 Add homeostasis: adaptive, time-varying threshold on SpikingNeuron Merged 2026-09
ansible #87503 vars: copy facts in set_host_facts() to stop cross-host fact aliasi... Merged 2026-09
core #6358 Fix use-after-free and double-free in RemoveFilament Merged 2026-09
kornia #4361 fix(geometry): render_gaussian2d pixel-coordinate linspace built at... Merged 2026-09
kornia #4360 fix(enhance): image_histogram2d bin centers built at image.dtype Merged 2026-09
DeepSpeed #8565 Fix memory leak and NULL-deref in shm_initialize Merged 2026-09
snntorch #455 Add neuron_from_equations(): generate a custom neuron class from st... Merged 2026-09
snntorch #453 Add SynapticDelay: per-channel axonal/synaptic delay with a learnab... Merged 2026-09
snntorch #441 Fix LeakyParallel silently ignoring a per-neuron beta; correct the ... Merged 2026-09
kornia #4359 fix(feature): CoarseMatching training-mode gt-padding crash + dtype... Merged 2026-09
kornia #4336 fix(geometry): bbox_to_mask position grid is exact at any image size Merged 2026-09
kornia #4337 fix(augmentation): register fill_value/sigma as buffers, not plain ... Merged 2026-09
ultralytics #26075 Remove stale SAM3 decoder coordinate caches Merged 2026-09
celery #10571 Fix Signature.clone() sharing kwargs with the original signature Merged 2026-09
kornia #4319 fix(feature): register RenderingDeFMO's times as a buffer so .to() ... Merged 2026-09
kornia #4303 fix(geometry): bbox_to_mask3d intersects axis ranges for a full/ove... Merged 2026-09
kornia #4299 fix(geometry): finite gradients for solve_cubic at its acos boundary Merged 2026-09
spikingjelly #744 Fix MSTDPLearner initialising eligibility without a dtype Merged 2026-09
spikingjelly #750 Add RAFNode: resonate-and-fire neuron Merged 2026-09
kornia #4210 fix(augmentation): auto-augment ops preserve float16 / bfloat16 inp... Merged 2026-09
spikingjelly #743 Move tensor reset values with the module in MemoryModule._apply Merged 2026-09
compressed-tensors #920 Group quantization of a layer with fewer columns than group_size fa... Reported; fixed upstream by antar-ghuman (#924, merged 2026-10)
sentence-transformers #4185 v6: models with Normalize at the model root (path "" in modules.j... Reported; fixed upstream by tomaarsen (#4190, merged 2026-10)
compressed-tensors #919 [Convert] ModelOptNvfp4Converter with default/"Linear" targets rela... Reported; fixed upstream by mottopanikeiku (#926, merged 2026-10)
superset #43918 Dataset 'Refresh columns' (fetch_metadata) doesn't bump changed_on,... Reported; fixed upstream by gps23 (#43921, merged 2026-09)
Pillow #9963 Image.copy() aliases mutable .info values (e.g. list-valued "Commen... Reported; fixed upstream by Andrew Murray (#9964, merged 2026-09)
aiohttp #13634 CookieJar.update_cookies() aliases a caller-supplied Morsel instead... Reported; fixed upstream by Sam Bull (#13637, merged 2026-09)
scipy #26095 BUG: scipy.optimize.milp() silently mutates the caller's options di... Reported; fixed upstream by j-bowhay (#26097, merged 2026-09)

Low-level systems

  • spikeling-os: a from-scratch x86_64 kernel (Rust) with its own filesystem, ELF loader, processes and an in-kernel subset-C compiler. Every milestone is verified by two QEMU boots and hand-computed self-tests. Differential fuzzing of the compiler found and fixed real silent miscompiles: 64-bit literals and case labels truncated to 32 bits, and a continue inside a switch that had been dropped for 75 milestones.
  • Native seam audit: a procedure for the Python-to-C/C++/CUDA boundary of ML libraries. Each of its 9 sanitizer and fuzzer configurations is validated on a planted bug before it's trusted, and the blind spots are recorded.
  • pytest-numba-cache: fixes a parallel cache-write race. Crashes fell from 8 of 10 rounds to 0 of 10 (measured on Windows).
  • baton: three LoRA adapters on one frozen model with pre-filled KV caches, hardened against a cache-position bug that ended in a CUDA device-side assert.

ML research

Pre-registered studies with bounded or negative results, reported as such.

  • Spikeling: one spiking-network description runs on Python, C, Verilog and GDScript backends. Event-driven execution was 16–29× faster at low activity, but its resonator neuron didn't beat Goertzel or FFT.
  • Heterogeneous neuron ensembles: a mixed-type ensemble beat all-LIF 60/60 vs 30/60 in Python (study). Its kernel port went through a full retraction (a false positive), then a measured 29/32 vs 12/32.
  • OBSERVE / ternary weights: 20× compression for 7.35 points of accuracy. Local semantic code search that grep still beats when you know the identifier.
  • methodlm: a causal-reasoning harness that cut false causal claims from 100% to about 1%. topological-phononics (preprint): topological protection holds exactly when chiral symmetry does, and the idealized gain doesn't transfer to hardware.

Tools I built for the hunt

  • reagent: 40 bug detectors (32 Python, 8 C) that nominate code from AST patterns, then confirm by running it.
  • crawlspike: a crawler for "one path honors a flag, its sibling drops it". On real OSS so far it has found 5 bugs in itself and 0 in its targets, and it says so.
  • sec-portfolio: the track record, regenerated from the real merged diffs with no model in the loop.

How I learn

  • The Method: measure, don't infer; validate the instrument on a planted case first; pre-register the verdict; report the worst slice; retract overclaims by name.
  • An evidence ladder, T0 to T5: from a grep hit to a fix whose sibling code has been searched and guarded. A finding needs T3 (reproduced through the real target), I file at T4, and I never round up.
  • Study material: an ML systems security curriculum (262 checked links, an 8-hour course, threat models), the ML memory ladder (16 C++/Python labs, each built on a real bug I fixed), the ML ladder, and the playbook.
  • A private research vault: every result is logged the same day, negatives included (575 work notes, 120 lessons). Mistakes become lessons, and lessons become the rules I check before any outward action.

The portfolio page maps how these connect: the curriculum teaches the evidence ladder, the ladder governs the audits, the audits produce fixes, and the fixes become labs in the memory ladder.

I use an AI coding assistant heavily for reproducing, testing and drafting. Every claim here is checked against the public record, and findings still under coordinated disclosure are deliberately left out.

Pinned Loading

  1. 012-trit-search 012-trit-search Public

    Ternary computing research + OBSERVE: a local, private semantic code-search tool (desktop GUI / CLI / MCP server) with a one-line install. Nothing leaves your machine.

    Python 2

  2. methodlm methodlm Public

    Verifiable causal-reasoning harness: pre-registers tests, runs real backdoor adjustment with a robustness value, keeps an honest ledger so any LLM must prove its causal claims. Sibling to OBSERVE.

    Python

  3. observe-api observe-api Public

    Hosted, pay-per-query semantic code search API for AI agents, plus an ACP/Google-UCP-compatible agent-commerce discovery and reputation layer. Live product, real Stripe billing.

    Python

  4. quasicrystal-mems-reservoir quasicrystal-mems-reservoir Public

    Finite-element study of quasicrystal-perforated MEMS resonators and what their mode structure can (and cannot) compute as a physical reservoir. Includes the paper.

    Python

  5. Spikeling Spikeling Public

    A neuromorphic DSL + runtime for spiking neural networks: write a .spk file, run it on Python, C, Verilog, or Godot backends. Includes a Godot game-AI plugin.

    C

  6. symmetry-selection-rule symmetry-selection-rule Public

    Lab report: a symmetry selection rule for computation in phononic / quasicrystal MEMS reservoirs.