Skip to content

fix: smart cell to_source should not include string representation of the code #93

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 3 additions & 41 deletions modules/2-owasp.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Notable CWEs included are CWE-259: Use of Hard-coded Password, CWE-327: Broken o

_Please uncomment the function call that you believe is correct._

<!-- livebook:{"attrs":"eyJtb2R1bGVfaWQiOm51bGwsInF1ZXN0aW9uX2lkIjpudWxsLCJzb3VyY2UiOiIjT1dBU1A6MVxuZGVmbW9kdWxlIFBhc3N3b3JkQ29tcGFyZSBkb1xuICBkZWYgb3B0aW9uX29uZShwYXNzd29yZCwgbWQ1X2hhc2gpIGRvXG4gICAgY2FzZSA6Y3J5cHRvLmhhc2goOm1kNSwgcGFzc3dvcmQpID09IG1kNV9oYXNoIGRvXG4gICAgICB0cnVlIC0+IDplbnRyeV9ncmFudGVkX29wMVxuICAgICAgZmFsc2UgLT4gOmVudHJ5X2RlbmllZF9vcDFcbiAgICBlbmRcbiAgZW5kXG5cbiAgZGVmIG9wdGlvbl90d28ocGFzc3dvcmQsIGJjcnlwdF9zYWx0ZWRfaGFzaCkgZG9cbiAgICBjYXNlIEJjcnlwdC52ZXJpZnlfcGFzcyhwYXNzd29yZCwgYmNyeXB0X3NhbHRlZF9oYXNoKSBkb1xuICAgICAgdHJ1ZSAtPiA6ZW50cnlfZ3JhbnRlZF9vcDJcbiAgICAgIGZhbHNlIC0+IDplbnRyeV9kZW5pZWRfb3AyXG4gICAgZW5kXG4gIGVuZFxuZW5kXG5cbiMgRE8gTk9UIENIQU5HRSBDT0RFIEFCT1ZFIFRISVMgTElORSA9PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiMgUGFzc3dvcmRDb21wYXJlLm9wdGlvbl9vbmUoXCJ1c2Vyc19wYXNzd29yZFwiLCBtZDVfaGFzaClcbiMgUGFzc3dvcmRDb21wYXJlLm9wdGlvbl90d28oXCJ1c2Vyc19wYXNzd29yZFwiLCBiY3J5cHRfc2FsdGVkX2hhc2gpIn0","chunks":null,"kind":"Elixir.GradingClient.GradedCell","livebook_object":"smart_cell"} -->
<!-- livebook:{"attrs":"eyJzb3VyY2UiOiIjT1dBU1A6MVxuZGVmbW9kdWxlIFBhc3N3b3JkQ29tcGFyZSBkb1xuICBkZWYgb3B0aW9uX29uZShwYXNzd29yZCwgbWQ1X2hhc2gpIGRvXG4gICAgY2FzZSA6Y3J5cHRvLmhhc2goOm1kNSwgcGFzc3dvcmQpID09IG1kNV9oYXNoIGRvXG4gICAgICB0cnVlIC0+IDplbnRyeV9ncmFudGVkX29wMVxuICAgICAgZmFsc2UgLT4gOmVudHJ5X2RlbmllZF9vcDFcbiAgICBlbmRcbiAgZW5kXG5cbiAgZGVmIG9wdGlvbl90d28ocGFzc3dvcmQsIGJjcnlwdF9zYWx0ZWRfaGFzaCkgZG9cbiAgICBjYXNlIEJjcnlwdC52ZXJpZnlfcGFzcyhwYXNzd29yZCwgYmNyeXB0X3NhbHRlZF9oYXNoKSBkb1xuICAgICAgdHJ1ZSAtPiA6ZW50cnlfZ3JhbnRlZF9vcDJcbiAgICAgIGZhbHNlIC0+IDplbnRyeV9kZW5pZWRfb3AyXG4gICAgZW5kXG4gIGVuZFxuZW5kXG5cbiMgRE8gTk9UIENIQU5HRSBDT0RFIEFCT1ZFIFRISVMgTElORSA9PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiMgUGFzc3dvcmRDb21wYXJlLm9wdGlvbl9vbmUoXCJ1c2Vyc19wYXNzd29yZFwiLCBtZDVfaGFzaClcbiMgUGFzc3dvcmRDb21wYXJlLm9wdGlvbl90d28oXCJ1c2Vyc19wYXNzd29yZFwiLCBiY3J5cHRfc2FsdGVkX2hhc2gpIn0","chunks":null,"kind":"Elixir.GradingClient.GradedCell","livebook_object":"smart_cell"} -->

