# セキュリティ設計書

## 概要

本ドキュメントは、Lua Language Server（lua-language-server）のセキュリティ設計について記載する。本プロジェクトはLanguage Server Protocol（LSP）を実装した言語サーバーであり、IDE/エディタと連携してLuaコードの解析・補完・診断等の機能を提供する。Webアプリケーションとは異なり、ローカル環境で動作するデスクトップ向けツールであるため、セキュリティ設計は主にプラグイン実行時の信頼性確保、ワークスペースアクセス制御、ファイル操作の安全性に焦点を当てる。

## 認証設計

### 認証方式

本プロジェクトはユーザー認証機能を持たない。LSPプロトコルに基づき、クライアント（IDE/エディタ）との通信はローカルのstdin/stdout経由で行われ、ネットワーク経由の認証は不要である。

### セッション管理

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| セッション有効期限 | N/A | ローカルプロセスのため該当なし |
| セッション固定化対策 | N/A | セッション管理不要 |

## 認可設計

### 権限体系

本プロジェクトは多段階の権限体系を持たないが、以下の信頼レベルに基づくアクセス制御が存在する。

| ロール | 権限 | 説明 |
| --- | --- | --- |
| 信頼済みプラグイン | コード実行 | ユーザーが明示的に信頼したプラグインのみ実行可能 |
| 未信頼プラグイン | 実行拒否 | 信頼確認ダイアログで承認されるまで実行されない |
| クライアント信頼委譲 | クライアント側判断 | VSCodeのワークスペース信頼機能等に委譲可能 |

### アクセス制御

#### プラグイン信頼制御

プラグインの読み込み時に以下の信頼確認メカニズムが実装されている（`script/plugin.lua`）:

1. **`TRUST_ALL_PLUGINS`フラグ**: CI環境等でのバッチ処理用に全プラグインを信頼するフラグ（通常使用では非推奨）
2. **信頼済みリスト**: `$LOGPATH/trusted`ファイルに信頼済みプラグインパスを保存
3. **対話的確認**: 未登録プラグインは`PLUGIN_TRUST_LOAD`ダイアログでユーザー確認を要求
4. **クライアント委譲**: `trustByClient`オプションにより、VSCode等のワークスペース信頼機能に委譲可能

```lua
-- script/plugin.lua:65-91
local function checkTrustLoad(scp)
    if TRUST_ALL_PLUGINS then
        return true
    end
    local pluginPath = scp:get('pluginPath')
    local filePath = LOGPATH .. '/trusted'
    local trusted = util.loadFile(filePath)
    -- 信頼済みリストとの照合
    ...
    -- 対話的確認
    local _, index = client.awaitRequestMessage('Warning', ...)
end
```

#### ワークスペースアクセス制御

危険なワークスペース（ルートディレクトリやHOMEディレクトリ）の使用を制限（`script/workspace/workspace.lua`）:

```lua
-- script/workspace/workspace.lua:51-57
if uri == furi.encode '/'
or uri == furi.encode(os.getenv 'HOME' or '') then
    if not FORCE_ACCEPT_WORKSPACE then
        client.showMessage('Error', lang.script('WORKSPACE_NOT_ALLOWED', ...))
        scp:set('bad root', true)
    end
end
```

## 通信セキュリティ

| 項目 | 対策 |
| --- | --- |
| HTTPS | N/A（ローカルstdin/stdout通信のため不要） |
| HSTS | N/A |
| 通信暗号化 | N/A（プロセス間通信はOSレベルで保護） |

本プロジェクトはLSPプロトコルに基づき、stdin/stdoutを通じてクライアントと通信する。ネットワーク通信を行わないため、TLS/SSLによる暗号化は適用対象外である。

## データセキュリティ

### 暗号化

| 対象 | 暗号化方式 |
| --- | --- |
| 通信 | N/A（ローカル通信） |
| 保存データ | N/A（暗号化対象データなし） |

### 機密情報管理

本プロジェクトは以下の機密情報を取り扱わない:
- パスワード・認証トークン
- 個人情報
- 暗号鍵

