Python で requests を使って Webサイトにアクセスする際に、タイムアウトを設定してみた

前のブログで bandit を利用し、Webサイトのスクレイピングを行っている pythonプログラムのセキュリティチェックを行ってみました。

http://k2-ornata.com/python_security_check_with_bandit/

すると、上記ブログにも記載したとおり「Requests call without timeout」という警告が出てしまった為、警告の指示通り、requests の部分に timeout を設定してみることにしました。

1.修正前

修正前は、ただ「requests.get(url)」としているだけでした。

response = requests.get(url)
html = response.content.decode("utf-8")

2.修正後

「requests.get(url)」としていた部分を「requests.get(url, timeout=(6.0, 10.0))」とし、タイムアウトが発生した際の例外処理を行っています。

from requests.exceptions import Timeout
・・・
# Get the HTML content of the top page
try:
    response = requests.get(url, timeout=(6.0, 10.0))
    html = response.content.decode("utf-8")
except Timeout:
    print(f"\n[Timeout {url}]")

なお、timeout の後ろに2つ数字を書いている理由ですが、
timeoutには、connect timeout(前) と read timeout(後) の2種類がある為です。

この2種類のタイムアウトについては、以下のサイトで詳しく説明されていますのでご紹介しておきます。(ありがとうございました!)

【Python】requestsを使うときは必ずtimeoutを設定するべき(Cosnomi Blog)https://blog.cosnomi.com/posts/1259/

3.bandit 実行結果

以下が修正後の pythonプログラムに対する実行結果です。

「Test results:」が「No issues identified.」となっており、問題が解消されたことが確認できました。

% bandit test.py
[main]	INFO	profile include tests: None
[main]	INFO	profile exclude tests: None
[main]	INFO	cli include tests: None
[main]	INFO	cli exclude tests: None
[main]	INFO	running on Python 3.8.3
[node_visitor]	WARNING	Unable to find qualified name for module: test.py
Run started:2023-08-14 08:04:48.814175

Test results:
	No issues identified.

Code scanned:
	Total lines of code: 53
	Total lines skipped (#nosec): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 0
		Medium: 0
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 0
		Medium: 0
		High: 0
Files skipped (0):
%

bandit を使って pythonコードのセキュリティチェックを行ってみた

python言語ってC言語などにくらべると安全そうなイメージがありますが、やはりセキュリティには気をつけないといけない、ということで 開発した python コードが安全かどうか調べるツールがないか調べてみました。

すると、bandit というツールが無償で利用できることがわかりました。

そこでこのツールを使って自分で開発した python プログラムのセキュリティチェックを行ってみましたのでここに記録しておきます。

なお、この bandit でチェックする前に、python のコーディング規約チェッカーである PEP 8 を使ってある程度(- -; コーディング規約に従うようにプログラムを修正しております。

この PEP 8 の PyCharm での利用方法については以下のサイトに記載しております。

http://k2-ornata.com/pychart_pep-8_check/

それでは bandit をインストールするところから行きたいと思います。

1.bandit のインストール

bandit のインストールは非常に簡単です。

pip がインストールされていれば、以下のコマンドを実行するだけです。

$ pip install pandit

なお、私の環境では pythonのバージョンがデフォルトで 2.X系になってしまっていた為、以下のような警告が出てしまいました。

bandit インストール時の警告

これを3系に変えようと思い pyenv を利用してみましたが一筋縄ではいかず、以下のサイトに助けていただきうまくいきました。ありがとうございました。m(_ _)m

pyenvでPythonのバージョンが切り替わらないときの対処方法【Mac Apple silicon環境】(ヒトリセカイ)https://hitori-sekai.com/python/error-pyenv/

2.banditの実行

bandit の実行も非常に簡単です。以下のとおりコマンドを打つだけです。

$ bandit <プログラム名>

実際に自分で作成したスクレイピングを行う pythonプログラムに対して実行してみた結果は以下の通りです。

bandit 実行結果

ちょっと上の画像は見にくいので、テキストでも掲載しておきます。

% bandit test.py
[main]	INFO	profile include tests: None
[main]	INFO	profile exclude tests: None
[main]	INFO	cli include tests: None
[main]	INFO	cli exclude tests: None
[main]	INFO	running on Python 3.8.3
[node_visitor]	WARNING	Unable to find qualified name for module: test.py
Run started:2023-08-14 01:37:45.050500

Test results:
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: test.py:31:11
30	# Get the HTML content of the top page
31	response = requests.get(url)
32	html = response.content.decode("utf-8")

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: test.py:62:15
61
62	    response = requests.get(link)
63	    html = response.content.decode("utf-8")

--------------------------------------------------

Code scanned:
	Total lines of code: 46
	Total lines skipped (#nosec): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 0
		Medium: 2
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 2
		Medium: 0
		High: 0
Files skipped (0):
%

3.bandit 実行結果の考察

どうやら「Test results:」という部分にプログラムの問題点が列挙されているようです。

2つ「Issue」が記載されていますが、どちらも Requests call without timeout となっています。

実際このプログラムでは指定したWebサイトからデータを取ってきているのですが、その時にタイムアウトの処理をしていませんでした。

たしかにこのままだと、Webサイトから応答が返ってくるまで繋ぎっぱなしになってしまい、そのまま何度もこのプログラムを実行するとサーバもクライアントもリソーズ不足になってしまいそうです。

改めて、こういったセキュリティチェック(ツール)の重要性を認識することができました。