```elixir
result =
Expand All @@ -121,26 +121,7 @@ result =
end
end

[module_id, question_id] =
"#OWASP:1\ndefmodule PasswordCompare do\n def option_one(password, md5_hash) do\n case :crypto.hash(:md5, password) == md5_hash do\n true -> :entry_granted_op1\n false -> :entry_denied_op1\n end\n end\n\n def option_two(password, bcrypt_salted_hash) do\n case Bcrypt.verify_pass(password, bcrypt_salted_hash) do\n true -> :entry_granted_op2\n false -> :entry_denied_op2\n end\n end\nend\n\n# DO NOT CHANGE CODE ABOVE THIS LINE =========================\n\n# PasswordCompare.option_one(\"users_password\", md5_hash)\n# PasswordCompare.option_two(\"users_password\", bcrypt_salted_hash)"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{"OWASP" => OWASP}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(OWASP, 1, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down Expand Up @@ -292,26 +273,7 @@ result =
Kino.Input.read(answer)
)

[module_id, question_id] =
"#OWASP:2\nanswer = \n Kino.Input.select(\"Answer\", [\n {:ecto, \"Ecto v2.2.2\"},\n {:nx, \"Nx v0.5.0\"},\n {:plug, \"Plug v1.3.2\"}\n ])\n\nKino.render(answer)\n\nKino.Input.read(answer)"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{"OWASP" => OWASP}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(OWASP, 2, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down
21 changes: 1 addition & 20 deletions modules/3-ssdlc.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,7 @@ _Use `System.get_env/1` on line 2._
```elixir
result = super_secret_password = "p@ssw0rd"

[module_id, question_id] =
"# SDLC:1\nsuper_secret_password = \"p@ssw0rd\""
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{"ESCT" => ESCT, "OWASP" => OWASP}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(SDLC, 1, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down
42 changes: 2 additions & 40 deletions modules/4-graphql.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -76,26 +76,7 @@ result =
Kino.Input.read(input)
)

[module_id, question_id] =
"# GRAPHQL:1\n\ninput = Kino.Input.select(\"Choose your answer\", [\n a: \"API6_2019_Mass_Assignment\", \n b: \"API10_2019_Insufficient_Logging_Monitoring\", \n c: \"API3_2019_Excessive_Data_Exposure\",\n d: \"API4_2019_Lack_of_Resources_Rate_Limiting\"\n])\n\nKino.render(input)\n\nKino.Input.read(input)"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{"ESCT" => ESCT, "GRAPHQL" => GRAPHQL, "OWASP" => OWASP}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(GRAPHQL, 1, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down Expand Up @@ -141,26 +122,7 @@ result =
Kino.Input.read(input)
)

[module_id, question_id] =
"# GRAPHQL:2\n\n# -------------------------------------------------------------\n# Option 1\n#\n# HTTP/2 401 Unauthorized\n# Date: Tues, 16 Aug 2022 21:06:42 GMT\n# …\n# {\n# \t“error”:”token expired”\n# {\n# -------------------------------------------------------------\n# Option 2\n#\n# HTTP/2 200 OK\n# Date: Tues, 16 Aug 2021 22:06:42 GMT\n# …\n# {\n# \t“errors”:[\n# \t\t{\n# \t\t\t“locations”:[\n# \t\t\t{\n# \t\t\t\t“column”:2,\n# \t\t\t\t:line”:2\n# \t\t\t}\n# \t\t\t],\n# \t\t\t“message”: “Parsing failed at\n# \t\t}\n# \t]\n# }\n# --------------------------------------------------------------\n# Option 3\n#\n# HTTP/2 200 OK\n# Date: Tues, 16 Aug 2022 21:06:42 GMT\n# …\n# {\n# \t“error”:”ID token for user 55e4cb07 at org 1234 expired”\n# {\n# ---------------------------------------------------------------\n# Option 4\n#\n# HTTP/2 404 File Not Found\n# Date: Tues, 16 Aug 2022 21:06:42 GMT\n# …\n# {\n# \t“error”:”/www/home/file.txt not found ”\n# {\n# ---------------------------------------------------------------\n\ninput = Kino.Input.select(\"Choose your answer\", [\n none: \"\",\n a: \"Option 1\", \n b: \"Option 2\", \n c: \"Option 3\",\n d: \"Option 4\"\n], default: :none)\n\nKino.render(input)\n\nKino.Input.read(input)"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{"ESCT" => ESCT, "GRAPHQL" => GRAPHQL, "OWASP" => OWASP}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(GRAPHQL, 2, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down
78 changes: 3 additions & 75 deletions modules/5-elixir.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,7 @@ result =
end
)

