|
26 | 26 | { |
27 | 27 | "warning_type": "SQL Injection", |
28 | 28 | "warning_code": 0, |
29 | | - "fingerprint": "1cd85bf7cb5861691738b889b473f9419d09e7924b9f8f5665b51de2b66ff64d", |
| 29 | + "fingerprint": "070a52e379818ec073deae3fb2e32266902f7862001941f1a5f0a73b258057a6", |
30 | 30 | "check_name": "SQL", |
31 | 31 | "message": "Possible SQL injection", |
32 | 32 | "file": "app/models/exercise.rb", |
33 | | - "line": 359, |
| 33 | + "line": 444, |
34 | 34 | "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", |
35 | | - "code": "self.class.connection.exec_query(\"\\n WITH working_time AS\\n (\\n SELECT contributor_id,\\n id,\\n exercise_id,\\n Max(score) AS max_score,\\n (created_at - Lag(created_at) OVER (partition BY contributor_id, exercise_id ORDER BY created_at)) AS working_time\\n FROM submissions\\n WHERE #{self.class.sanitize_sql([\"exercise_id = ?\", id])}\\n AND contributor_type IN ('ExternalUser', 'ProgrammingGroup')\\n GROUP BY contributor_id,\\n id,\\n exercise_id), max_points AS\\n (\\n SELECT context_id AS ex_id,\\n Sum(weight) AS max_points\\n FROM files\\n WHERE context_type = 'Exercise'\\n AND #{self.class.sanitize_sql([\"context_id = ?\", id])}\\n AND role IN ('teacher_defined_test', 'teacher_defined_linter')\\n GROUP BY context_id),\\n -- filter for rows containing max points\\n time_max_score AS\\n (\\n SELECT *\\n FROM working_time W1,\\n max_points MS\\n WHERE w1.exercise_id = ex_id\\n AND w1.max_score = ms.max_points),\\n -- find row containing the first time max points\\n first_time_max_score AS\\n (\\n SELECT id,\\n contributor_id,\\n exercise_id,\\n max_score,\\n working_time,\\n rn\\n FROM (\\n SELECT id,\\n contributor_id,\\n exercise_id,\\n max_score,\\n working_time,\\n Row_number() OVER(partition BY contributor_id, exercise_id ORDER BY id ASC) AS rn\\n FROM time_max_score) T\\n WHERE rn = 1), times_until_max_points AS\\n (\\n SELECT w.id,\\n w.contributor_id,\\n w.exercise_id,\\n w.max_score,\\n w.working_time,\\n m.id AS reachedmax_at\\n FROM working_time W,\\n first_time_max_score M\\n WHERE w.contributor_id = m.contributor_id\\n AND w.exercise_id = m.exercise_id\\n AND w.id <= m.id),\\n -- if user never makes it to max points, take all times\\n all_working_times_until_max AS (\\n (\\n SELECT id,\\n contributor_id,\\n exercise_id,\\n max_score,\\n working_time\\n FROM times_until_max_points)\\n UNION ALL\\n (\\n SELECT id,\\n contributor_id,\\n exercise_id,\\n max_score,\\n working_time\\n FROM working_time W1\\n WHERE NOT EXISTS\\n (\\n SELECT 1\\n FROM first_time_max_score F\\n WHERE f.contributor_id = w1.contributor_id\\n AND f.exercise_id = w1.exercise_id))), filtered_times_until_max AS\\n (\\n SELECT contributor_id,\\n exercise_id,\\n max_score,\\n CASE\\n WHEN #{StatisticsHelper.working_time_larger_delta} THEN '0'\\n ELSE working_time\\n END AS working_time_new\\n FROM all_working_times_until_max ), result AS\\n (\\n SELECT e.external_id AS external_contributor_id,\\n f.contributor_id,\\n exercise_id,\\n Max(max_score) AS max_score,\\n Sum(working_time_new) AS working_time\\n FROM filtered_times_until_max f,\\n external_users e\\n WHERE f.contributor_id = e.id\\n GROUP BY e.external_id,\\n f.contributor_id,\\n exercise_id )\\n SELECT unnest(percentile_cont(#{self.class.sanitize_sql([\"array[?]\", quantiles])}) within GROUP (ORDER BY working_time))\\n FROM result\\n \")", |
| 35 | + "code": "self.class.connection.exec_query(\"\\n WITH working_time AS\\n (\\n SELECT contributor_id,\\n contributor_type,\\n created_at,\\n exercise_id,\\n Max(score) AS max_score,\\n (created_at - Lag(created_at) OVER (partition BY contributor_id, exercise_id ORDER BY created_at)) AS working_time\\n FROM submissions\\n WHERE #{self.class.sanitize_sql([\"exercise_id = ?\", id])}\\n GROUP BY contributor_id,\\n contributor_type,\\n id,\\n exercise_id), max_points AS\\n (\\n SELECT context_id AS ex_id,\\n Sum(weight) AS max_points\\n FROM files\\n WHERE context_type = 'Exercise'\\n AND #{self.class.sanitize_sql([\"context_id = ?\", id])}\\n AND role IN ('teacher_defined_test', 'teacher_defined_linter')\\n GROUP BY context_id),\\n -- filter for rows containing max points\\n time_max_score AS\\n (\\n SELECT *\\n FROM working_time W1,\\n max_points MS\\n WHERE w1.exercise_id = ex_id\\n AND w1.max_score = ms.max_points),\\n -- find row containing the first time max points\\n first_time_max_score AS\\n (\\n SELECT created_at,\\n contributor_id,\\n contributor_type,\\n exercise_id,\\n max_score,\\n working_time,\\n rn\\n FROM (\\n SELECT created_at,\\n contributor_id,\\n contributor_type,\\n exercise_id,\\n max_score,\\n working_time,\\n Row_number() OVER(partition BY contributor_id, contributor_type, exercise_id ORDER BY created_at ASC) AS rn\\n FROM time_max_score) T\\n WHERE rn = 1), times_until_max_points AS\\n (\\n SELECT w.created_at,\\n w.contributor_id,\\n w.contributor_type,\\n w.exercise_id,\\n w.max_score,\\n w.working_time,\\n m.created_at AS reachedmax_at\\n FROM working_time W,\\n first_time_max_score M\\n WHERE w.contributor_id = m.contributor_id\\n AND w.contributor_type = m.contributor_type\\n AND w.exercise_id = m.exercise_id\\n AND w.created_at <= m.created_at),\\n -- if user never makes it to max points, take all times\\n all_working_times_until_max AS (\\n (\\n SELECT created_at,\\n contributor_id,\\n contributor_type,\\n exercise_id,\\n max_score,\\n working_time\\n FROM times_until_max_points)\\n UNION ALL\\n (\\n SELECT created_at,\\n contributor_id,\\n contributor_type,\\n exercise_id,\\n max_score,\\n working_time\\n FROM working_time W1\\n WHERE NOT EXISTS\\n (\\n SELECT 1\\n FROM first_time_max_score F\\n WHERE f.contributor_id = w1.contributor_id\\n AND f.contributor_type = w1.contributor_type\\n AND f.exercise_id = w1.exercise_id))), filtered_times_until_max AS\\n (\\n SELECT contributor_id,\\n contributor_type,\\n exercise_id,\\n max_score,\\n CASE\\n WHEN #{StatisticsHelper.working_time_larger_delta} THEN '0'\\n ELSE working_time\\n END AS working_time_new\\n FROM all_working_times_until_max ), result AS\\n (\\n SELECT contributor_id,\\n contributor_type,\\n exercise_id,\\n Max(max_score) AS max_score,\\n Sum(working_time_new) AS working_time\\n FROM filtered_times_until_max\\n GROUP BY contributor_id,\\n contributor_type,\\n exercise_id )\\n SELECT unnest(percentile_cont(#{self.class.sanitize_sql([\"array[?]\", quantiles])}) within GROUP (ORDER BY working_time))\\n FROM result\\n \")", |
36 | 36 | "render_path": null, |
37 | 37 | "location": { |
38 | 38 | "type": "method", |
|
49 | 49 | { |
50 | 50 | "warning_type": "SQL Injection", |
51 | 51 | "warning_code": 0, |
52 | | - "fingerprint": "277bcd4729b671541c9cd43b3de3423f2f621578a55ecbf547ac2f42ec50e9eb", |
| 52 | + "fingerprint": "d78908a8173535fb77f61486223bd1f5b5353b5f01a32b5ab253883997102085", |
53 | 53 | "check_name": "SQL", |
54 | 54 | "message": "Possible SQL injection", |
55 | 55 | "file": "app/models/exercise.rb", |
56 | | - "line": 453, |
| 56 | + "line": 537, |
57 | 57 | "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", |
58 | | - "code": "self.class.connection.exec_query(\"\\n WITH WORKING_TIME AS\\n (SELECT contributor_id,\\n id,\\n exercise_id,\\n max(score) AS max_score,\\n (created_at - lag(created_at) OVER (PARTITION BY contributor_id, exercise_id\\n ORDER BY created_at)) AS working_time\\n FROM submissions\\n WHERE #{self.class.sanitize_sql([\"exercise_id = :id AND contributor_id = :contributor_id AND contributor_type = :contributor_type\", { :id => id, :contributor_id => contributor.id, :contributor_type => contributor.class.name }])}\\n GROUP BY contributor_id, id, exercise_id),\\n MAX_POINTS AS\\n (SELECT context_id AS ex_id, sum(weight) AS max_points FROM files WHERE context_type = 'Exercise' AND context_id = #{id} AND role IN ('teacher_defined_test', 'teacher_defined_linter') GROUP BY context_id),\\n\\n -- filter for rows containing max points\\n TIME_MAX_SCORE AS\\n (SELECT *\\n FROM WORKING_TIME W1, MAX_POINTS MS\\n WHERE W1.exercise_id = ex_id AND W1.max_score = MS.max_points),\\n\\n -- find row containing the first time max points\\n FIRST_TIME_MAX_SCORE AS\\n ( SELECT id,contributor_id,exercise_id,max_score,working_time, rn\\n FROM (\\n SELECT id,contributor_id,exercise_id,max_score,working_time,\\n ROW_NUMBER() OVER(PARTITION BY contributor_id, exercise_id ORDER BY id ASC) AS rn\\n FROM TIME_MAX_SCORE) T\\n WHERE rn = 1),\\n\\n TIMES_UNTIL_MAX_POINTS AS (\\n SELECT W.id, W.contributor_id, W.exercise_id, W.max_score, W.working_time, M.id AS reachedmax_at\\n FROM WORKING_TIME W, FIRST_TIME_MAX_SCORE M\\n WHERE W.contributor_id = M.contributor_id AND W.exercise_id = M.exercise_id AND W.id <= M.id),\\n\\n -- if contributor never makes it to max points, take all times\\n ALL_WORKING_TIMES_UNTIL_MAX AS\\n ((SELECT id, contributor_id, exercise_id, max_score, working_time FROM TIMES_UNTIL_MAX_POINTS)\\n UNION ALL\\n (SELECT id, contributor_id, exercise_id, max_score, working_time FROM WORKING_TIME W1\\n WHERE NOT EXISTS (SELECT 1 FROM FIRST_TIME_MAX_SCORE F WHERE F.contributor_id = W1.contributor_id AND F.exercise_id = W1.exercise_id))),\\n\\n FILTERED_TIMES_UNTIL_MAX AS\\n (\\n SELECT contributor_id,exercise_id, max_score, CASE WHEN #{StatisticsHelper.working_time_larger_delta} THEN '0' ELSE working_time END AS working_time_new\\n FROM ALL_WORKING_TIMES_UNTIL_MAX\\n )\\n SELECT e.external_id AS external_contributor_id, f.contributor_id, exercise_id, MAX(max_score) AS max_score, sum(working_time_new) AS working_time\\n FROM FILTERED_TIMES_UNTIL_MAX f, EXTERNAL_USERS e\\n WHERE f.contributor_id = e.id GROUP BY e.external_id, f.contributor_id, exercise_id\\n \")", |
| 58 | + "code": "self.class.connection.exec_query(\"\\n WITH WORKING_TIME AS\\n (SELECT contributor_id,\\n contributor_type,\\n created_at,\\n exercise_id,\\n max(score) AS max_score,\\n (created_at - lag(created_at) OVER (PARTITION BY contributor_id, contributor_type, exercise_id\\n ORDER BY created_at)) AS working_time\\n FROM submissions\\n WHERE #{self.class.sanitize_sql([\"exercise_id = :id AND contributor_id = :contributor_id AND contributor_type = :contributor_type\", { :id => id, :contributor_id => contributor.id, :contributor_type => contributor.class.name }])}\\n GROUP BY contributor_id, contributor_type, created_at, exercise_id),\\n MAX_POINTS AS\\n (SELECT context_id AS ex_id, sum(weight) AS max_points FROM files WHERE context_type = 'Exercise' AND context_id = #{id} AND role IN ('teacher_defined_test', 'teacher_defined_linter') GROUP BY context_id),\\n\\n -- filter for rows containing max points\\n TIME_MAX_SCORE AS\\n (SELECT *\\n FROM WORKING_TIME W1, MAX_POINTS MS\\n WHERE W1.exercise_id = ex_id AND W1.max_score = MS.max_points),\\n\\n -- find row containing the first time max points\\n FIRST_TIME_MAX_SCORE AS\\n ( SELECT created_at, contributor_id, contributor_type, exercise_id, max_score, working_time, rn\\n FROM (\\n SELECT created_at, contributor_id, contributor_type, exercise_id, max_score, working_time,\\n ROW_NUMBER() OVER(PARTITION BY contributor_id, contributor_type, exercise_id ORDER BY created_at ASC) AS rn\\n FROM TIME_MAX_SCORE) T\\n WHERE rn = 1),\\n\\n TIMES_UNTIL_MAX_POINTS AS (\\n SELECT W.created_at, W.contributor_id, W.contributor_type, W.exercise_id, W.max_score, W.working_time, M.created_at AS reachedmax_at\\n FROM WORKING_TIME W, FIRST_TIME_MAX_SCORE M\\n WHERE W.contributor_id = M.contributor_id AND W.contributor_type = M.contributor_type AND W.exercise_id = M.exercise_id AND W.created_at <= M.created_at),\\n\\n -- if contributor never makes it to max points, take all times\\n ALL_WORKING_TIMES_UNTIL_MAX AS\\n ((SELECT created_at, contributor_id, contributor_type, exercise_id, max_score, working_time FROM TIMES_UNTIL_MAX_POINTS)\\n UNION ALL\\n (SELECT created_at, contributor_id, contributor_type, exercise_id, max_score, working_time FROM WORKING_TIME W1\\n WHERE NOT EXISTS (SELECT 1 FROM FIRST_TIME_MAX_SCORE F WHERE F.contributor_id = W1.contributor_id AND F.contributor_type = W1.contributor_type AND F.exercise_id = W1.exercise_id))),\\n\\n FILTERED_TIMES_UNTIL_MAX AS\\n (\\n SELECT contributor_id, contributor_type, exercise_id, max_score, CASE WHEN #{StatisticsHelper.working_time_larger_delta} THEN '0' ELSE working_time END AS working_time_new\\n FROM ALL_WORKING_TIMES_UNTIL_MAX\\n )\\n SELECT contributor_id, contributor_type, exercise_id, MAX(max_score) AS max_score, sum(working_time_new) AS working_time\\n FROM FILTERED_TIMES_UNTIL_MAX\\n GROUP BY contributor_id, contributor_type, exercise_id\\n \")", |
59 | 59 | "render_path": null, |
60 | 60 | "location": { |
61 | 61 | "type": "method", |
|
70 | 70 | "note": "The `StatisticsHelper.working_time_larger_delta` already returns an SQL-escaped string and does not allow passing any params." |
71 | 71 | } |
72 | 72 | ], |
73 | | - "updated": "2024-08-22 23:05:04 +0200", |
74 | | - "brakeman_version": "6.2.1" |
| 73 | + "brakeman_version": "7.1.0" |
75 | 74 | } |
0 commit comments