Packages
metastatic
0.20.2
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.2
0.22.1
0.22.0
0.21.3
0.21.2
0.21.1
0.21.0
0.20.3
0.20.2
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Cross-language code meta-model library using unified MetaAST representation. Parse, transform, and translate code across Python, Elixir, Ruby, Erlang, Haskell, and more via a shared three-tuple AST format.
Current section
Files
Jump to
Current section
Files
lib/metastatic/analysis/taint/result.ex
defmodule Metastatic.Analysis.Taint.Result do
@moduledoc """
Result structure for taint analysis.
Contains information about taint flows from sources to sinks,
identifying potential security issues from untrusted data.
## Fields
- `:has_taint_flows?` - Boolean indicating if taint flows were found
- `:taint_flows` - List of detected taint flow paths
- `:summary` - Human-readable summary of findings
- `:total_flows` - Count of taint flows
- `:by_risk` - Map of counts by risk level
## Examples
iex> result = Metastatic.Analysis.Taint.Result.new([])
iex> result.has_taint_flows?
false
iex> flows = [%{source: "input", sink: "eval", risk: :critical}]
iex> result = Metastatic.Analysis.Taint.Result.new(flows)
iex> result.has_taint_flows?
true
"""
@type taint_flow :: %{
source: String.t(),
sink: String.t(),
risk: risk_level(),
path: [String.t()],
recommendation: String.t()
}
@type risk_level :: :critical | :high | :medium | :low
@type t :: %__MODULE__{
has_taint_flows?: boolean(),
taint_flows: [taint_flow()],
summary: String.t(),
total_flows: non_neg_integer(),
by_risk: %{risk_level() => non_neg_integer()}
}
defstruct has_taint_flows?: false,
taint_flows: [],
summary: "No taint flows detected",
total_flows: 0,
by_risk: %{}
@doc """
Creates a new result from a list of taint flows.
## Examples
iex> Metastatic.Analysis.Taint.Result.new([])
%Metastatic.Analysis.Taint.Result{has_taint_flows?: false, summary: "No taint flows detected"}
iex> flows = [%{source: "input", sink: "eval", risk: :critical, path: [], recommendation: "sanitize"}]
iex> result = Metastatic.Analysis.Taint.Result.new(flows)
iex> result.has_taint_flows?
true
"""
@spec new([taint_flow()]) :: t()
def new([]), do: %__MODULE__{}
def new([_ | _] = taint_flows) do
by_risk = count_by_risk(taint_flows)
%__MODULE__{
has_taint_flows?: true,
taint_flows: taint_flows,
summary: build_summary(taint_flows, by_risk),
total_flows: length(taint_flows),
by_risk: by_risk
}
end
@doc """
Creates a result with no taint flows.
## Examples
iex> result = Metastatic.Analysis.Taint.Result.no_taint()
iex> result.has_taint_flows?
false
"""
@spec no_taint() :: t()
def no_taint do
new([])
end
@doc """
Converts result to JSON-compatible map.
## Examples
iex> result = Metastatic.Analysis.Taint.Result.new([])
iex> map = Metastatic.Analysis.Taint.Result.to_map(result)
iex> is_map(map)
true
"""
@spec to_map(t()) :: map()
def to_map(%__MODULE__{} = result) do
%{
has_taint_flows: result.has_taint_flows?,
summary: result.summary,
total_flows: result.total_flows,
by_risk: result.by_risk,
taint_flows: result.taint_flows
}
end
# Private helpers
defp count_by_risk(flows) do
Enum.reduce(flows, %{}, fn %{risk: risk}, acc ->
Map.update(acc, risk, 1, &(&1 + 1))
end)
end
defp build_summary(flows, by_risk) do
total = length(flows)
risk_summary =
by_risk
|> Enum.sort_by(fn {risk, _} -> risk_order(risk) end, :desc)
|> Enum.map_join(", ", fn {risk, count} ->
"#{count} #{risk}"
end)
"Found #{total} taint flow(s): #{risk_summary}"
end
defp risk_order(:critical), do: 4
defp risk_order(:high), do: 3
defp risk_order(:medium), do: 2
defp risk_order(:low), do: 1
end