[module_id, question_id] =
"# ELIXIR_SECURITY:1\nmalicious_user_input = UUID.uuid4()\n\ntry do\n malicious_user_input\n # ONLY CHANGE NEXT LINE\n |> String.to_atom()\nrescue\n e -> e\nend"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{
"ELIXIR_SECURITY" => ELIXIR_SECURITY,
"GRAPHQL" => GRAPHQL,
"OWASP" => OWASP,
"SDLC" => SDLC
}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(ELIXIR_SECURITY, 1, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down Expand Up @@ -263,31 +239,7 @@ result =
end
)

[module_id, question_id] =
"# ELIXIR_SECURITY:2\n\ndefmodule SecurityCheck do\n def validate(input, password_hash) do\n case Plug.Crypto.secure_compare(input, password_hash) do\n true -> :ok\n false -> :access_denied\n end\n end\n\n defexception message: \"There was an issue\"\nend\n\npassword = \"some_secure_password_hash\"\nuser_input = \"some_string_which_obviously_isnt_the_same_as_the_password\"\n:ok\n# DO NOT EDIT ANY CODE ABOVE THIS LINE =====================\n\ntry do\n# if SecurityCheck.validate(user_input, password) or raise(SecurityCheck) do :you_let_a_baddie_in end\n# if SecurityCheck.validate(user_input, password) || raise(SecurityCheck) do :you_let_a_baddie_in end\nrescue\n e -> e\nend"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{
"ELIXIR_SECURITY" => ELIXIR_SECURITY,
"GRAPHQL" => GRAPHQL,
"OWASP" => OWASP,
"SDLC" => SDLC
}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(ELIXIR_SECURITY, 2, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down Expand Up @@ -361,31 +313,7 @@ result =
:ets.info(secret_table)[:protection]
)

[module_id, question_id] =
"# ELIXIR_SECURITY:3\n\n# ONLY EDIT THIS LINE\nsecret_table = :ets.new(:secret_table, [:public])\n:ets.info(secret_table)[:protection]"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{
"ELIXIR_SECURITY" => ELIXIR_SECURITY,
"GRAPHQL" => GRAPHQL,
"OWASP" => OWASP,
"SDLC" => SDLC
}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(ELIXIR_SECURITY, 3, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down
27 changes: 1 addition & 26 deletions modules/6-cookies.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -197,32 +197,7 @@ result =
{cookie, binary_part(cookie_name, 0, 6)}
)

[module_id, question_id] =
"# COOKIE_SECURITY:1 \n\ncookie_name = \"CHANGE_ME\"\n\n# Uncomment and change the put_resp_cookie call below\n# conn =\n# Plug.Conn.put_resp_cookie(\n# conn,\n# cookie_name,\n# <<0::8, 42::8>>,\n# domain: ...,\n# path: ...,\n# secure: ...,\n# http_only: ...,\n# same_site: ...\n# )\n\ncookie = \n conn\n |> Plug.Conn.fetch_cookies()\n |> Plug.Conn.get_resp_cookies()\n |> Map.fetch!(cookie_name)\n\n{cookie, binary_part(cookie_name, 0, 6)}"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{
"COOKIE_SECURITY" => COOKIE_SECURITY,
"ELIXIR_SECURITY" => ELIXIR_SECURITY,
"GRAPHQL" => GRAPHQL,
"OWASP" => OWASP,
"SDLC" => SDLC
}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(COOKIE_SECURITY, 1, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down
32 changes: 2 additions & 30 deletions modules/7-anti-patterns.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ Penguin.slide([3, 4, 5, 2, 1])

### <span style="color:red;">Quiz</span>

**What sort method is the module above using?**

_Uncomment the line with your answer._
**What sorting algorithm is the module above using?**

<!-- livebook:{"attrs":"eyJzb3VyY2UiOiIjIEFOVElQQVRURVJOUzoxXG5cbmlucHV0ID0gS2luby5JbnB1dC5zZWxlY3QoXCJBbnN3ZXJcIiwgW1xuICBhOiBcIkJ1YmJsZSBTb3J0XCIsXG4gIGI6IFwiTWVyZ2UgU29ydFwiLFxuICBjOiBcIlF1aWNrIFNvcnRcIixcbiAgZDogXCJSYW5kb20gU29ydFwiXG5dKVxuXG5LaW5vLnJlbmRlcihpbnB1dClcblxuS2luby5JbnB1dC5yZWFkKGlucHV0KSJ9","chunks":null,"kind":"Elixir.GradingClient.GradedCell","livebook_object":"smart_cell"} -->

Expand All @@ -92,33 +90,7 @@ result =
Kino.Input.read(input)
)

