環境
ESLint v8.41.0
問題発生の経緯
フラグ名が適正かどうかを判定するために hasOwnProperty を使用したところ、ESLintに怒られてしましました。
該当するコードは以下の通りです。
function setFlag(flagName) {
if (!flags.hasOwnProperty(flagName)) {
console.log(`ERROR:_${flagName} is not a valid flag`);
throw new Error(`Invalid flag name:_${flagName}`);
}
if (flags[flagName]) {
console.log(`FLAG:_${flagName} is already set`);
return;
}
flags[flagName] = true;
console.log(`FLAG:_${flagName} is set`);
}
「no-prototype-builtins」で怒られたようです。
以下に詳しく書かれています。
詳細を追ってみます。
エラー抜粋
一部の Object.prototype メソッドをオブジェクト上で直接呼び出すことを禁止します
オブジェクトには、Object.prototype の組み込みをシャドウイングするプロパティが含まれる可能性があり、意図しない動作やサービス拒否のセキュリティ脆弱性を引き起こす可能性があります。
たとえば、Web サーバーがクライアントからの JSON 入力を解析し、結果のオブジェクトに対して hasOwnProperty を直接呼び出すことは安全ではありません。
悪意のあるクライアントが {"hasOwnProperty": 1} のような JSON 値を送信し、サーバーをクラッシュさせる可能性があるためです。
要するに、直接hasOwnPropertyを呼び出す方法では、悪意のあるユーザーによって不正な値が混入される危険性があると言っています。
意図しない動作やサービス拒否のセキュリティの脆弱性を引き起こす可能性があり、最悪の場合はWebサーバーがクラッシュする可能性があります。
このような不正データが入り込む系のリスクはSQLインジェクションの概念とちょっぴり似ているような気がします。
正しい使い方
ESLintのドキュメンテーションのRule Detailsに使い方が記載されていました。
/*eslint no-prototype-builtins: "error"*/
var hasBarProperty = foo.hasOwnProperty("bar");
var isPrototypeOfBar = foo.isPrototypeOf(bar);
var barIsEnumerable = foo.propertyIsEnumerable("bar");
/*eslint no-prototype-builtins: "error"*/
var hasBarProperty = Object.prototype.hasOwnProperty.call(foo, "bar");
var isPrototypeOfBar = Object.prototype.isPrototypeOf.call(foo, bar);
var barIsEnumerable = {}.propertyIsEnumerable.call(foo, "bar");
なるほど、これが正しい使い方ですか。
対処法
以下のようにコードを修正することで、ESLintに怒られなくなりました。
function setFlag(flagName) {
if (!Object.prototype.hasOwnProperty.call(flags, flagName)) {
console.log(`ERROR:_${flagName} is not a valid flag`);
throw new Error(`Invalid flag name:_${flagName}`);
}
if (flags[flagName]) {
console.log(`FLAG:_${flagName} is already set`);
return;
}
flags[flagName] = true;
console.log(`FLAG:_${flagName} is set`);
}
これで、ESLintのルールに沿ったセキュアなコードになりました。
まとめ
ESLintの警告でリスクを事前に知り、リスク回避することができました。
不正データの混入によるセキュリティ上のリスクを回避するためには、
- そもそも不適切な値が混入する余地のない実装をする
- 適切な入力検証を実施する
- データのサニタイズ処理を実施する
など、不正なデータの混入を防止する対策が必要です。
信頼できないデータを排除し、システムの安全性を確保しましょう。
以上です