Skip to main content

Security hypothesis analysis

Check security hypotheses against the code graph through CLI or MCP. Inspect evidence, compare results after a change and export test targets.

Technical Reference

Security review starts with a question: can untrusted input reach a dangerous operation, can a permission check be bypassed, or does a known weakness apply to this code? Answering it requires entry points, connections and execution conditions. A suspicious fragment alone does not explain how the problem would occur in the application.

CodeGraph turns these assumptions into hypotheses and checks them against the Code Property Graph (CPG). A hypothesis defines the question; the graph helps investigate program structure and available relations. The workflow uses a knowledge base and registered pattern providers. Each checked hypothesis is confirmed, rejected or inconclusive.

The team receives evidence for investigation: what was checked, which queries ran, which assumptions were supported and where evidence was insufficient. This helps focus manual review on specific code locations. Engineers use the source locations and query evidence to examine exploitability conditions and prepare a security test.

From an assumption to a check

Consider a teaching question: can a value from an HTTP request affect an SQL query? The reviewer selects relevant hypotheses and a repository revision. The workflow then queries the CPG within the chosen scope. The engineer compares the resulting locations with source code and checks parameterization, data transformations and other conditions that affect the risk.

If graph relations are insufficient, the result remains inconclusive and identifies a need for further investigation. After a fix, the team rebuilds the graph and repeats the check under the same conditions. Comparing the results shows how the fix affected the data path under review.

When to use this analysis

  • Review a sensitive change by investigating selected hypotheses for the intended revision.
  • Investigate a known weakness using supported category or CVE filters.
  • Prepare execution checks by exporting supported fuzz or DAST targets.
  • Hand results to AppSec with the report, scope, exclusions and source locations.

Connecting hypotheses to a graph turns a general warning into a question that can be checked against code. Use the analysis capability map to select checks for your language and framework, then add adjacent checks: hypotheses examine code weaknesses, threat modeling examines system boundaries, and SCA/SBOM examines dependencies.

Choose an interface

Use the CLI for local, explicit CPG files, detailed filters, incremental runs, report files, and fuzz-target export. Use MCP when an authorized agent session already has project context and needs a typed analysis result.

See the CLI guide for command options and the MCP operator guide to connect an agent session. Use codegraph_security_hypothesis_run through MCP. For automation, use the selected command’s --help output or the MCP tool schema in your installed version.

Run from the CLI

Install the CLI using the CLI guide. Run these Bash commands from the CodeGraph repository root. The current executor requires an accessible GoCPG gRPC service. --db selects the CPG; it does not enable direct DuckDB access.

export CODEGRAPH_ALLOW_LOCAL_PYTHON_CLI=1
python -m src.cli hypothesis run --db "<cpg-path>" --human-language en

Select language, volume, priority, and output explicitly when reproducibility matters:

python -m src.cli hypothesis run \
  --db "<cpg-path>" \
  --language C \
  --max 50 \
  --min-priority 0.5 \
  --format json \
  --output "hypothesis-report.json" \
  --human-language en

The JSON report includes the batch identity, execution counts, result counts, timing, and bounded hypothesis fields. Preserve the indexed Git revision and command arguments beside the report.

Parameters for a regular run select what to check and how much to return:

Run from the CLI
Parameter How to choose a value Default
--language Set the source language, such as C. C
--max Set the maximum number of hypotheses in the batch. 50
--min-priority Set the minimum hypothesis priority for validation. The example uses 0.5. 0.3
--category Select a weakness category; repeat the flag for multiple categories. No category filter
--format Choose json for programmatic processing or text for terminal output. text
--human-language Choose the explanation language: ru or en. en

Keep the same filters and threshold when comparing two revisions. This lets you relate a change in confirmed hypotheses to the code change demonstrated below.

Check a change with a worked example

In this example, a function reads text from an environment variable through getenv and passes it to system. The command-injection hypothesis checks for the input source and command execution within that function. We then replace command execution with text output through puts, rebuild the graph and compare the results.

Run these Bash commands from the CodeGraph repository root. Set GOCPG_BIN to the absolute path of your installed GoCPG executable in place of <path-to-gocpg>; on Windows, use the gocpg.exe file. You also need an accessible GoCPG gRPC service, as for the preceding commands. Replace <new-demo-dir> with a new directory for the example sources, graphs and reports. Parse the teaching source with the analyzer; you do not need to compile or execute it to check the hypothesis.

Create the source, build its CPG and save the report:

GOCPG_BIN="<path-to-gocpg>"
DEMO_DIR="<new-demo-dir>"
mkdir -p "$DEMO_DIR/before"
cat > "$DEMO_DIR/before/example.c" <<'C'
#include <stdio.h>
#include <stdlib.h>

void run_action(void) {
    char *command = getenv("CODEGRAPH_DEMO_COMMAND");
    if (command != NULL) {
        system(command);
    }
}
C

"$GOCPG_BIN" parse --input "$DEMO_DIR/before" \
  --output "$DEMO_DIR/before.duckdb" --lang c
export CODEGRAPH_ALLOW_LOCAL_PYTHON_CLI=1
python -m src.cli hypothesis run \
  --db "$DEMO_DIR/before.duckdb" \
  --language C --category command_injection \
  --max 50 --min-priority 0.5 --format json \
  --output "$DEMO_DIR/before.json" --human-language en

Open <new-demo-dir>/before.json. For this source, expect one executed check (executed_queries: 1) and one confirmed hypothesis (confirmed_hypotheses: 1) in category command_injection. Its cwe_ids include CWE-78. In the source, follow command from getenv to system: this is the code the team receives for review.

Replace system(command) with puts(command) and keep the new version separately. Rebuild the CPG and repeat the same check:

mkdir -p "$DEMO_DIR/after"
sed 's/system(command);/puts(command);/' \
  "$DEMO_DIR/before/example.c" > "$DEMO_DIR/after/example.c"
"$GOCPG_BIN" parse --input "$DEMO_DIR/after" \
  --output "$DEMO_DIR/after.duckdb" --lang c
python -m src.cli hypothesis run \
  --db "$DEMO_DIR/after.duckdb" \
  --language C --category command_injection \
  --max 50 --min-priority 0.5 --format json \
  --output "$DEMO_DIR/after.json" --human-language en

In <new-demo-dir>/after.json, expect executed_queries: 1, confirmed_hypotheses: 0 and rejected_hypotheses: 1. The number of checks stays the same, while the command-injection hypothesis becomes rejected: the new version prints the value as text through puts. The two sources, graphs and reports let the reviewer inspect both the change and its repeated check.

Limit the scope

A regular run applies repeatable --category and comma-separated --cve arguments. The parser accepts run --cwe, but the current handler does not use it. For export, --cwe filters already validated hypotheses for export; it does not limit queries.

--incremental --base-ref "<git-ref>" compares that revision with HEAD in the current working directory. It excludes uncommitted changes. This mode ignores --category, --cwe, --cve, and all exclusion arguments. An empty changed-file list triggers full validation. A Git diff failure can also produce an empty list. Check the baseline and changed-file list separately before starting this mode.

For regular run and export, use --exclude-fixtures, --exclude-mocks, --exclude-generated, or repeatable --exclude-category when those inputs are outside the assessment. Record exclusions with the report to identify the scope of the assessment.

Before analysis, update the CPG for the repository revision being assessed and pass its path through --db.

Inspect coverage and export targets

List the available knowledge-base entries and registered providers before choosing filters:

python -m src.cli hypothesis list-cwes --format json
python -m src.cli hypothesis providers

A provider groups analysis patterns for a language or framework, data sources, and sensitive operations. The providers command shows its contents: Patterns counts patterns, Sources counts data sources, and Sinks counts sensitive operations. Use this list to choose a provider for your project. The list-cwes command shows weakness categories in the knowledge base and helps you choose what to investigate.

Export supported fuzzing or DAST targets with an explicit database and output directory:

python -m src.cli hypothesis export \
  --db "<cpg-path>" \
  --format generic \
  --output "fuzz_targets" \
  --human-language en

The export command runs validation, selects hypotheses by priority and the optional CWE filter, then writes targets.json and files for each target. The manifest includes entry and sink functions, input hints, CWE identifiers, priority and the hypothesis text. Source locations come from the collected evidence; function names can also come from the hypothesis’s source and sink patterns.

The generic format writes a JSON description for each target. The afl and libfuzzer formats write seed inputs and harness stubs. Hypotheses for supported web weaknesses also produce Nuclei templates. Connect each harness to the application entry point, configure its build and inputs, and run it in a sandbox. Use the validation report to choose which hypotheses to investigate first.

Run through MCP

Use the AppSec read connection with profile codex:role:codegraph_appsec:read, then select codegraph_security_hypothesis_run in the client. The tool accepts an action of run, list_cwes, or list_providers, plus supported language, volume, priority, category, and human-language fields.

To list provider names and their languages, pass this object to the tool:

{"action": "list_providers"}

For run, the MCP tool selects the CPG from the authorized project’s runtime context. Select the project in the client before starting analysis.

For setup and typed-call rules, use the MCP operator guide.

Interpret results

Interpret results
Result What the check established Next action
Confirmed Evidence satisfies the current validation rules. Open the source locations and examine the data path and execution conditions.
Rejected The evaluated hypothesis did not meet these rules. Keep the result with the check scope and revision for comparison with a later run.
Inconclusive The available graph or evidence could not settle the hypothesis. Identify the relations or data needed to continue the check.

The current metrics calculation counts each confirmed hypothesis as a true positive (true_positives). Missed explicitly requested CVEs increase false_negatives; false_positives retains its initial value of 0. Values for precision, recall and f1_score are calculated from these counters and describe the current run’s results. When reviewing a finding, open its source locations, query evidence, category and CWE mapping. To assess exploitability, follow the data path and execution conditions, then reproduce the behavior with an appropriate security test.

Work with findings

Language patterns define the constructs to check, and the CPG supplies relations between code elements. Engineers use hypothesis evidence to select code for review and prepare a test. After a fix, refresh the graph and rerun the same hypothesis check.

Run generated fuzz targets in a sandbox after reviewing their code and build settings. Keep reports in the team’s designated storage with access for reviewers: they contain repository structure and details of identified weaknesses.

Use threat modeling for system-level trust boundaries and SCA/SBOM for dependency risk; the three workflows answer different questions.