[module_id, question_id] =
"# ANTIPATTERNS:1\n\ninput = Kino.Input.select(\"Answer\", [\n a: \"Bubble Sort\",\n b: \"Merge Sort\",\n c: \"Quick Sort\",\n d: \"Random Sort\"\n])\n\nKino.render(input)\n\nKino.Input.read(input)"
|> String.split("\n", parts: 2)
|> hd()
|> String.trim_leading("#")
|> String.split(":", parts: 2)

module_id =
case %{
"ANTIPATTERNS" => ANTIPATTERNS,
"COOKIE_SECURITY" => COOKIE_SECURITY,
"ELIXIR_SECURITY" => ELIXIR_SECURITY,
"GRAPHQL" => GRAPHQL,
"OWASP" => OWASP,
"SDLC" => SDLC
}[String.trim(module_id)] do
nil -> raise "invalid module id: #{module_id}"
module_id -> module_id
end

question_id =
case Integer.parse(String.trim(question_id)) do
{id, ""} -> id
_ -> raise "invalid question id: #{question_id}"
end

case GradingClient.check_answer(module_id, question_id, result) do
case GradingClient.check_answer(ANTIPATTERNS, 1, result) do
:correct ->
IO.puts([IO.ANSI.green(), "Correct!", IO.ANSI.reset()])

Expand Down
17 changes: 10 additions & 7 deletions modules/8-cicd.livemd
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,25 @@ This module will cover over some of the automated processes you may see in a CI/

Built in Elixir, for Elixir, by NCC Group - this tool will try to determine whether your codebase has a number of web vulnerabilities as well as the insecurites outlined in [Module 5 - Elixir Security](./5-elixir.livemd).

### <span style="color:blue;">Example</span>
### <span style="color:blue;">Example</span>

Install [Sobelow](https://sobelow.io/) and add it to your application dependencies or install it by following the instructions https://hexdocs.pm/sobelow/readme.html

Scan your project by running the following at a terminal in your project's root directory

```
$ mix sobelow
```
As a vulnerability scanner, there are multiple categories of vulnerabilities sobelow is capable of discovering and reporting on.

For instance, there are a number of security issues published on the Common Weakness Enumeration (CWE) site - [CWE's](https://cwe.mitre.org/top25/archive/2022/2022_cwe_top25.html) and on OWASP Top 10 [OWASP Top 10](https://owasp.org/www-project-top-ten/).
As a vulnerability scanner, there are multiple categories of vulnerabilities sobelow is capable of discovering and reporting on.

For instance, there are a number of security issues published on the Common Weakness Enumeration (CWE) site - [CWE's](https://cwe.mitre.org/top25/archive/2022/2022_cwe_top25.html) and on OWASP Top 10 [OWASP Top 10](https://owasp.org/www-project-top-ten/).

Scanning tools like Sobelow identify code patterns that match these issues and report them back to developers/users.

### <span style="color:blue;">Example</span>
Let's say you are interested finding in places in your application that may be susceptible to injection attacks.
### <span style="color:blue;">Example</span>

Let's say you are interested finding in places in your application that may be susceptible to injection attacks.

There are several types of injection. Referring to the CWE list, we see #17 CWE-77 for Command Injection, #25 CWE-94 is Code Injection, and #3 CWE-89 is SQL Injection. If we look at the OWASP Top 10 for 2021, A03:2021-Injection is third on the list. Sobelow has the capability to detect these types of security issues.

Expand All @@ -59,7 +62,7 @@ Sobelow.CI
Sobelow.CI.OS
Sobelow.CI.System
```

Reference: https://docs.guardrails.io/docs/vulnerabilities/elixir/insecure_use_of_dangerous_function

### Usage
Expand Down
Loading