Skip to main content

How Zift scans: the two-pass model

Objective

Describe Zift's two scan passes and when to use each, and recognize the real zift command shape.

Concept

Zift is an open-source Rust scanner (v0.2 at the time of writing). It scans in two passes.

Pass one is structural. Zift parses your source into a syntax tree using tree-sitter and looks for the shapes that mean authorization: role comparisons, permission-guard calls, and route middleware. This pass is fast, deterministic, and needs no network. It catches the obvious, well-formed checks, the ones that look like if user.role == "admin" or requireRole("editor").

Pass two is --deep. Structural matching misses authorization that does not look like a textbook check: a helper function named something innocuous, a permission encoded as a magic number, a check split across two functions. The --deep pass is LLM-assisted. It reasons about code the structural pass flagged as ambiguous or missed, and proposes findings the tree alone would not surface. It is slower and it is the pass you run when you want thoroughness over speed.

The command shape is small and real. Do not invent flags.

# Structural scan of the current directory.
zift .

# Structural scan of a subtree.
zift scan ./src

# Add the deep, LLM-assisted pass.
zift scan ./src --deep

# Produce a human-readable report of what was found.
zift report .

Both passes produce findings: a located piece of embedded authorization, with enough context to understand what it decides. You review findings before extracting them, because Zift is assessing, not silently rewriting your code.

A note on honesty: the two passes trade off. The structural pass can miss cleverly disguised checks (false negatives); the --deep pass can propose something that is not really an authorization decision (a false positive). That is why a human reviews findings before extraction.

Hands-on lab

No new lab commands. Practice the command shape by writing out, from memory, the zift invocation that scans ./services/api with the deep pass enabled, then the invocation that prints a report for the whole repository. Check yourself against the block above. (The graded lab uses opa; you validate the extracted policy, you do not run Zift here.)

Check for understanding

  1. Which pass is deterministic and needs no network, and what kind of check does it reliably catch?
  2. Give one example of embedded authorization the structural pass would likely miss but --deep could catch.
  3. What is the correct command to run a structural-plus-deep scan of ./src?