転職3ヶ月の記録:CursorでのキャッチアップとRuffセキュリティオプションを使用した開発の紹介

その他

2025.12.14

Topics

この記事はNHN テコラス Advent Calendar 2025の14日目の記事です。

はじめに

はじめまして。今年の9月にNHNテコラスに転職し、データ分析基盤開発チームでETLパイプラインの開発をしています。転職してから早3ヵ月が経ち、環境にも少しずつですが慣れてきました。開発で取り扱うデータのドメイン知識や既存コードの理解等、転職後から振り返るとキャッチアップが大変だったと改めて感じます。
そんな中で大きな助けとなったのが、AI搭載のコードエディタCursorです。
チーム内ではCursorを使用した開発がルール化されていて、転職後のキャッチアップにも活用できました。
チーム内でのCursor活用のルールや効果検証については下記を参考にして下さい。

関連記事
Cursorで加速するチーム開発

入社後からPythonを中心とした開発を実施してきましたが、中でも、静的コード解析ツールのRuffを使用した開発が印象的でした。
この記事では、転職3ヶ月の記録としてCursorでのキャッチアップとRuffセキュリティオプションについてご紹介します。

①Cursorを利用した既存コード理解

Cursorでは、生成AIによる自律的なコード開発のためにチャット形式で3つのモードを選択できるAgentが搭載されています。
Agentでは、3つのモードを選択できます。

Agent:複雑な機能開発、リファクタリング で活用。自律的な探索、複数ファイルの編集を行う
Ask:学習、計画、質問で活用。 読み取り専用での探索、自動変更なし
Plan:事前の計画が必要な複雑な機能開発。実行前に詳細なプランを作成し、不明点を質問して確認
出典:モード

キャッチアップには、Askモードが役立ちました。Cursorの活用例について紹介します。

フォルダを指定して概要を理解

Cursorでフォルダを開くと、自動的にフォルダ内のファイルがインデックス化されます。
この状態でフォルダを指定して質問すると、フォルダ内のファイルを横断してAgentで質問できます。
ドメイン知識を身につけた上でフォルダを指定して質問をすると、理解が早まりました。
Agentの質問と回答のスクリーンショット

コードの指定行に対して質問する

Cursorでは、コードの指定行に対しても質問が可能な為、複数のファイルに渡った質問をすると役立ちました。
Agentの質問と回答のスクリーンショット

Ruffによる厳密なLintルールを通過することがチーム内のルールとなっていて、前職ではここまで厳密なLintルールを通過することが求められていなかったため、最初は戸惑いました。
Cursorでは指定行のRuff Lintエラーについても質問するとエラーの修正のみではなくエラーの意味や修正方法も教えてくれるので、エラーの意味を理解しながら修正することができました。

②チームでのRuffセキュリティオプション活用について

Pythonを使用した開発では、uv + Ruffを使用した開発を行っています。
uvは、Pythonのパッケージ管理ツールです。
Ruffは、Pythonの静的コード解析やフォーマットを兼ね備えたツールです。
両方のツールともRustで作られており、高速に動作することが特徴です。
uvとRuffともに同じ設定ファイル(pyproject.toml)による設定が可能で、Ruffの解析ルールを設定可能です。
下記のように設定ができます。

[project]
name = "sample-project-name"
version = "0.1.0"
description = "sample project description"
authors = [
    {name = "Your Name", email = "your.email@example.com"}
]
readme = "README.md"
requires-python = ">=3.14,<3.15.0" # Pythonのバージョンを指定
dependencies = [
    # プロジェクトの依存関係をここに記述
    "requests>=2.25.0",
    "click>=8.0.0",
    ...
]
[tool.ruff]
exclude = [
    # Ruffの設定:ファイルの除外設定
    ".git",
    ...
]
[tool.ruff.lint]
select = [
    # Ruffの設定:有効にするルール
    "S",   # セキュリティオプション
    "ARG", # flake8-unused-arguments (未使用引数) 
    "B",   # flake8-bugbear (バグの可能性)
    ...
]
ignore = [
    # Ruffの設定:無視するルール
    "ARG002",  # classの関数に未使用の引数が存在するか
    "B009",    # 定数属性値を使用したgetattrの使用を避ける
    ...
]

セキュリティオプションの具体的な活用について

pyproject.toml等設定ファイルでセキュリティオプション(-S)を追加することで、セキュリティ対策を強化できます。
安全なコーディングパターンをいくつか紹介します。

S307:evalの禁止

eval()は、動的にコードを実行する関数の為、安全ではありません。
eval()を使用しているとS307Ruffチェックエラー対象となるため、改善が必要です。

#悪い例
def execute(self):
    # S102: eval()の使用は危険
    return eval(self.method_name)

#良い例
def execute(self):
    # 安全なメソッド呼び出し
    method = getattr(self.client, self.method_name, None)
    if method is None:
        raise AttributeError(f"Method {self.method_name} not found")
    return method()

S608:SQLインジェクション

SQLインジェクションとは、SQL文に不正な入力を渡すことで、意図しないSQL文が実行される攻撃手法です。
データベースへのクエリについてSQL文を直接ハードコードし変数で変更可能な場合、S608Ruffチェックエラー対象となるため、改善が必要です。
パラメータ化クエリを使用しクエリとパラメータを分離することで、SQLインジェクションを防げます。

#悪い例
def delete_query(table_name, user_id):
    # S608:SQLインジェクションの危険性
    # table_nameおよびuser_idが変更可能で危険
    query = f"DELETE FROM {table_name} WHERE id = '{user_id}'"
    return execute_query(query)

#良い例
def delete_query(user_id):
    # 安全なメソッド呼び出し
    query = "DELETE FROM example WHERE id = '%s'" #プレースホルダーを使用(推奨)、テーブル名は固定
    return execute_delete_query(query, user_id) #パラメータ化クエリを使用した関数の実行

S113:無制限なrequests処理

requestsやhttpxモジュールを使用して外部APIを呼び出す場合、タイムアウト無しでAPI呼び出しを行うとS113Ruffチェックエラー対象となります。
タイムアウト無しで応答が無い場合、プログラムがハングアップする可能性があります。
タイムアウトの時間を指定することで、改善が可能です。

#悪い例
import requests
response = requests.get("https://api.example.com/data")

#良い例
response = requests.get("https://api.example.com/data", timeout=10)

S311:暗号化目的でのrandomモジュール利用の禁止

randomモジュールは、暗号化目的で使用する際は予測が可能なため、S311Ruffチェックエラー対象となります。
sercretsモジュール等、機密情報を扱うため乱数を生成するモジュールを使用することで、改善が可能です。

#悪い例
import random
random_secret_number = random.randint(1, 10)

#良い例
import secrets
random_secret_number = secrets.randbelow(10) + 1

S106:機密情報のハードコーディング禁止

ソースコードに直接パスワード等の機密情報がハードコーディングされている場合、S106Ruffチェックエラー対象となります。
環境変数等を使用して機密情報をソースコード外で管理することで改善が可能です。

#悪い例
password = connect_to_service(password="password")

#良い例
password = connect_to_service(password=os.getenv("PASSWORD")) # 環境変数としてソースコード外でパスワードは管理

まとめ

転職3ヶ月の記録としてCursorでのキャッチアップを振り返り、Ruffセキュリティオプションについて紹介しました。
Ruffのおかげでコードの品質は一定水準まで担保できるので、コードレビューを依頼する前に自分で気づけるようになったり、既存コードの読み込みもしやすくなりました。
Cursorを活用することで理解を早め、これからもエンジニアとして成長していきたいです!

NHN テコラスの採用情報はこちら

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

taisuke

データ分析基盤開発チームに所属しています。 趣味はゲームやジム通いです。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら