Work on this exercise locally
This web app is a reference guide — you can read instructions, browse starter code, and view tests here. To actually complete the exercise, you need to work in your local development environment.
git clone https://github.com/weihaoqu/program-analysis-bootcamp-studentfailwith "TODO" with your implementation.dune runtest modules/module5-security-analysis/exercises/vulnerability-detectionVulnerability Detection
7. Exercise 5: Vulnerability Detection (18 tests)
Goal: Combine taint propagation with a security configuration to detect OWASP vulnerability patterns -- SQL injection, XSS, command injection, path traversal, and open redirect.
Time: ~30 minutes
File to edit: exercises/vulnerability-detection/starter/vuln_detector.ml
Also provided (read-only):
exercises/vulnerability-detection/starter/taint_domain.ml-- fully implementedexercises/vulnerability-detection/starter/vuln_config.ml-- security config withdefault_config,is_source,find_sink,find_sanitizerexercises/vulnerability-detection/starter/sample_programs.ml-- test programs
Dependencies: abstract_domains, shared_ast
Architecture
vuln_config.ml (provided) vuln_detector.ml (YOUR CODE)
+---------------------------+ +------------------------------------+
| default_config | | eval_expr : config -> Env.t |
| is_source, find_sink, | | -> expr -> taint |
| find_sanitizer | | |
+---------------------------+ | check_call : config -> Env.t |
| -> ... -> vulnerability |
taint_domain.ml (provided) | list |
+---------------------------+ | |
| Bot/Untainted/Tainted/Top | | transfer_and_check : config -> ... |
| join, propagate, ... | | -> Env.t * vulnerability list |
+---------------------------+ | |
| analyze_function, analyze_program |
sample_programs.ml (provided) | format_vulnerability |
+---------------------------+ | severity_of_vuln_type |
| sql_injection, xss_ | +------------------------------------+
| reflected, command_ |
| injection, ... |
+---------------------------+
The vulnerability record
type vulnerability = {
vuln_type : string; (* e.g. "sql-injection" *)
location : string; (* function name *)
source_var : string; (* the tainted variable *)
sink_name : string; (* the sink function called *)
message : string; (* human-readable description *)
}
What to implement (in order)
| # | Function | Hint |
|---|---|---|
| 1 | severity_of_vuln_type vt | "sql-injection", "command-injection" -> Critical; "xss", "path-traversal" -> High; "open-redirect" -> Medium; other -> Low |
| 2 | string_of_severity s | Critical -> "CRITICAL", High -> "HIGH", Medium -> "MEDIUM", Low -> "LOW" |
| 3 | eval_expr config env e | Like Exercise 3, but use Vuln_config.is_source config, Vuln_config.find_sanitizer config, etc. instead of hardcoded lists |
| 4 | check_call config env func_name call_name args | If call_name is a sink, evaluate the argument at sink_param_index -- if potentially tainted, create a vulnerability record |
| 5 | transfer_and_check config func_name env s | Transfer the statement (updating env) AND check any Call expressions for vulnerabilities. Return (updated_env, vulnerabilities) |
| 6 | analyze_function config func | Initialize params to Top, fold transfer_and_check over body, collect all vulnerabilities |
| 7 | analyze_program config prog | Map analyze_function over all functions, concatenate vulnerabilities |
| 8 | format_vulnerability v | Must include the severity string (e.g. "CRITICAL") -- the test checks for it |
Run tests
dune runtest modules/module5-security-analysis/exercises/vulnerability-detection/
Starter output (before any implementation):
EEEEEEEEEEEEEEEEEE
All 18 tests error. Start with the simple helper functions (severity_of_vuln_type,
string_of_severity), then eval_expr, then build up from there.
Hints
-
check_call: Use
Vuln_config.find_sink config call_name. If it returnsSome sink, evaluate the argument at indexsink.sink_param_index. If the taint is potentially tainted (Taint_domain.is_potentially_tainted), return a vulnerability. If the argument index is out of range or the call is not a sink, return[]. -
transfer_and_check: For an
Assign(x, e)whereeisCall(name, args), you need to both update the environment AND check the call. ForIfandWhile, recurse into branches and collect vulnerabilities from both. -
format_vulnerability: The test checks that the output
contains_substring"CRITICAL"for a sql-injection vulnerability. Make sureseverity_of_vuln_typeandstring_of_severitywork correctly first.
Starter Files
Test Files
Work on this exercise locally
This web app is a reference guide — you can read instructions, browse starter code, and view tests here. To actually complete the exercise, you need to work in your local development environment.
git clone https://github.com/weihaoqu/program-analysis-bootcamp-studentfailwith "TODO" with your implementation.dune runtest modules/module5-security-analysis/exercises/vulnerability-detectionVulnerability Detection
7. Exercise 5: Vulnerability Detection (18 tests)
Goal: Combine taint propagation with a security configuration to detect OWASP vulnerability patterns -- SQL injection, XSS, command injection, path traversal, and open redirect.
Time: ~30 minutes
File to edit: exercises/vulnerability-detection/starter/vuln_detector.ml
Also provided (read-only):
exercises/vulnerability-detection/starter/taint_domain.ml-- fully implementedexercises/vulnerability-detection/starter/vuln_config.ml-- security config withdefault_config,is_source,find_sink,find_sanitizerexercises/vulnerability-detection/starter/sample_programs.ml-- test programs
Dependencies: abstract_domains, shared_ast
Architecture
vuln_config.ml (provided) vuln_detector.ml (YOUR CODE)
+---------------------------+ +------------------------------------+
| default_config | | eval_expr : config -> Env.t |
| is_source, find_sink, | | -> expr -> taint |
| find_sanitizer | | |
+---------------------------+ | check_call : config -> Env.t |
| -> ... -> vulnerability |
taint_domain.ml (provided) | list |
+---------------------------+ | |
| Bot/Untainted/Tainted/Top | | transfer_and_check : config -> ... |
| join, propagate, ... | | -> Env.t * vulnerability list |
+---------------------------+ | |
| analyze_function, analyze_program |
sample_programs.ml (provided) | format_vulnerability |
+---------------------------+ | severity_of_vuln_type |
| sql_injection, xss_ | +------------------------------------+
| reflected, command_ |
| injection, ... |
+---------------------------+
The vulnerability record
type vulnerability = {
vuln_type : string; (* e.g. "sql-injection" *)
location : string; (* function name *)
source_var : string; (* the tainted variable *)
sink_name : string; (* the sink function called *)
message : string; (* human-readable description *)
}
What to implement (in order)
| # | Function | Hint |
|---|---|---|
| 1 | severity_of_vuln_type vt | "sql-injection", "command-injection" -> Critical; "xss", "path-traversal" -> High; "open-redirect" -> Medium; other -> Low |
| 2 | string_of_severity s | Critical -> "CRITICAL", High -> "HIGH", Medium -> "MEDIUM", Low -> "LOW" |
| 3 | eval_expr config env e | Like Exercise 3, but use Vuln_config.is_source config, Vuln_config.find_sanitizer config, etc. instead of hardcoded lists |
| 4 | check_call config env func_name call_name args | If call_name is a sink, evaluate the argument at sink_param_index -- if potentially tainted, create a vulnerability record |
| 5 | transfer_and_check config func_name env s | Transfer the statement (updating env) AND check any Call expressions for vulnerabilities. Return (updated_env, vulnerabilities) |
| 6 | analyze_function config func | Initialize params to Top, fold transfer_and_check over body, collect all vulnerabilities |
| 7 | analyze_program config prog | Map analyze_function over all functions, concatenate vulnerabilities |
| 8 | format_vulnerability v | Must include the severity string (e.g. "CRITICAL") -- the test checks for it |
Run tests
dune runtest modules/module5-security-analysis/exercises/vulnerability-detection/
Starter output (before any implementation):
EEEEEEEEEEEEEEEEEE
All 18 tests error. Start with the simple helper functions (severity_of_vuln_type,
string_of_severity), then eval_expr, then build up from there.
Hints
-
check_call: Use
Vuln_config.find_sink config call_name. If it returnsSome sink, evaluate the argument at indexsink.sink_param_index. If the taint is potentially tainted (Taint_domain.is_potentially_tainted), return a vulnerability. If the argument index is out of range or the call is not a sink, return[]. -
transfer_and_check: For an
Assign(x, e)whereeisCall(name, args), you need to both update the environment AND check the call. ForIfandWhile, recurse into branches and collect vulnerabilities from both. -
format_vulnerability: The test checks that the output
contains_substring"CRITICAL"for a sql-injection vulnerability. Make sureseverity_of_vuln_typeandstring_of_severitywork correctly first.