Davis Geometric
SCJ / Shadow Clone Jutsu

Turn a vulnerability
into a solvable search.

Fixing a vulnerability in one place leaves a harder question: where else does the same unsafe relationship survive? Different implementations can hide the same missing protection behind different names, operations and control flow. Shadow Clone Jutsu (SCJ) is my research into making those relationships searchable—and their safety conditions testable.

Research setting IBM Security research · Origin in NASA’s Gemini Drift work

01 / The research question

What makes two pieces of code meaningfully alike?

This is a representation problem: how do we describe code so that a meaningful relationship survives changes in its implementation? A copy operation, for example, depends on a relationship between the amount copied and the space available. Searching for that relationship requires more than matching the spelling of the code.

SCJ gives a vulnerability a geometric fingerprint: a mathematical representation of the operation, its context, and the conditions that make it unsafe. It searches for related implementations, then uses a constraint solver to check whether they enforce the safety conditions introduced by the patch. The goal is to locate the flaw’s unresolved twins—even when their code looks different.

Inside the fingerprint / actual saved vectors

Look past the copy. Compare its context.

A copy operation alone tells us little. SCJ also records the operations and patterns around it. Together, those numbers form a vector—a fingerprint we can compare with other functions.

Three functions, written as numbers.

Reference function Coordinate 0: 0.636 Coordinate 1: 1.233 Coordinate 2: 1.123 Coordinate 3: 0.000 Coordinate 4: 0.000 Coordinate 5: 0.000 Coordinate 6: 0.000 Coordinate 7: 0.000 Coordinate 8: 0.000 Coordinate 9: 0.000 Coordinate 10: 1.000 Coordinate 11: 1.000 Coordinate 12: 1.000 Coordinate 13: 0.000 Coordinate 14: 1.000 Coordinate 15: 0.000 Coordinate 16: 0.000 Coordinate 17: 0.000 Coordinate 18: 0.000 Coordinate 19: 0.000 Coordinate 20: 1.000 Coordinate 21: 1.000 Coordinate 22: 0.000 Coordinate 23: 0.000 Coordinate 24: 2.000 Coordinate 25: 0.000 Coordinate 26: 0.000 Coordinate 27: 0.000 Coordinate 28: 0.000 Coordinate 29: 0.000 Coordinate 30: 1.000 Coordinate 31: 1.000 Coordinate 32: 0.000 Coordinate 33: 0.000 Coordinate 34: 0.000 Coordinate 35: 0.000 Coordinate 36: 0.000 Coordinate 37: 0.000 Coordinate 38: 0.000 Coordinate 39: 0.000 Coordinate 40: 1.000 Coordinate 41: 0.000 Coordinate 42: 0.000 Coordinate 43: 0.000 Coordinate 44: 0.000 00 20 44 2
Candidate A · similar context Coordinate 0: 0.499 Coordinate 1: 0.825 Coordinate 2: 0.618 Coordinate 3: 0.000 Coordinate 4: 0.000 Coordinate 5: 0.000 Coordinate 6: 0.000 Coordinate 7: 0.000 Coordinate 8: 0.000 Coordinate 9: 0.000 Coordinate 10: 1.000 Coordinate 11: 1.000 Coordinate 12: 1.000 Coordinate 13: 0.000 Coordinate 14: 1.000 Coordinate 15: 0.000 Coordinate 16: 0.000 Coordinate 17: 0.000 Coordinate 18: 0.000 Coordinate 19: 0.000 Coordinate 20: 1.000 Coordinate 21: 1.000 Coordinate 22: 0.000 Coordinate 23: 0.000 Coordinate 24: 2.000 Coordinate 25: 0.000 Coordinate 26: 0.000 Coordinate 27: 0.000 Coordinate 28: 0.000 Coordinate 29: 0.000 Coordinate 30: 1.000 Coordinate 31: 1.000 Coordinate 32: 0.000 Coordinate 33: 0.000 Coordinate 34: 0.000 Coordinate 35: 0.000 Coordinate 36: 0.000 Coordinate 37: 0.000 Coordinate 38: 0.000 Coordinate 39: 0.000 Coordinate 40: 1.000 Coordinate 41: 0.000 Coordinate 42: 0.000 Coordinate 43: 0.000 Coordinate 44: 0.000 00 20 44 2
Candidate B · different context Coordinate 0: 0.354 Coordinate 1: 0.461 Coordinate 2: 0.220 Coordinate 3: 0.000 Coordinate 4: 0.000 Coordinate 5: 0.000 Coordinate 6: 0.000 Coordinate 7: 0.000 Coordinate 8: 0.000 Coordinate 9: 0.000 Coordinate 10: 0.000 Coordinate 11: 0.000 Coordinate 12: 1.000 Coordinate 13: 0.000 Coordinate 14: 0.000 Coordinate 15: 0.000 Coordinate 16: 0.000 Coordinate 17: 0.000 Coordinate 18: 0.000 Coordinate 19: 0.000 Coordinate 20: 0.000 Coordinate 21: 0.000 Coordinate 22: 0.000 Coordinate 23: 0.000 Coordinate 24: 0.000 Coordinate 25: 0.000 Coordinate 26: 0.000 Coordinate 27: 0.000 Coordinate 28: 0.000 Coordinate 29: 0.000 Coordinate 30: 1.000 Coordinate 31: 0.000 Coordinate 32: 0.000 Coordinate 33: 0.000 Coordinate 34: 0.000 Coordinate 35: 0.000 Coordinate 36: 0.000 Coordinate 37: 0.000 Coordinate 38: 0.000 Coordinate 39: 0.000 Coordinate 40: 0.000 Coordinate 41: 0.000 Coordinate 42: 0.000 Coordinate 43: 0.000 Coordinate 44: 0.000 00 20 44 2

Each bar is one stored coordinate. Height is its value, on the same 0–2 scale throughout. Coordinates 45–127 are all zero in these three records. From SCJ’s engineered-feature prototype; function identities are anonymized.

0.663 distance from the reference
Euclidean distance · smaller means closer

Expand the nonzero coordinates

Reference Candidate A Value / 0–2
00Function size 0.636 0.499
01Call count 1.233 0.825
02Branch count 1.123 0.618
10Allocation 1.000 1.000
11Free operation 1.000 1.000
12Copy operation 1.000 1.000
14Pool operation 1.000 1.000
20Multiply pattern 1.000 1.000
21Shift pattern 1.000 1.000
24Shift → allocation 2.000 2.000
30String operation 1.000 1.000
31Loop 1.000 1.000
40Overflow-pattern count 1.000 1.000

The operation and pattern coordinates align. Only size, call count and branch count differ. This is the nearest distinct vector in this saved cache by ordinary Euclidean distance.

What happens next?

A close fingerprint gives SCJ a place to look. The next question is whether that implementation enforces the patch’s safety conditions. See how the solver checks the protection →

About these vectors & their encodings

Three anonymized records from a saved SCJ cache of 6,370 functions. These are sparse, engineered features from a prototype, distinct from the learned embedding architecture described in the v0.4r specification. The plotted values are unchanged. The reference is an example function, not a confirmed vulnerability.

The distance shown is calculated for this comparison; it does not reproduce SCJ’s geometric ranking. No source code, function names or vulnerability verdicts are published here. Pattern flags describe heuristic detections, not proof of behavior.

How the displayed coordinates are encoded
Coordinate Feature Encoding
0 Function size log(1 + size) / 15
1 Call count log(1 + calls) / 5
2 Branch count log(1 + branches) / 5
10 Allocation Detected pattern: 1; absent: 0
11 Free operation Detected pattern: 1; absent: 0
12 Copy operation Detected pattern: 1; absent: 0
14 Pool operation Detected pattern: 1; absent: 0
20 Multiply pattern Detected pattern: 1; absent: 0
21 Shift pattern Detected pattern: 1; absent: 0
24 Shift → allocation Detected pattern weighted by 2
30 String operation Detected pattern: 1; absent: 0
31 Loop Detected pattern: 1; absent: 0
40 Overflow-pattern count Matching pattern labels × 0.5

All 128 values, selection method & source checksum · JSON · Read the broader embedding architecture

02 / Two connected representations

The fingerprint finds candidates. The solver checks the protection.

A geometric search

