Skip to content

Commit b7ba5b6

Browse files
committed
Update template parsing
1 parent 97e8651 commit b7ba5b6

File tree

4 files changed

+88
-10
lines changed

4 files changed

+88
-10
lines changed

lib/sobelow.ex

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ defmodule Sobelow do
2020
alias Sobelow.Config
2121
alias Sobelow.Vuln
2222
alias Sobelow.FindingLog
23+
alias Sobelow.MetaLog
2324
alias Mix.Shell.IO, as: MixIO
2425
# Remove directory structure check for release candidate
2526
# prior to 1.0
@@ -49,6 +50,7 @@ defmodule Sobelow do
4950
# off the test pipeline to avoid dumping warning
5051
# messages into the findings output.
5152
root_meta_files = get_meta_files(root)
53+
template_meta_files = get_meta_templates(root)
5254

5355
# If web_root ends with the app_name, then it is the
5456
# more recent version of Phoenix. Meaning, all files are
@@ -61,6 +63,9 @@ defmodule Sobelow do
6163
libroot_meta_files = if !phx_post_1_2?, do: get_meta_files(lib_root), else: []
6264

6365
FindingLog.start_link()
66+
MetaLog.start_link()
67+
68+
MetaLog.add_templates(template_meta_files)
6469

6570
# This is where the core testing-pipeline starts.
6671
#
@@ -242,6 +247,25 @@ defmodule Sobelow do
242247
end
243248
end
244249

250+
defp get_meta_templates(root) do
251+
ignored_files = get_env(:ignored_files)
252+
253+
Utils.template_files(root)
254+
|> Enum.reject(&is_ignored_file(&1, ignored_files))
255+
|> Enum.map(&get_template_meta/1)
256+
|> Map.new()
257+
end
258+
259+
defp get_template_meta(filename) do
260+
meta_funs = Utils.get_meta_template_funs(filename)
261+
raw = meta_funs.raw
262+
263+
{
264+
Utils.normalize_path(filename),
265+
%{raw: raw}
266+
}
267+
end
268+
245269
defp get_meta_files(root) do
246270
ignored_files = get_env(:ignored_files)
247271

@@ -269,14 +293,13 @@ defmodule Sobelow do
269293
|> Enum.map(&get_mod/1)
270294

271295
Enum.each(mods -- skip_mods, fn mod ->
272-
apply(mod, :get_vulns, [fun, meta_file, web_root, skip_mods])
296+
params = [fun, meta_file, web_root, skip_mods]
297+
apply(mod, :get_vulns, params)
273298
end)
274299
end
275300

276301
defp get_fun_vulns(fun, meta_file, web_root, mods) do
277-
Enum.each(mods, fn mod ->
278-
apply(mod, :get_vulns, [fun, meta_file, web_root])
279-
end)
302+
get_fun_vulns({fun, []}, meta_file, web_root, mods)
280303
end
281304

282305
defp combine_skips([]), do: []

lib/sobelow/meta_log.ex

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
defmodule Sobelow.MetaLog do
2+
use GenServer
3+
4+
def start_link() do
5+
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
6+
end
7+
8+
def add_templates(templates) do
9+
GenServer.cast(__MODULE__, {:add, templates})
10+
end
11+
12+
def get_templates() do
13+
GenServer.call(__MODULE__, :get_templates)
14+
end
15+
16+
def init(:ok) do
17+
{:ok, %{:templates => %{}}}
18+
end
19+
20+
def handle_cast({:add, templates}, log) do
21+
{:noreply, Map.put(log, :templates, templates)}
22+
end
23+
24+
def handle_call(:get_templates, _from, log) do
25+
{:reply, log.templates, log}
26+
end
27+
end

lib/sobelow/utils.ex

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,23 @@ defmodule Sobelow.Utils do
353353

354354
def get_meta_funs(ast, acc), do: {ast, acc}
355355

356+
def get_meta_template_funs(filepath) do
357+
ast = EEx.compile_string(File.read!(filepath))
358+
get_meta_template_fun(ast)
359+
end
360+
361+
def get_meta_template_fun(ast) do
362+
init_acc = %{raw: []}
363+
{_, acc} = Macro.prewalk(ast, init_acc, &get_meta_template_fun(&1, &2))
364+
acc
365+
end
366+
367+
def get_meta_template_fun({:raw, _, _} = ast, acc) do
368+
{ast, Map.update!(acc, :raw, &[ast | &1])}
369+
end
370+
371+
def get_meta_template_fun(ast, acc), do: {ast, acc}
372+
356373
def get_fun_vars_and_meta(fun, idx, type, module \\ nil) do
357374
{params, {fun_name, line_no}} = get_fun_declaration(fun)
358375

@@ -784,6 +801,14 @@ defmodule Sobelow.Utils do
784801
end
785802
end
786803

804+
def template_files(filepath, _directory \\ "") do
805+
if File.dir?(filepath) do
806+
Path.wildcard(filepath <> "/**/*.html.eex")
807+
else
808+
[]
809+
end
810+
end
811+
787812
# Setup Utils
788813
def get_app_name(filepath) do
789814
if File.exists?(filepath) do
@@ -919,10 +944,11 @@ defmodule Sobelow.Utils do
919944

920945
# XSS Utils
921946

922-
def get_template_vars(filepath) do
923-
ast = EEx.compile_string(File.read!(filepath))
924-
{_, acc} = Macro.prewalk(ast, [], &extract_template_vars(&1, &2))
925-
acc
947+
def get_template_vars(raw_funs) do
948+
Enum.flat_map(raw_funs, fn ast ->
949+
{_, acc} = Macro.prewalk(ast, [], &extract_template_vars(&1, &2))
950+
acc
951+
end)
926952
end
927953

928954
defp extract_template_vars({:raw, _, [{_, _, [_, raw]}]} = ast, acc) do

lib/sobelow/xss/raw.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ defmodule Sobelow.XSS.Raw do
2525
def run(fun, meta_file, web_root, controller) do
2626
{vars, _, {fun_name, [{_, line_no}]}} = parse_render_def(fun)
2727
filename = meta_file.filename
28+
templates = Sobelow.MetaLog.get_templates()
2829

2930
root =
3031
if String.ends_with?(web_root, "/lib/") do
@@ -45,9 +46,10 @@ defmodule Sobelow.XSS.Raw do
4546
end
4647

4748
template_path = root <> "templates/" <> controller <> "/" <> template <> ".eex"
49+
raw_funs = templates[Utils.normalize_path(template_path)]
4850

49-
if File.exists?(template_path) do
50-
raw_vals = Utils.get_template_vars(template_path)
51+
if raw_funs do
52+
raw_vals = Utils.get_template_vars(raw_funs.raw)
5153

5254
Enum.each(ref_vars, fn var ->
5355
if Enum.member?(raw_vals, var) do

0 commit comments

Comments
 (0)