(configPath: string)
| 176 | } |
| 177 | |
| 178 | export const parseConfig = async (configPath: string): Promise<Config> => { |
| 179 | try { |
| 180 | // 1. Verify file exists |
| 181 | if (!(await fs.pathExists(configPath))) { |
| 182 | throw new PentestError( |
| 183 | `Configuration file not found: ${configPath}`, |
| 184 | 'config', |
| 185 | false, |
| 186 | { configPath }, |
| 187 | ErrorCode.CONFIG_NOT_FOUND, |
| 188 | ); |
| 189 | } |
| 190 | |
| 191 | // 2. Check file size |
| 192 | const stats = await fs.stat(configPath); |
| 193 | const maxFileSize = 1024 * 1024; // 1MB |
| 194 | if (stats.size > maxFileSize) { |
| 195 | throw new PentestError( |
| 196 | `Configuration file too large: ${stats.size} bytes (maximum: ${maxFileSize} bytes)`, |
| 197 | 'config', |
| 198 | false, |
| 199 | { configPath, fileSize: stats.size, maxFileSize }, |
| 200 | ErrorCode.CONFIG_VALIDATION_FAILED, |
| 201 | ); |
| 202 | } |
| 203 | |
| 204 | // 3. Read and check for empty content |
| 205 | const configContent = await fs.readFile(configPath, 'utf8'); |
| 206 | |
| 207 | if (!configContent.trim()) { |
| 208 | throw new PentestError( |
| 209 | 'Configuration file is empty', |
| 210 | 'config', |
| 211 | false, |
| 212 | { configPath }, |
| 213 | ErrorCode.CONFIG_VALIDATION_FAILED, |
| 214 | ); |
| 215 | } |
| 216 | |
| 217 | // 4. Parse YAML with safe schema |
| 218 | let config: unknown; |
| 219 | try { |
| 220 | config = yaml.load(configContent, { |
| 221 | schema: yaml.FAILSAFE_SCHEMA, // Only basic YAML types, no JS evaluation |
| 222 | json: false, // Don't allow JSON-specific syntax |
| 223 | filename: configPath, |
| 224 | }); |
| 225 | } catch (yamlError) { |
| 226 | const errMsg = yamlError instanceof Error ? yamlError.message : String(yamlError); |
| 227 | throw new PentestError( |
| 228 | `YAML parsing failed: ${errMsg}`, |
| 229 | 'config', |
| 230 | false, |
| 231 | { configPath, originalError: errMsg }, |
| 232 | ErrorCode.CONFIG_PARSE_ERROR, |
| 233 | ); |
| 234 | } |
| 235 |
no test coverage detected