The v0.4r specification combines instruction features, graph neighborhoods and engineered features into a compressed representation. Sink identity and callsite context help group related functions across modules.

A semantic question

The patch introduces safety conditions. SPES traces bounded paths to the candidate’s sink and asks whether its predicates imply those conditions. A mismatch identifies a missing protection within the model; ambiguous mappings and timeouts remain inconclusive.

The original specification, June profile-based report and later v0.16 anomaly scan are distinct records. The F Prime merges below establish their specific engineering outcomes.

From research to reviewed contributions

Putting SCJ to work in F Prime.

F Prime (F′) is an open-source framework developed at NASA’s Jet Propulsion Laboratory for building spaceflight and other embedded software. It provides reusable components that engineering teams assemble into applications. The checks inside those components help determine how they behave when an input is too large, too small, or otherwise unexpected.

I used SCJ-assisted source-code investigations to examine where operations relied on safety conditions enforced elsewhere. That work led to two local safety checks and a reusable CodeQL analysis rule, refined through F Prime’s public review process and merged into its repository. SCJ helped direct the investigation; tracing the code, testing the conditions and working with maintainers turned it into these contributions.

01 / MERGED · 09 JUN 2026

Protect the copy

FileUplink checks the path length where it copies the bytes.

F Prime #5262 ↗

02 / MERGED · 04 AUG 2026

Protect the subtraction

DpCompressProc rejects a short packet before constructing its container.

F Prime #5518 ↗

03 / MERGED · 05 AUG 2026

Search for the pattern

A CodeQL query checks whether size arithmetic has a corresponding guard.

F Prime #5544 ↗

For this research, the value is the traceable path from an analysis candidate to a change accepted by the people maintaining the software. The case study follows what was proposed, what review changed, and what the resulting tests establish.

03 / A finding becomes an upstream change

The header was valid. The buffer was too short.

In DpCompressProc, a handler formed a payload buffer by subtracting the minimum packet size from the supplied buffer size. That subtraction needs a lower bound. The bound was asserted in the container code, but not checked locally before construction.

The accepted change adds an early return and a dedicated telemetry event. Review also produced an off-nominal test: keep the header valid, shorten the buffer view, and verify that compression never starts.

This is a source-level hardening result with a reproduced off-nominal condition. It does not establish an exploitable flaw in a deployed spacecraft.

04 / Beyond the individual fix

The check has to belong to the same object.

A long handler may contain many size comparisons. A check on other.getSize() says nothing about buf.getSize() − K. The follow-up CodeQL contribution makes that relationship explicit—and accepts FW_ASSERT as a valid check, following F Prime’s review policy.

RELATED CHECK / RECOGNIZED

FW_ASSERT(buf.getSize() >= K);
consume(buf.getSize() - K);

The check and subtraction read the same buffer.

UNRELATED CHECK / REPORTED

FW_ASSERT(other.getSize() >= K);
consume(buf.getSize() - K);

Matching accessor names cannot substitute for object identity.

Simplified from the merged query fixtures. The query is a conservative heuristic; it does not prove that every accepted check controls the execution path.

05 / Evidence you can follow

From a ranked candidate to a reviewed change.

Verified merged contributions · nasa/fprime · checked 15 October 2026
Contribution What landed Evidence
#5262
FileUplink
Local path-length check before copying. Existing U8 type already constrained valid lengths; the contribution makes the defense local. 96187b7
2026-06-09
#5518
DpCompressProc
Early rejection, specific event, documentation and an off-nominal regression test. 1e91573
2026-08-04
#5544
CodeQL
A reusable unsigned-size-subtraction query with same-object guard matching and expected test results. 8818e15
2026-08-05

These merges document accepted engineering contributions. They do not establish a general detection rate, complete vulnerability coverage, or independent validation of the whole geometric framework. The June study’s profiles were developed with knowledge of baseline findings; prospective evaluation remains a separate research question.

06 / Software & working record

Inspect the workflow.

Recorded evidence-pack workflow

Archived software demonstration. The F Prime case study above is the record for the merged contributions.

Reports and archived builds

Start with the source-code investigation report for the search profiles, triage decisions and June 2026 results. The downloadable binaries below are the retained v0.5 builds; they predate the later v0.16 scan.