Skip to content

Threat-model pipeline: extend entry-point queries to Python CLI frameworks (argparse, click, typer) #264

@mlieberman85

Description

@mlieberman85

Summary

The tree-sitter discovery pipeline produces empty threat models for Python CLI projects. The Python query set covers web services (Flask, FastAPI, Django routes) and MCP servers (@mcp.tool decorators) but has no patterns for the dominant Python CLI frameworks: argparse, click, typer.

Sibling to #262 (Go cobra CLI coverage, addressed in feature 014). This issue covers the Python half of the same coverage gap.

Motivating example: darnit itself

darnit is the canonical dogfood target. Its surface is split:

  • MCP server (packages/darnit/src/darnit/tools/, packages/darnit-baseline/src/darnit_baseline/tools.py) — covered today via python.entry.mcp_tool.
  • CLI (packages/darnit/src/darnit/cli.py) — argparse.ArgumentParser with 8 subparsers (serve, audit, plan, profiles, validate, init, list, install), each registered via subparsers.add_parser(...). Not covered.

So running darnit's threat-model generator against the darnit repo produces a thread model for the MCP tools only — the CLI surface is invisible. This is structurally analogous to gittuf's situation before #262.

Why this matters

  • OSPS-SA-03.02 (Threat model documentation) is one of darnit-baseline's flagship auto-remediations. Without Python CLI coverage we can't dogfood it against our own CLI.
  • Python CLIs are everywhere in dev tooling (pip, pipx, uv, ruff, pre-commit, mypy, sphinx, etc.). Saying "darnit produces threat models for Python projects" without CLI coverage is a real overclaim.
  • This issue + Threat-model pipeline: extend entry-point queries to Go CLIs (cobra) and other non-HTTP shapes #262 together close the major non-web-service entry-point gap for the two languages darnit's pipeline already targets.

Suggested approach

Phase 1 — argparse (the stdlib standard):

  • Add tree-sitter queries: argparse.ArgumentParser(...) construction, subparsers.add_parser(\"<name>\", ...) calls, parser.add_subparsers(...) calls
  • Detect the add_subparsersadd_parser relationship to group sibling commands as a family (analogous to feature 014's cobra family-grouping)
  • Reuse feature 014's EntryPointKind.CLI_COMMAND and the import-based STRIDE-heuristic table (Tampering / Repudiation / Spoofing+Information Disclosure / Elevation of Privilege / Tampering fallback)
  • Render under the existing ### CLI Entry Points subsection (no document-structure changes — feature 014 already built that)
  • Tests: synthetic fixtures (argparse_minimal, argparse_subcommands); regression run against darnit itself

Phase 2 — click:

  • Match @click.command() and @<group>.command() decorators
  • Match @click.group() for family roots
  • Click commands often live in single-file CLIs; grouping defaults to one family per click.group plus an "ungrouped" family for top-level commands

Phase 3 — typer:

  • Match @app.command() and typer.Typer() instantiation
  • Sub-app patterns (app.add_typer(sub_app, ...)) → family

Effort estimate

  • Phase 1 (argparse): ~2-3 days incl. tests. Python query infrastructure is more mature than the Go pipeline that feature 014 had to build out, so several stages (extractor scaffolding, family grouping, STRIDE heuristic, renderer) can be reused with framework-specific extensions rather than ground-up additions.
  • Phase 2 (click): ~1.5-2 days additional.
  • Phase 3 (typer): ~1 day additional (very similar to click).

Phases can land independently.

Acceptance

  • Darnit cold-audit produces a non-empty ### CLI Entry Points section listing all 8 of darnit's argparse subcommands (one family).
  • Each finding includes a STRIDE category, a file:line location, and the "needs reviewer attention" marker.
  • Existing Python pipeline tests (Flask, FastAPI, MCP) pass with no regression.
  • README's "Threat-model coverage scope" table updates to acknowledge Python CLI coverage for whichever frameworks land.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions