分123hrefプロパティに相対URLを設定したときに,href以外の各プロパティが正しく取得できない問題を解決する<a>要素は,絶対URLを指すhrefプロパティだけでなく,locationオブジェクトやURLオブジェクトと同様に,protocolやhost,hostnameといった,URLの部分文字列を指すプロパティもサポートしています。これらのプロパティを用いて,URLをパースして各部分を取り出すことを考えてみましょう。IEにて,以下のコードのように新たに生成した<a>要素のhrefプロパティにURLを代入し,protocolやhost,hostnameなどのプロパティを読みだしてみます。"example.jp"想定したとおりに正しく動いているように見えるかもしれません。じつはIEでは,hrefプロパティに相対URLを設定したときに,href以外の各プロパティが正しく取得できないという問題があります。"example.jp"そこで,IEで<a>要素などを用いてURLを取り扱うという場合には,相対URLをいったん絶対URLに変換する必要があります。相対URLを絶対URLに変換するコードは,先ほどのものがそのまま利用できます。表示される相対URLを絶対URLに変換する際に,ベースとなるURLを明示的に指定できない問題を解決するさらに,<a>要素を用いて相対URLを絶対URLに変換する際には,常に現在のURL(location.href)を起点として変換されてしまい,ベースとなるURLを明示的に指定できないという問題もあります。これを解決するためには,以下のような方法を採ります。IE11ではDOMParserを,IE10ではdocument.implementation.createHTMLDocumentを用い,現在表示されているコンテンツとは切り離されたDOMツリーを作成するそのDOMツリーに<base>要素を追加し,ベースURLを指定するそのDOMツリー内で前述の<a>要素を使った方法を用いて相対URLを絶対URLに変換する具体的なコードは以下のようになります。"?bar"このcreateUrlという関数は,これまで説明したとおりURLコンストラクタが利用可能な場合にはそれを利用し,利用できない場合には<a>要素を使いつつ,相対URLの場合にはDOMParserまたはcreateHTMLDocumentを用いて絶対URLに変換します。戻り値として,locationやURLオブジェクトと同様に,URLをパースした結果を各プロパティにセットしたオブジェクトを生成して返します。先に説明したように,URLにBasic認証のユーザー名やパスワードが含まれている場合にはセキュリティ上の問題を引き起こすことがあるので,ユーザー名やパスワードが含まれるURLの場合には例外を発生するようになっています。まとめ今回は,URLを文字列として自前でパースするのではなく,ブラウザの機能を利用してパースする方法を解説しました。このような方法をとることで,少ないコードで,実際のブラウザが解釈するとおりのURLのパース結果を得ることができます。繰り返しになりますが,JavaScriptのコード上において,URLを基準としてセキュリティ上の判断を行う場面は,開発者が意図していない場合も含めると,比較的頻繁に発生します。いった場面で,URLを文字列として取り扱い,自身でURLをパースするコードを書くことは,多くの場合に脆弱性を発生させる原因になります。理由がない限り,URLをパースするには,自身でコードを書くのではなく,ブラウザの機能を用いるようにしましょう。今回説明したようなURLのパース時の問題以外にも,JavaScript上のコードからURLを操作する際にlocationオブジェクトなどを通じてセキュリティ上の問題が発生することがよくあります。locationオブジェクトの操作に起因する脆弱性としてよく見かけるのは以下のようなものです。"xss"といったスクリプトのスキームを代入されることによりXSSが発生するHTML内にlocation.hrefやlocation.hashを表示する際に,URL内に含まれる「<」「⁠>」などがエスケープされていないことが原因でXSSが発生するこのような脆弱性の具体例や対策の詳細についても,今後回を追って取り上げたいと思います。オリジン著者プロフィールはせがわようすけ株式会社セキュアスカイ・テクノロジー常勤技術顧問。FirefoxをはじめWebアプリケーションに関する多数の脆弱性を発見。