From 7ac6b3a79bda668f3a8247513c3f312d797165f3 Mon Sep 17 00:00:00 2001 From: nacchan Date: Mon, 11 Aug 2025 10:42:36 +0900 Subject: [PATCH 1/2] =?UTF-8?q?security:=20SlackNotifier=E3=81=A7=E3=81=AE?= =?UTF-8?q?Command=20Injection=E8=84=86=E5=BC=B1=E6=80=A7=E3=82=92?= =?UTF-8?q?=E8=A7=A3=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - app/services/slack_notifier.rb を新規追加 - curlコマンドをNet::HTTPに置換し、外部入力を安全に処理 - タイムアウト設定とエラーハンドリングを追加 - 2箇所のCommand Injection警告を解消 --- app/services/slack_notifier.rb | 34 ++++++++++++++++++++++++++++++ lib/statistics/aggregation.rb | 2 +- lib/upcoming_events/aggregation.rb | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 app/services/slack_notifier.rb diff --git a/app/services/slack_notifier.rb b/app/services/slack_notifier.rb new file mode 100644 index 00000000..2a1e5026 --- /dev/null +++ b/app/services/slack_notifier.rb @@ -0,0 +1,34 @@ +require "net/http" +require "uri" +require "json" + +class SlackNotifier + class << self + # @param message [String] 通知するメッセージ + # @param webhook_url [String] SlackのWebhook URL + # @return [Boolean] 送信成功なら true / 失敗なら false + def post_message(message, webhook_url) + return false if webhook_url.blank? + + uri = URI.parse(webhook_url) + + request = Net::HTTP::Post.new(uri) + request["Content-Type"] = "application/json" + request.body = { text: message.to_s }.to_json + + response = Net::HTTP.start( + uri.host, + uri.port, + use_ssl: uri.scheme == "https", + open_timeout: 5, + read_timeout: 5 + ) { |http| http.request(request) } + + Rails.logger.info("Slack通知レスポンスコード: #{response.code}") + response.code.to_i.between?(200, 299) + rescue StandardError => e + Rails.logger.warn("Slack通知エラー: #{e.class} #{e.message}") + false + end + end +end diff --git a/lib/statistics/aggregation.rb b/lib/statistics/aggregation.rb index a9bf0813..e68da3d9 100644 --- a/lib/statistics/aggregation.rb +++ b/lib/statistics/aggregation.rb @@ -160,7 +160,7 @@ def notifierable? def notify(msg) $stdout.puts msg - puts `curl -X POST -H 'Content-type: application/json' --data '{"text":"#{msg}"}' #{slack_hook_url} -o /dev/null -w "slack: %{http_code}"` if notifierable? + SlackNotifier.post_message(msg, slack_hook_url) if notifierable? end end end diff --git a/lib/upcoming_events/aggregation.rb b/lib/upcoming_events/aggregation.rb index e7809d9c..90217813 100644 --- a/lib/upcoming_events/aggregation.rb +++ b/lib/upcoming_events/aggregation.rb @@ -86,7 +86,7 @@ def notifierable? def notify(msg) $stdout.puts msg - puts `curl -X POST -H 'Content-type: application/json' --data '{"text":"#{msg}"}' #{slack_hook_url} -o /dev/null -w "slack: %{http_code}"` if notifierable? + SlackNotifier.post_message(msg, slack_hook_url) if notifierable? end end end From 3cd4b77f572eb27f9f40d6badf7af454a4bf8024 Mon Sep 17 00:00:00 2001 From: nacchan Date: Mon, 11 Aug 2025 11:21:26 +0900 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20Command=20Injection=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E5=AE=8C=E4=BA=86=E3=81=AB=E4=BC=B4=E3=81=84=E8=A9=B2?= =?UTF-8?q?=E5=BD=93=E3=81=AEBrakeman=20ignore=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/brakeman.ignore | 46 ------------------------------------------ 1 file changed, 46 deletions(-) diff --git a/config/brakeman.ignore b/config/brakeman.ignore index 4b3ac025..4e055a9a 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -23,29 +23,6 @@ ], "note": "" }, - { - "warning_type": "Command Injection", - "warning_code": 14, - "fingerprint": "7307f11036b1ab86f410d8d967d3972618705df73cafdd17f8e311c10c76c1f1", - "check_name": "Execute", - "message": "Possible command injection", - "file": "lib/statistics/aggregation.rb", - "line": 163, - "link": "https://brakemanscanner.org/docs/warning_types/command_injection/", - "code": "`curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"#{msg}\"}' #{slack_hook_url} -o /dev/null -w \"slack: %{http_code}\"`", - "render_path": null, - "location": { - "type": "method", - "class": "Statistics::Statistics::Aggregation::Notifier", - "method": "s(:self).notify" - }, - "user_input": "msg", - "confidence": "Medium", - "cwe_id": [ - 77 - ], - "note": "" - }, { "warning_type": "Cross-Site Scripting", "warning_code": 4, @@ -244,29 +221,6 @@ 79 ], "note": "" - }, - { - "warning_type": "Command Injection", - "warning_code": 14, - "fingerprint": "e5394a11f2e9bb6bc213b7ebd34fbcead20048858592aa19e5ae2961f33c636d", - "check_name": "Execute", - "message": "Possible command injection", - "file": "lib/upcoming_events/aggregation.rb", - "line": 89, - "link": "https://brakemanscanner.org/docs/warning_types/command_injection/", - "code": "`curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"#{msg}\"}' #{slack_hook_url} -o /dev/null -w \"slack: %{http_code}\"`", - "render_path": null, - "location": { - "type": "method", - "class": "UpcomingEvents::UpcomingEvents::Aggregation::Notifier", - "method": "s(:self).notify" - }, - "user_input": "msg", - "confidence": "Medium", - "cwe_id": [ - 77 - ], - "note": "" } ], "brakeman_version": "7.1.0"