/** * PythonReceiverTaintFormatPass — cognium-dev #264 (Python receiver-taint). * * Emits `format_string` (CWE-134) findings for Python `.format(...)` / * `.format_map(...)` calls whose RECEIVER is a tainted variable. The * generic sink-pattern schema keys exclusively on `arg_positions`, * which cannot represent a taint that lives on the call's receiver — * Python's `str.format(*args)` shape puts the format template AS the * receiver, not as an argument. * * ## Coverage overlap with Sprint 86 (#189) * * `language-sources-pass.ts` already carries a Sprint 86 (#189) * codepath that regex-matches `.format(` and ` %` shapes at * file scope, gated on the presence of a Flask / Django / FastAPI * request extractor in the source. **That path handles the common * case.** This pass is intentionally a fallback for the shapes * Sprint 86 misses: * * - Files that don't reference `request.args` / `flask.request` * (Sprint 86 short-circuits and never runs). * - `.format_map(...)` calls — Sprint 86's regex only accepts * `.format\s*\(`, not `.format_map`. As of 3.181.0 Sprint 86's * regex is extended, but this pass is kept as belt-and-suspenders. * - Non-Flask taint sources (e.g. `os.environ`, `sys.stdin`) that * the plugin's `getBuiltinSources()` catches but Sprint 86's * framework-gate excludes. * * ## Taint signal * * The pass consumes `graph.ir.taint.sources` (populated by * `TaintMatcherPass` before this pass runs). Each source has an * optional `variable` field naming the identifier the source's * return-value flows into. A `.format` call whose receiver name * matches any source's `variable` name in the same file is * treated as receiver-taint. * * (Prior to 3.181.0 this pass read `ConstantPropagatorResult.tainted` * which is empty for many Python cases — the pass no-op'd whenever * constant-propagation didn't populate the set. The switch to * `graph.ir.taint.sources[].variable` matches the taint-tracker's * own view of tainted identifiers and no longer depends on * constant-propagation state.) * * Python-only. No-op on other languages. * * Direct-finding emission via `ctx.addFinding` rather than * synthetic-sink emission because the source→sink relationship is * already established: the taint source populated `variable` at * assignment time; the format-call at the sink line consumes it * directly. Emitting a sink would require TaintPropagationPass to * also understand receiver-taint, a much broader engine change. */ import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js'; export interface PythonReceiverTaintFormatResult { /** Number of `.format()` / `.format_map()` calls flagged this run. */ findingsEmitted: number; } export declare class PythonReceiverTaintFormatPass implements AnalysisPass { readonly name = "python-receiver-taint-format"; readonly category: "security"; run(ctx: PassContext): PythonReceiverTaintFormatResult; } //# sourceMappingURL=python-receiver-taint-format-pass.d.ts.map