**テレメトリについて**: v3.6.5以前はオプトイン方式のテレメトリ機能が存在したが、現在は完全に削除されている（README.md:81）。

## 入出力対策

| 脅威 | 対策 |
| --- | --- |
| XSS | N/A（Webアプリケーションではないため該当なし） |
| SQLインジェクション | N/A（データベースを使用しない） |
| CSRF | N/A（Webアプリケーションではないため該当なし） |
| パストラバーサル | ファイルURI正規化による対策 |
| コードインジェクション | プラグイン信頼制御・サンドボックス化 |

### パストラバーサル対策

ファイルURIの正規化処理により、不正なパス操作を防止（`script/file-uri.lua`）:

```lua
-- script/file-uri.lua
function m.encode(path)
    -- パスの正規化
    path = path:gsub('\\', '/')
    -- URIエンコーディング
    ...
end

function m.decode(uri)
    -- URI → パス変換時の正規化
    path = normalize(path)
    ...
end
```

### コードインジェクション対策

プラグイン実行時の保護（`script/plugin.lua`）:

1. **サンドボックス環境**: プラグインは独立した環境で実行（`setmetatable({}, { __index = _ENV })`）
2. **xpcall による保護**: プラグイン実行はxpcallでラップし、エラーを捕捉
3. **信頼確認**: 実行前にユーザー確認を必須化

```lua
-- script/plugin.lua:147-157
local interface = setmetatable({}, { __index = _ENV })
local f, err = load(pluginLua, '@' .. pluginPath, "t", interface)
if not f then
    -- エラーハンドリング
end
if not client.getOption('trustByClient') and not checkTrustLoad(scp) then
    return  -- 信頼確認なしでは実行しない
end
local suc, err = xpcall(f, log.error, f, uri, myArgs)
```

### 設定ファイル読み込み

設定ファイル（`.luarc.json`, `.luarc.jsonc`）の読み込み時のエラーハンドリング（`script/config/loader.lua`）:

```lua
-- script/config/loader.lua:33-40
local suc, res = pcall(jsonc.decode_jsonc, buf)
if not suc then
    errorMessage(lang.script('CONFIG_LOAD_ERROR', res))
    return scp:get('lastRCConfig')
end
```

## 監査ログ

| ログ種別 | 記録内容 | 保持期間 |
| --- | --- | --- |
| アプリケーションログ | 起動・終了・エラー・警告・デバッグ情報 | セッション中（最大100MB） |
| プラグインエラーログ | プラグイン実行時のエラー | アプリケーションログに含む |
| 設定読み込みログ | 設定ファイルの読み込み状況 | アプリケーションログに含む |

### ログ実装詳細

`script/log.lua`で実装されたロギング機能:

- **ログレベル**: trace, debug, info, warn, error
- **最大サイズ**: 100MB（超過時は書き込み停止）
- **出力先**: `$LOGPATH/{workspace}.log`
- **エラー時スタックトレース**: errorレベルでは自動的にスタックトレースを記録

```lua
-- script/log.lua:20-28
m.maxSize = 100 * 1024 * 1024
m.level = 'info'
m.levelMap = {
    ['trace'] = 1,
    ['debug'] = 2,
    ['info']  = 3,
    ['warn']  = 4,
    ['error'] = 5,
}
```

## 備考

### セキュリティ関連CLI引数

| 引数 | 説明 | 用途 |
| --- | --- | --- |
| `--trust_all_plugins` | 全プラグインを信頼 | CI環境専用（通常使用は非推奨） |
| `--force_accept_workspace` | ワークスペース制限を無効化 | 特殊用途のみ |

### VSCodeワークスペース信頼機能との連携

v3.2.0以降、VSCodeのワークスペース信頼機能（Workspace Trust）と連携可能。VSCode側でワークスペースが信頼されている場合、プラグインの個別確認をスキップできる（`trustByClient`オプション）。

### セキュリティ改善履歴

| バージョン | 変更内容 |
| --- | --- |
| v3.6.5 | テレメトリ機能を完全削除 |
| v3.2.0 | VSCodeワークスペース信頼機能との連携 |
| v2.x | プラグインのデフォルトパスをセキュリティ上の理由で空文字に変更 |
