diff --git a/sast-engine/dsl/dataflow_executor.go b/sast-engine/dsl/dataflow_executor.go index 3440e8a6..e8752736 100644 --- a/sast-engine/dsl/dataflow_executor.go +++ b/sast-engine/dsl/dataflow_executor.go @@ -435,9 +435,10 @@ func (e *DataflowExecutor) resolveMatchers(rawMatchers []json.RawMessage) []Call // CallSiteMatch represents a matched call site. type CallSiteMatch struct { - CallSite core.CallSite - FunctionFQN string - Line int + CallSite core.CallSite + FunctionFQN string + Line int + TrackedParams []TrackedParam // Which parameters are taint-sensitive (from matcher IR) } // findPath uses DFS to find a path between two functions. diff --git a/sast-engine/dsl/ir_types.go b/sast-engine/dsl/ir_types.go index 4f6dd702..87671465 100644 --- a/sast-engine/dsl/ir_types.go +++ b/sast-engine/dsl/ir_types.go @@ -41,6 +41,21 @@ type ArgumentConstraint struct { Comparator string `json:"comparator,omitempty"` } +// TrackedParam specifies a parameter that is taint-sensitive in dataflow analysis. +// Exactly one of Index, Name, or Return should be set. +type TrackedParam struct { + // Index is the 0-based positional parameter index. + // Pointer type so that index 0 is distinguishable from "not set". + Index *int `json:"index,omitempty"` + + // Name is the parameter name (e.g., "query", "args"). + // Resolved to a positional index at analysis time via function signature. + Name string `json:"name,omitempty"` + + // Return is true when tracking the return value (used for source matchers). + Return bool `json:"return,omitempty"` +} + // CallMatcherIR represents call_matcher JSON IR. type CallMatcherIR struct { Type string `json:"type"` // "call_matcher" @@ -58,6 +73,10 @@ type CallMatcherIR struct { // Example: {"debug": ArgumentConstraint{Value: true}} // This field is optional and will be omitted from JSON if empty. KeywordArgs map[string]ArgumentConstraint `json:"keywordArgs,omitempty"` + + // TrackedParams specifies which parameters are taint-sensitive. + // When empty, all parameters are considered sensitive (default). + TrackedParams []TrackedParam `json:"trackedParams,omitempty"` } // GetType returns the IR type. @@ -113,6 +132,14 @@ type DataflowDetection struct { Scope string // "local" or "global" MatchedCallSite *core.CallSite // Internal: matched call site for DataflowExecutor use MatchMethod string // How the match was made: "type_inference", "fqn_bridge", "fqn_prefix", "name_fallback" + + // SinkParamIndex is the positional index of the tainted sink parameter. + // nil when parameter position could not be determined. + SinkParamIndex *int `json:"sinkParamIndex,omitempty"` + + // SinkParamName is the name of the tainted sink parameter, if known. + // Deferred: not populated in v1, reserved for future use. + SinkParamName string `json:"sinkParamName,omitempty"` } // TypeConstrainedCallIR represents type_constrained_call JSON IR. @@ -133,6 +160,10 @@ type TypeConstrainedCallIR struct { // Argument matching (reuses ArgumentConstraint) PositionalArgs map[string]ArgumentConstraint `json:"positionalArgs,omitempty"` KeywordArgs map[string]ArgumentConstraint `json:"keywordArgs,omitempty"` + + // TrackedParams specifies which parameters are taint-sensitive. + // When empty, all parameters are considered sensitive (default). + TrackedParams []TrackedParam `json:"trackedParams,omitempty"` } // GetEffectiveReceiverTypes returns the receiver types, merging legacy single field. diff --git a/sast-engine/graph/callgraph/analysis/taint/var_dep_graph.go b/sast-engine/graph/callgraph/analysis/taint/var_dep_graph.go index 2d8e5190..0032aa61 100644 --- a/sast-engine/graph/callgraph/analysis/taint/var_dep_graph.go +++ b/sast-engine/graph/callgraph/analysis/taint/var_dep_graph.go @@ -14,6 +14,7 @@ type TaintDetection struct { SourceVar string SinkLine uint32 SinkCall string + SinkVar string // Variable at the sink call site (the argument that carries taint) PropagationPath []string Confidence float64 } @@ -140,6 +141,7 @@ func (g *VarDepGraph) FindTaintFlows(statements []*core.Statement, sinks []strin SourceVar: srcNode.VarName, SinkLine: stmt.LineNumber, SinkCall: stmt.CallTarget, + SinkVar: usedVar, PropagationPath: g.pathToVarNames(path), Confidence: 1.0, })