Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipeline error for sobelow #158

Open
MikaAK opened this issue Mar 19, 2024 · 3 comments
Open

Pipeline error for sobelow #158

MikaAK opened this issue Mar 19, 2024 · 3 comments

Comments

@MikaAK
Copy link
Contributor

MikaAK commented Mar 19, 2024

Having an issue on one of our apps, i've tested this using #157 and the issue persists

** (FunctionClauseError) no function clause matching in Sobelow.Config.vuln_pipeline?/2

    The following arguments were given to Sobelow.Config.vuln_pipeline?/2:

        # 1
        {:pipeline, [line: 32, column: 9], [{:map, [line: 32, column: 18], []}, {:keyword, [line: 32, column: 25], []}]}

        # 2
        :csrf

    Attempted function clauses (showing 2 out of 2):

        def vuln_pipeline?({:pipeline, _, [_name, [do: block]]}, :csrf)
        def vuln_pipeline?({:pipeline, _, [_name, [do: block]]}, :headers)

    (sobelow 0.13.0) lib/sobelow/config.ex:123: Sobelow.Config.vuln_pipeline?/2
    (elixir 1.14.2) lib/stream.ex:522: anonymous fn/4 in Stream.filter/2
    (elixir 1.14.2) lib/enum.ex:4751: Enumerable.List.reduce/3
    (elixir 1.14.2) lib/stream.ex:1811: Enumerable.Stream.do_each/4
    (elixir 1.14.2) lib/enum.ex:4307: Enum.each/2
    (elixir 1.14.2) lib/enum.ex:975: Enum."-each/2-lists^foreach/1-0-"/2
    (sobelow 0.13.0) lib/sobelow.ex:94: Sobelow.run/0
    (mix 1.14.2) lib/mix/task.ex:421: anonymous fn/3 in Mix.Task.run_task/4
@houllette
Copy link
Contributor

Sorry for the delay in response, @MikaAK - there was substantial changes around the migration from things like vulnerable? to is_vulnerable? as part of #156 that haven't made it to hex yet. I had been waiting to push v0.13.1 til I got a response in one of the issue threads that I was trying to address, but I think the delay is causing other folks like yourself too many issues.

I will be pushing out the new version to hex shortly, but in the meantime, you should be able to use Sobelow by referencing the GitHub repo in your mix file to use a version that includes all the various changes.

@houllette
Copy link
Contributor

Hey @MikaAK! I'm all caught up on digging into this issue - ignore my last comment, I was slightly confused 😅

So the primary issue for me in trying to fix this bug is that it is erroring out because of an edge case in the function clauses not matching against whatever you're scanning - presuming that the test cases we have in Sobelow are conclusively testing whether things are working right now (which I'm not sure if they are or not); mix test is passing all checks and mix sobelow is running fine scanning other phoenix projects (including detecting known CSRF detections), so it's hard to detect an issue here myself without having the codebase you're trying to scan in hand.

From what I can tell though - Sobelow is erroring out on lib/sobelow.ex:94 which is where we're starting to fetch Configs, which starts to line up with the pattern match error stemming from within the Sobelow.Config.vuln_pipeline? that kicked this whole thing off. It's possible that there is just an edge-case surrounding how one of your pipelines is formatted that it's having trouble parsing?

It's possible that there is a missing function clause in Parse.get_funs_of_type/3 that we need to account for since it appears the Config.vuln_pipeline? is anticipating an AST code block that just isn't being given through the process of extracting pipelines in get_pipelines (as seen by your error messaging indicating that Config.vuln_pipeline? is being given [{:map, [line: 32, column: 18], []}, {:keyword, [line: 32, column: 25], []}] when it is anticipating something that matches [do: block] instead).

I am going to keep digging into this issue for sure (and any additional info / context you can give me around your project where available would be helpful), but you may be able to unblock your situation by using CLI arguments to ignore Config or Config.CSRF related checks when running Sobelow - that may just completely bypass the offending code. I would definitely be curious if that is the only blocker with your codebase or if this error is just the first of many!

@btkostner
Copy link

btkostner commented Nov 8, 2024

I just ran into this issue, so here is some more details.

CLI output:

> mix sobelow --config
** (FunctionClauseError) no function clause matching in Sobelow.Config.is_vuln_pipeline?/2

    The following arguments were given to Sobelow.Config.is_vuln_pipeline?/2:

        # 1
        {:pipeline, [line: 232, column: 9], nil}

        # 2
        :csrf

    Attempted function clauses (showing 2 out of 2):

        def is_vuln_pipeline?({:pipeline, _, [_name, [do: block]]}, :csrf)
        def is_vuln_pipeline?({:pipeline, _, [_name, [do: block]]}, :headers)

    (sobelow 0.13.0) lib/sobelow/config.ex:123: Sobelow.Config.is_vuln_pipeline?/2
    (elixir 1.17.2) lib/stream.ex:523: anonymous fn/4 in Stream.filter/2
    (elixir 1.17.2) lib/enum.ex:4858: Enumerable.List.reduce/3
    (elixir 1.17.2) lib/stream.ex:1891: Enumerable.Stream.do_each/4
    (elixir 1.17.2) lib/enum.ex:4423: Enum.each/2
    (elixir 1.17.2) lib/enum.ex:987: Enum."-each/2-lists^foreach/1-0-"/2
    (sobelow 0.13.0) lib/sobelow.ex:94: Sobelow.run/0
    (mix 1.17.2) lib/mix/task.ex:495: anonymous fn/3 in Mix.Task.run_task/5

This is a Phoenix project with Absinthe installed. The router includes code like this:

  scope "/graphql" do
    pipe_through([:api, :graphql_context])

    forward(
      "/",
      Absinthe.Plug,
      analyze_complexity: true,
      schema: MyAppWeb.Schema,
      pipeline: {__MODULE__, :graphql_pipeline},
      json_codec: Jason
    )
  end

  def graphql_pipeline(config, pipeline_opts) do
    secure? =
      :my_app
      |> Application.get_env(MyAppWeb.Endpoint, [])
      |> Keyword.get(:secure?, false)

    config.schema_mod
    |> Absinthe.Pipeline.for_document(pipeline_opts)
    |> then(fn pipeline ->
      if secure? do
        pipeline
        |> Absinthe.Pipeline.without(Phase.Schema.Introspection)
        |> Absinthe.Pipeline.insert_before(
          Absinthe.Phase.Document.Validation.Result,
          MyAppWeb.Phase.RemoveSuggestions
        )
      else
        pipeline
      end
    end)
  end

edit: Instead of using the variable pipeline and just doing pipe it seems to work. I'm guessing the code is making assumptions about variable naming in this file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants