# 脆弱性があるソースコードがちゃんと修正されるかの実験
Java でデシリアライゼーション時にノーチェックのプログラムを書いてそれを aiderを使って修正できるかの検証をしてみました。
使用環境などは以下です
https://qiita.com/maestro_shin1/items/4e9e163b65c4042fcbbe
モデルは qwen3.6-35b-a3b を使ってみました
ダメなソース
package com.example.demo;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class LogWriter implements Serializable {
private static final long serialVersionUID = 1L;
private String path;
private String content;
// デシリアライズ時に実行されるマジックメソッド
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // 通常の復元
// 脆弱性のポイント: 復元されたパスと内容でファイルを書き出す
try (FileWriter fw = new FileWriter(path)) {
fw.write(content);
System.out.println("[Vulnerability] File written to: " + path);
}
}
}
aiderさんへ依頼
プロンプト
/add src/main/java/com/example/demo/LogWriter.java
このソースコードを解析して、問題点があれば報告してください
実行結果
ちゃんと理解されているようです
修正されたソースコード
package com.example.demo;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.nio.file.Path;
import java.nio.file.Paths;
public class LogWriter implements Serializable {
private static final long serialVersionUID = 1L;
private String path;
private String content;
// 許可された書き込み先ディレクトリ(環境に合わせて設定)
private static final String ALLOWED_BASE_DIR = "/var/logs/app";
// デシリアライズ時に実行されるマジックメソッド
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // 通常の復元
// 1. null チェック
if (path == null || content == null) {
throw new IOException("Invalid data: path and content must not be null");
}
// 2. パストラバーサル対策: パスを正規化し、許可されたディレクトリ内か検証
Path normalizedPath = Paths.get(path).normalize();
if (!normalizedPath.startsWith(ALLOWED_BASE_DIR)) {
throw new IOException("Invalid path: path must be within " + ALLOWED_BASE_DIR);
}
// 3. コンテンツの長さ制限(例: 1000文字)
if (content.length() > 1000) {
throw new IOException("Invalid content: content exceeds maximum length");
}
// 安全なファイル書き出し
try (FileWriter fw = new FileWriter(normalizedPath.toString())) {
fw.write(content);
System.out.println("[Secure] File written to: " + normalizedPath);
}
}
}
なるほどです。
これを数秒でやっつけてくれて、git commitまで一連でやってくれると楽ですね。
