sdk/api

SDK API Reference

Python SDK (codepathfinder v2.1.0) for writing Code Pathfinder rules. This page covers language-agnostic primitives. Pick a language below for the decorator and matcher reference specific to that target.

Pick your target language

Critical default
flows(..., propagates_through=None) defaults to an empty list, meaning no propagation is applied. Source and sink must already be connected by a primitive you pass explicitly. Use propagates_through=PropagationPresets.standard() unless you know otherwise, or set it globally with set_default_propagation(PropagationPresets.standard()). Confirmed in codepathfinder/config.py:15.

flows()

The core dataflow analysis primitive. Traces taint from sources to sinks and reports paths that reach a sink without passing through a sanitizer. Works for Go and Python rules. Dockerfile / docker-compose rules do not use flows().

python
from codepathfinder import flows
from codepathfinder.presets import PropagationPresets

flows(
    from_sources,                     # AnyMatcher | list[AnyMatcher], required
    to_sinks,                         # AnyMatcher | list[AnyMatcher], required
    sanitized_by=None,                # optional
    propagates_through=None,          # defaults to [] (see callout above)
    scope=None,                       # "local" | "global" (default: global)
)
Parameters
from_sourcesrequired
AnyMatcher | list[AnyMatcher]
Where untrusted data enters. The AnyMatcher union (dataflow.py:17) covers CallMatcher (calls()), AttributeMatcher (attribute()), MethodMatcher (QueryType.method()), and AttributeMethodMatcher (QueryType.attr()). Logic combinators (And, Or, Not) are also accepted.
to_sinksrequired
AnyMatcher | list[AnyMatcher]
Dangerous destinations where tainted data must not reach. Same accepted types as sources.
sanitized_by
AnyMatcher | list[AnyMatcher] | None
Optional. If taint passes through any sanitizer on the path from source to sink, the finding is suppressed.
propagates_through
list[PropagationPrimitive] | None
How taint spreads across statements. Defaults to the global default (initially [], meaning no propagation). Pass PropagationPresets.standard() for typical taint tracking.
scope
"local" | "global" | None
"local" runs intra-procedurally (same function)."global" runs inter-procedurally (across functions). None uses the global default, which is "global". Invalid values raise ValueError.

scope: local vs global

Determines whether the analyzer traces taint across function boundaries.

"local"intra-procedural

Source and sink must be in the same function. Faster, no false positives from cross-function paths, but misses real flows that go through helpers.

"global"default

Traces taint through function calls, returns, and across files using the project-wide call graph. Recommended for real-world rules.

PropagationPresets

Pre-bundled lists of propagation primitives. Import from codepathfinder.presets. All presets are static methods that return list[PropagationPrimitive].

python
from codepathfinder.presets import PropagationPresets

PropagationPresets.minimal()       # [assignment, function_args], ~40% coverage
PropagationPresets.standard()      # adds function_returns, string_concat, string_format (recommended)
PropagationPresets.comprehensive() # same primitives as standard() today
PropagationPresets.exhaustive()    # same primitives as comprehensive() today
In the current release (v2.1.0), comprehensive() and exhaustive() return the same list as standard(). Defined in codepathfinder/presets.py:82-136.

propagates: individual primitives

Individual propagation primitives for fine-grained control. Import the propagates namespace directly.

python
from codepathfinder import propagates

propagates.assignment()        # x = tainted; chained assignment; tuple unpacking
propagates.function_args()     # func(tainted); *args, **kwargs
propagates.function_returns()  # return tainted; conditional returns
propagates.string_concat()     # "pre" + tainted + "post"
propagates.string_format()     # f"{tainted}"; "{}".format(tainted); "%s" % tainted

Five propagation primitives are currently implemented. The PropagationPresets.standard() bundle includes all of them.

Qualifiers

Constraint helpers used with .where(), .arg(), or inside match_position / match_name dicts on calls().

python
from codepathfinder import lt, gt, lte, gte, regex, missing

# Numeric constraints
RSAModule.method("generate_private_key").where("key_size", lt(2048))
FlaskApp.method("run").where("port", gte(1024))

# Regex on string values
calls("connect").where(0, regex(r"^(?!localhost).*"))

# missing(): keyword argument is absent from the call (uses default value)
ResponseModule.method("set_cookie").where("secure", missing())
Qualifier signatures
lt(value)
int | float → LessThan
Argument value is strictly less than value.
gt(value)
int | float → GreaterThan
Argument value is strictly greater than value.
lte(value)
int | float → LessThanOrEqual
Argument value ≤ value.
gte(value)
int | float → GreaterThanOrEqual
Argument value ≥ value.
regex(pattern)
str → Regex
Argument string matches the regex pattern.
missing()
() → Missing
Keyword argument is absent from the call. Useful for catching missing security flags.

And / Or / Not

Boolean combinators for matchers. Works on any matcher type (calls, variable, QueryType method, etc.).

python
from codepathfinder import And, Or, Not

Or(calls("eval"), calls("exec"))                  # any of
And(calls("open"), variable("user_*"))            # both
Not(calls("test_*"))                              # exclude test functions

# Nested: mix Go QueryType with calls()
Or(GoOSExec.method("Command"), calls("os/exec.Command"))

And and Or require ≥2 matchers; Not takes exactly one. Container rules use all_of / any_of / none_of instead (see Dockerfile page).

Global configuration

Override the global defaults for propagation and scope. Useful when every rule in a ruleset needs the same setup.

python
from codepathfinder import set_default_propagation, set_default_scope, PropagationPresets

# Apply PropagationPresets.standard() to every flows() call that omits propagates_through
set_default_propagation(PropagationPresets.standard())

# Switch the global default to local scope
set_default_scope("local")

codepathfinder package exports

Everything available via from codepathfinder import ...:

callsvariableattributeflowsruleQueryTypepropagatesPropagationPresetsAndOrNotltgtltegteregexmissingset_default_propagationset_default_scope__version__

Language-specific decorators and pre-defined types live in submodules: codepathfinder.go_decorators, codepathfinder.python_decorators, codepathfinder.container_decorators, codepathfinder.go_rule, codepathfinder.container_matchers.