graphql-sentinel 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +530 -0
- package/dist/cli.cjs +1834 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1811 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +1822 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +176 -0
- package/dist/index.d.ts +176 -0
- package/dist/index.js +1768 -0
- package/dist/index.js.map +1 -0
- package/package.json +95 -0
package/dist/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/cli/scan.ts","../src/scanner/checks/introspection.ts","../src/scanner/checks/depth-limit.ts","../src/scanner/checks/batch-attack.ts","../src/scanner/checks/field-suggestion.ts","../src/scanner/checks/alias-overloading.ts","../src/scanner/checks/csrf.ts","../src/scanner/checks/auth-bypass.ts","../src/scanner/checks/index.ts","../src/scanner/runner.ts","../src/reporter/json.ts","../src/reporter/terminal.ts","../src/reporter/html.ts","../src/reporter/sarif.ts","../src/reporter/dashboard.ts","../src/reporter/index.ts","../src/cli/proxy.ts","../src/proxy/server.ts","../src/shield/depth-limiter.ts","../src/shield/complexity-analyzer.ts","../src/shield/alias-limiter.ts","../src/shield/introspection-control.ts","../src/shield/rate-limiter.ts","../src/shield/field-auth.ts","../src/shield/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { createScanCommand } from './cli/scan.js';\nimport { createProxyCommand } from './cli/proxy.js';\n\nconst program = new Command()\n .name('graphql-sentinel')\n .description('GraphQL security scanner and runtime shield')\n .version(process.env.PACKAGE_VERSION || '0.1.0');\n\nprogram.addCommand(createScanCommand());\nprogram.addCommand(createProxyCommand());\n\nprogram.parse();\n","import { Command } from 'commander';\nimport { runScan } from '../scanner/runner.js';\nimport { generateReport, type ReportFormat } from '../reporter/index.js';\nimport fs from 'node:fs';\n\nexport function createScanCommand(): Command {\n return new Command('scan')\n .description('Scan a GraphQL endpoint for security vulnerabilities')\n .argument('<url>', 'GraphQL endpoint URL to scan')\n .option('-f, --format <format>', 'Output format (terminal, json, html)', 'terminal')\n .option('-o, --output <file>', 'Write report to file instead of stdout')\n .option(\n '-H, --header <header...>',\n 'Custom headers (format: \"Key: Value\")',\n )\n .option('-c, --checks <checks>', 'Comma-separated list of checks to run')\n .option('-t, --timeout <ms>', 'Timeout per check in milliseconds', '10000')\n .action(async (url: string, options: {\n format: string;\n output?: string;\n header?: string[];\n checks?: string;\n timeout: string;\n }) => {\n const headers: Record<string, string> = {};\n if (options.header) {\n for (const h of options.header) {\n const colonIdx = h.indexOf(':');\n if (colonIdx > 0) {\n const key = h.substring(0, colonIdx).trim();\n const value = h.substring(colonIdx + 1).trim();\n headers[key] = value;\n }\n }\n }\n\n const checks = options.checks ? options.checks.split(',').map((c) => c.trim()) : undefined;\n const format = options.format as ReportFormat;\n\n if (!['terminal', 'json', 'html', 'sarif', 'dashboard'].includes(format)) {\n console.error(`Invalid format \"${format}\". Use: terminal, json, html, sarif, dashboard`);\n process.exit(1);\n }\n\n if (format === 'terminal') {\n console.log(`\\nScanning ${url}...\\n`);\n }\n\n try {\n const report = await runScan({\n endpoint: url,\n headers: Object.keys(headers).length > 0 ? headers : undefined,\n checks,\n timeout: parseInt(options.timeout, 10),\n });\n\n const output = generateReport(report, format);\n\n if (options.output) {\n fs.writeFileSync(options.output, output, 'utf-8');\n console.log(`Report written to ${options.output}`);\n } else {\n console.log(output);\n }\n\n // Exit with code 1 if any critical or high severity failures\n const hasCriticalFailures = report.results.some(\n (r) => !r.passed && (r.severity === 'critical' || r.severity === 'high'),\n );\n\n if (hasCriticalFailures) {\n process.exit(1);\n }\n } catch (error) {\n console.error(`Scan failed: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(2);\n }\n });\n}\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nexport const introspectionCheck: SecurityCheck = {\n name: 'introspection',\n severity: 'medium',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n const query = '{ __schema { types { name } } }';\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ query }),\n });\n\n \n const body: any = await response.json();\n const hasSchema = body?.data?.__schema?.types?.length > 0;\n\n return {\n check: 'introspection',\n severity: 'medium',\n passed: !hasSchema,\n title: 'Introspection Enabled',\n description: hasSchema\n ? 'GraphQL introspection is enabled, exposing the full API schema to attackers.'\n : 'GraphQL introspection is properly disabled.',\n remediation: 'Disable introspection in production to prevent schema exposure.',\n details: {\n introspectionEnabled: hasSchema,\n typesFound: hasSchema ? body.data.__schema.types.length : 0,\n },\n };\n } catch (error) {\n return {\n check: 'introspection',\n severity: 'medium',\n passed: true,\n title: 'Introspection Enabled',\n description: 'Could not perform introspection query (likely disabled or endpoint unreachable).',\n remediation: 'Disable introspection in production to prevent schema exposure.',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nexport const depthLimitCheck: SecurityCheck = {\n name: 'depth-limit',\n severity: 'high',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n // Build a deeply nested query using __type introspection which naturally allows nesting\n const depth = 20;\n let current = '__typename';\n for (let i = depth; i >= 0; i--) {\n current = `d${i}: __type(name: \"Query\") { ${current} }`;\n }\n const query = `{ ${current} }`;\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ query }),\n });\n\n \n const body: any = await response.json();\n const hasErrors = body?.errors?.length > 0;\n const depthError = body?.errors?.some(\n (e: { message: string }) =>\n e.message.toLowerCase().includes('depth') ||\n e.message.toLowerCase().includes('too complex') ||\n e.message.toLowerCase().includes('max') ||\n e.message.toLowerCase().includes('limit'),\n );\n\n // If there are depth-related errors, the server has protection\n if (depthError) {\n return {\n check: 'depth-limit',\n severity: 'high',\n passed: true,\n title: 'No Query Depth Limit',\n description: 'Server properly enforces query depth limits.',\n remediation: 'Enforce query depth limits to prevent deeply nested query attacks.',\n details: { depthTested: depth, blocked: true },\n };\n }\n\n // If no errors at all, server accepted deep query\n const noDepthLimit = !hasErrors || !depthError;\n\n return {\n check: 'depth-limit',\n severity: 'high',\n passed: !noDepthLimit,\n title: 'No Query Depth Limit',\n description: noDepthLimit\n ? 'Server does not enforce query depth limits, enabling denial-of-service via deeply nested queries.'\n : 'Server properly enforces query depth limits.',\n remediation: 'Enforce query depth limits to prevent deeply nested query attacks.',\n details: { depthTested: depth, blocked: !noDepthLimit },\n };\n } catch (error) {\n return {\n check: 'depth-limit',\n severity: 'high',\n passed: true,\n title: 'No Query Depth Limit',\n description: 'Could not test query depth (endpoint unreachable or request failed).',\n remediation: 'Enforce query depth limits to prevent deeply nested query attacks.',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nexport const batchAttackCheck: SecurityCheck = {\n name: 'batch-attack',\n severity: 'medium',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n const singleQuery = { query: '{ __typename }' };\n const batchPayload = Array.from({ length: 10 }, () => ({ ...singleQuery }));\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify(batchPayload),\n });\n\n \n const body: any = await response.json();\n const isBatchResponse = Array.isArray(body) && body.length === 10;\n\n return {\n check: 'batch-attack',\n severity: 'medium',\n passed: !isBatchResponse,\n title: 'Batch Queries Allowed',\n description: isBatchResponse\n ? 'Server accepts batched queries, enabling amplification attacks.'\n : 'Server does not accept batched queries.',\n remediation:\n 'Disable or limit batch query support to prevent query amplification attacks.',\n details: {\n batchSize: 10,\n batchAccepted: isBatchResponse,\n responseType: Array.isArray(body) ? 'array' : typeof body,\n },\n };\n } catch (error) {\n return {\n check: 'batch-attack',\n severity: 'medium',\n passed: true,\n title: 'Batch Queries Allowed',\n description: 'Could not test batch queries (endpoint unreachable or request failed).',\n remediation:\n 'Disable or limit batch query support to prevent query amplification attacks.',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nexport const fieldSuggestionCheck: SecurityCheck = {\n name: 'field-suggestion',\n severity: 'low',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n const query = '{ __schemax }';\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ query }),\n });\n\n \n const body: any = await response.json();\n const errorMessages = (body?.errors || [])\n .map((e: { message: string }) => e.message)\n .join(' ');\n const hasSuggestions =\n errorMessages.toLowerCase().includes('did you mean') ||\n errorMessages.toLowerCase().includes('do you mean');\n\n return {\n check: 'field-suggestion',\n severity: 'low',\n passed: !hasSuggestions,\n title: 'Field Suggestions Exposed',\n description: hasSuggestions\n ? 'Server exposes field suggestions in error messages, aiding schema discovery.'\n : 'Server does not expose field suggestions in error messages.',\n remediation:\n 'Disable field suggestions in production to prevent schema enumeration via error messages.',\n details: {\n suggestionsExposed: hasSuggestions,\n errorMessages: errorMessages.substring(0, 500),\n },\n };\n } catch (error) {\n return {\n check: 'field-suggestion',\n severity: 'low',\n passed: true,\n title: 'Field Suggestions Exposed',\n description: 'Could not test field suggestions (endpoint unreachable or request failed).',\n remediation:\n 'Disable field suggestions in production to prevent schema enumeration via error messages.',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nexport const aliasOverloadingCheck: SecurityCheck = {\n name: 'alias-overloading',\n severity: 'medium',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n const aliasCount = 100;\n const aliases = Array.from({ length: aliasCount }, (_, i) => `a${i}: __typename`).join(' ');\n const query = `{ ${aliases} }`;\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ query }),\n });\n\n \n const body: any = await response.json();\n const hasData = body?.data !== undefined && body?.data !== null;\n const aliasKeys = hasData ? Object.keys(body.data) : [];\n const allAliasesResolved = aliasKeys.length >= aliasCount;\n\n // Check if server returned errors related to aliases\n const hasAliasError = body?.errors?.some(\n (e: { message: string }) =>\n e.message.toLowerCase().includes('alias') ||\n e.message.toLowerCase().includes('too many') ||\n e.message.toLowerCase().includes('limit'),\n );\n\n const passed = hasAliasError || !allAliasesResolved;\n\n return {\n check: 'alias-overloading',\n severity: 'medium',\n passed,\n title: 'Alias Overloading Possible',\n description: passed\n ? 'Server properly limits the number of aliases in a query.'\n : `Server accepted ${aliasCount} aliases without restriction, enabling alias-based DoS attacks.`,\n remediation:\n 'Implement alias limits to prevent denial-of-service via alias overloading.',\n details: {\n aliasesTested: aliasCount,\n aliasesAccepted: aliasKeys.length,\n blocked: passed,\n },\n };\n } catch (error) {\n return {\n check: 'alias-overloading',\n severity: 'medium',\n passed: true,\n title: 'Alias Overloading Possible',\n description:\n 'Could not test alias overloading (endpoint unreachable or request failed).',\n remediation:\n 'Implement alias limits to prevent denial-of-service via alias overloading.',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nexport const csrfCheck: SecurityCheck = {\n name: 'csrf',\n severity: 'high',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n // Test if the server accepts queries via GET request (CSRF risk for mutations)\n const query = encodeURIComponent('{ __typename }');\n const url = `${endpoint}?query=${query}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n ...headers,\n },\n });\n\n \n const body: any = await response.json();\n const hasData = body?.data?.__typename !== undefined;\n\n return {\n check: 'csrf',\n severity: 'high',\n passed: !hasData,\n title: 'GET Mutations Allowed (CSRF Risk)',\n description: hasData\n ? 'Server accepts GraphQL queries via GET requests, which can be exploited for CSRF attacks on mutations.'\n : 'Server does not accept GraphQL queries via GET requests.',\n remediation:\n 'Disable GET method for GraphQL queries, or at minimum restrict GET to only allow queries (not mutations).',\n details: {\n getRequestAccepted: hasData,\n statusCode: response.status,\n },\n };\n } catch (error) {\n return {\n check: 'csrf',\n severity: 'high',\n passed: true,\n title: 'GET Mutations Allowed (CSRF Risk)',\n description:\n 'Could not test CSRF via GET request (endpoint unreachable or request failed).',\n remediation:\n 'Disable GET method for GraphQL queries, or at minimum restrict GET to only allow queries (not mutations).',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck, ScanResult } from '../../types/index.js';\n\nconst INTROSPECTION_QUERY = `{\n __schema {\n queryType { name }\n types {\n name\n kind\n fields {\n name\n type { name kind ofType { name kind } }\n }\n }\n }\n}`;\n\nfunction findFirstQueryField(schemaData: Record<string, unknown>): string | null {\n \n const types = (schemaData as any)?.__schema?.types;\n if (!Array.isArray(types)) return null;\n\n \n const queryTypeName = (schemaData as any)?.__schema?.queryType?.name || 'Query';\n \n const queryType = types.find((t: any) => t.name === queryTypeName);\n if (!queryType?.fields || !Array.isArray(queryType.fields)) return null;\n\n // Find a field that returns a scalar or simple type (not introspection)\n \n for (const field of queryType.fields as any[]) {\n if (field.name.startsWith('__')) continue;\n return field.name;\n }\n\n return null;\n}\n\nasync function sendQuery(\n endpoint: string,\n query: string,\n headers?: Record<string, string>,\n): Promise<{ status: number; body: Record<string, unknown> | null }> {\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: JSON.stringify({ query }),\n });\n\n \n const body: any = await response.json();\n return { status: response.status, body };\n } catch {\n return { status: 0, body: null };\n }\n}\n\nfunction isAuthError(body: Record<string, unknown> | null, status: number): boolean {\n if (status === 401 || status === 403) return true;\n if (!body) return false;\n\n \n const errors = (body as any)?.errors;\n if (!Array.isArray(errors)) return false;\n\n return errors.some((e: { message: string; extensions?: { code?: string } }) => {\n const msg = (e.message || '').toLowerCase();\n const code = (e.extensions?.code || '').toLowerCase();\n return (\n msg.includes('unauthorized') ||\n msg.includes('unauthenticated') ||\n msg.includes('not authenticated') ||\n msg.includes('authentication required') ||\n msg.includes('access denied') ||\n msg.includes('forbidden') ||\n msg.includes('must be logged in') ||\n msg.includes('not allowed') ||\n code.includes('unauthenticated') ||\n code.includes('unauthorized') ||\n code.includes('forbidden')\n );\n });\n}\n\nfunction hasData(body: Record<string, unknown> | null): boolean {\n if (!body) return false;\n \n const data = (body as any)?.data;\n if (data === null || data === undefined) return false;\n // Check if data has any non-null values\n if (typeof data === 'object') {\n return Object.values(data).some((v) => v !== null);\n }\n return true;\n}\n\nexport const authBypassCheck: SecurityCheck = {\n name: 'auth-bypass',\n severity: 'high',\n\n async run(endpoint: string, headers?: Record<string, string>): Promise<ScanResult> {\n try {\n // Step 1: Try introspection to find query fields\n const introResult = await sendQuery(endpoint, INTROSPECTION_QUERY, headers);\n let testField: string | null = null;\n if (introResult.body && hasData(introResult.body)) {\n \n testField = findFirstQueryField((introResult.body as any).data);\n }\n\n // Use a discovered field or fall back to __typename\n const testQuery = testField ? `{ ${testField} }` : '{ __typename }';\n\n // Step 2: Send request WITHOUT any auth headers\n const noAuthResult = await sendQuery(endpoint, testQuery);\n const noAuthBlocked = isAuthError(noAuthResult.body, noAuthResult.status);\n const noAuthHasData = hasData(noAuthResult.body);\n\n // Step 3: Send request with empty Authorization header\n const emptyAuthResult = await sendQuery(endpoint, testQuery, {\n Authorization: '',\n });\n const emptyAuthBlocked = isAuthError(emptyAuthResult.body, emptyAuthResult.status);\n const emptyAuthHasData = hasData(emptyAuthResult.body);\n\n // Step 4: Send request with invalid Bearer token\n const invalidTokenResult = await sendQuery(endpoint, testQuery, {\n Authorization: 'Bearer invalid_token_sentinel_test',\n });\n const invalidTokenBlocked = isAuthError(invalidTokenResult.body, invalidTokenResult.status);\n const invalidTokenHasData = hasData(invalidTokenResult.body);\n\n // Step 5: If auth headers were provided, compare with authenticated response\n if (headers && (headers['Authorization'] || headers['authorization'])) {\n await sendQuery(endpoint, testQuery, headers);\n }\n\n // Analysis\n const allBlocked = noAuthBlocked && emptyAuthBlocked && invalidTokenBlocked;\n const anyDataLeaked = noAuthHasData || emptyAuthHasData || invalidTokenHasData;\n\n // If no auth headers provided and data returned, it could be a public API\n const isPublicApi = !headers && noAuthHasData && !noAuthBlocked;\n\n if (isPublicApi && !headers) {\n return {\n check: 'auth-bypass',\n severity: 'info',\n passed: true,\n title: 'Authorization Bypass Detection',\n description:\n 'API appears to be publicly accessible without authentication. Verify this is intentional.',\n remediation:\n 'If this API should require authentication, implement proper auth middleware.',\n details: {\n publicApi: true,\n noAuthBlocked,\n emptyAuthBlocked,\n invalidTokenBlocked,\n testQuery,\n },\n };\n }\n\n if (allBlocked) {\n return {\n check: 'auth-bypass',\n severity: 'high',\n passed: true,\n title: 'Authorization Bypass Detection',\n description:\n 'All unauthorized requests were properly rejected. Authorization checks appear to be in place.',\n remediation:\n 'Continue enforcing authorization checks on all fields and mutations.',\n details: {\n noAuthBlocked,\n emptyAuthBlocked,\n invalidTokenBlocked,\n testQuery,\n },\n };\n }\n\n if (anyDataLeaked) {\n const bypasses: string[] = [];\n if (noAuthHasData) bypasses.push('no-auth-header');\n if (emptyAuthHasData) bypasses.push('empty-auth-header');\n if (invalidTokenHasData) bypasses.push('invalid-bearer-token');\n\n return {\n check: 'auth-bypass',\n severity: 'high',\n passed: false,\n title: 'Authorization Bypass Detection',\n description: `Data was returned without valid authorization via: ${bypasses.join(', ')}. The API may have missing or improperly configured authorization.`,\n remediation:\n 'Ensure all queries require proper authentication. Validate authorization tokens on every request and verify field-level authorization is enforced.',\n details: {\n noAuthBlocked,\n noAuthHasData,\n emptyAuthBlocked,\n emptyAuthHasData,\n invalidTokenBlocked,\n invalidTokenHasData,\n bypasses,\n testQuery,\n },\n };\n }\n\n return {\n check: 'auth-bypass',\n severity: 'high',\n passed: true,\n title: 'Authorization Bypass Detection',\n description:\n 'Unauthorized requests did not return data. Authorization appears to be configured.',\n remediation:\n 'Continue enforcing authorization checks on all fields and mutations.',\n details: {\n noAuthBlocked,\n emptyAuthBlocked,\n invalidTokenBlocked,\n testQuery,\n },\n };\n } catch (error) {\n return {\n check: 'auth-bypass',\n severity: 'high',\n passed: true,\n title: 'Authorization Bypass Detection',\n description:\n 'Could not perform authorization bypass check (endpoint unreachable or request failed).',\n remediation:\n 'Ensure all queries require proper authentication and retry the scan.',\n details: { error: String(error) },\n };\n }\n },\n};\n","import type { SecurityCheck } from '../../types/index.js';\nimport { introspectionCheck } from './introspection.js';\nimport { depthLimitCheck } from './depth-limit.js';\nimport { batchAttackCheck } from './batch-attack.js';\nimport { fieldSuggestionCheck } from './field-suggestion.js';\nimport { aliasOverloadingCheck } from './alias-overloading.js';\nimport { csrfCheck } from './csrf.js';\nimport { authBypassCheck } from './auth-bypass.js';\n\nexport const allChecks: SecurityCheck[] = [\n introspectionCheck,\n depthLimitCheck,\n batchAttackCheck,\n fieldSuggestionCheck,\n aliasOverloadingCheck,\n csrfCheck,\n authBypassCheck,\n];\n\nexport function getChecks(names?: string[]): SecurityCheck[] {\n if (!names || names.length === 0) {\n return allChecks;\n }\n return allChecks.filter((check) => names.includes(check.name));\n}\n\nexport {\n introspectionCheck,\n depthLimitCheck,\n batchAttackCheck,\n fieldSuggestionCheck,\n aliasOverloadingCheck,\n csrfCheck,\n authBypassCheck,\n};\n","import type { ScannerConfig, ScanReport, ScanResult, Severity } from '../types/index.js';\nimport { getChecks } from './checks/index.js';\n\nexport async function runScan(config: ScannerConfig): Promise<ScanReport> {\n const { endpoint, headers, checks: checkNames, timeout = 10000 } = config;\n const checks = getChecks(checkNames);\n const startTime = Date.now();\n\n const results: ScanResult[] = await Promise.all(\n checks.map(async (check) => {\n try {\n const result = await Promise.race<ScanResult>([\n check.run(endpoint, headers),\n new Promise<ScanResult>((_, reject) =>\n setTimeout(() => reject(new Error(`Check '${check.name}' timed out`)), timeout),\n ),\n ]);\n return result;\n } catch (error) {\n return {\n check: check.name,\n severity: check.severity,\n passed: true,\n title: `Check ${check.name}`,\n description: `Check failed to execute: ${String(error)}`,\n remediation: 'Retry the scan or check endpoint availability.',\n details: { error: String(error) },\n };\n }\n }),\n );\n\n const duration = Date.now() - startTime;\n\n const bySeverity: Record<Severity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n const failed = results.filter((r) => !r.passed);\n for (const result of failed) {\n bySeverity[result.severity]++;\n }\n\n return {\n target: endpoint,\n timestamp: new Date().toISOString(),\n duration,\n results,\n summary: {\n total: results.length,\n passed: results.filter((r) => r.passed).length,\n failed: failed.length,\n bySeverity,\n },\n };\n}\n","import type { ScanReport } from '../types/index.js';\n\nexport function generateJsonReport(report: ScanReport): string {\n return JSON.stringify(report, null, 2);\n}\n","import type { ScanReport, ScanResult, Severity } from '../types/index.js';\n\nconst COLORS = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n bgRed: '\\x1b[41m',\n bgGreen: '\\x1b[42m',\n bgYellow: '\\x1b[43m',\n bgBlue: '\\x1b[44m',\n bgMagenta: '\\x1b[45m',\n};\n\nfunction severityColor(severity: Severity): string {\n switch (severity) {\n case 'critical':\n return COLORS.bgRed + COLORS.white;\n case 'high':\n return COLORS.red;\n case 'medium':\n return COLORS.yellow;\n case 'low':\n return COLORS.blue;\n case 'info':\n return COLORS.dim;\n }\n}\n\nfunction severityBadge(severity: Severity): string {\n const color = severityColor(severity);\n return `${color}[${severity.toUpperCase()}]${COLORS.reset}`;\n}\n\nfunction statusIcon(passed: boolean): string {\n return passed ? `${COLORS.green}PASS${COLORS.reset}` : `${COLORS.red}FAIL${COLORS.reset}`;\n}\n\nfunction formatResult(result: ScanResult): string {\n const lines: string[] = [];\n lines.push(\n ` ${statusIcon(result.passed)} ${severityBadge(result.severity)} ${COLORS.bold}${result.title}${COLORS.reset}`,\n );\n lines.push(` ${COLORS.dim}${result.description}${COLORS.reset}`);\n if (!result.passed) {\n lines.push(` ${COLORS.cyan}Remediation: ${result.remediation}${COLORS.reset}`);\n }\n return lines.join('\\n');\n}\n\nexport function generateTerminalReport(report: ScanReport): string {\n const lines: string[] = [];\n\n // Header\n lines.push('');\n lines.push(\n `${COLORS.bold}${COLORS.magenta}=== GraphQL Sentinel Security Scan ===${COLORS.reset}`,\n );\n lines.push(`${COLORS.dim}Target: ${report.target}${COLORS.reset}`);\n lines.push(`${COLORS.dim}Timestamp: ${report.timestamp}${COLORS.reset}`);\n lines.push(`${COLORS.dim}Duration: ${report.duration}ms${COLORS.reset}`);\n lines.push('');\n\n // Results\n lines.push(`${COLORS.bold}Results:${COLORS.reset}`);\n lines.push('');\n\n for (const result of report.results) {\n lines.push(formatResult(result));\n lines.push('');\n }\n\n // Summary\n lines.push(`${COLORS.bold}${COLORS.magenta}--- Summary ---${COLORS.reset}`);\n lines.push(` Total checks: ${report.summary.total}`);\n lines.push(` ${COLORS.green}Passed: ${report.summary.passed}${COLORS.reset}`);\n lines.push(` ${COLORS.red}Failed: ${report.summary.failed}${COLORS.reset}`);\n\n if (report.summary.failed > 0) {\n lines.push('');\n lines.push(` ${COLORS.bold}Failures by severity:${COLORS.reset}`);\n for (const [severity, count] of Object.entries(report.summary.bySeverity)) {\n if (count > 0) {\n lines.push(` ${severityBadge(severity as Severity)} ${count}`);\n }\n }\n }\n\n lines.push('');\n\n return lines.join('\\n');\n}\n","import type { ScanReport, ScanResult, Severity } from '../types/index.js';\n\nfunction severityColor(severity: Severity): string {\n switch (severity) {\n case 'critical':\n return '#dc2626';\n case 'high':\n return '#ea580c';\n case 'medium':\n return '#ca8a04';\n case 'low':\n return '#2563eb';\n case 'info':\n return '#6b7280';\n }\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction renderResult(result: ScanResult, index: number): string {\n const color = severityColor(result.severity);\n const statusClass = result.passed ? 'pass' : 'fail';\n\n return `\n <div class=\"result ${statusClass}\">\n <div class=\"result-header\" onclick=\"toggleDetails('details-${index}')\">\n <span class=\"status-icon\">${result.passed ? '✔' : '✘'}</span>\n <span class=\"severity-badge\" style=\"background-color: ${color}\">${result.severity.toUpperCase()}</span>\n <span class=\"result-title\">${escapeHtml(result.title)}</span>\n </div>\n <div class=\"result-body\">\n <p class=\"description\">${escapeHtml(result.description)}</p>\n ${\n !result.passed\n ? `<details id=\"details-${index}\">\n <summary>Remediation</summary>\n <p class=\"remediation\">${escapeHtml(result.remediation)}</p>\n </details>`\n : ''\n }\n </div>\n </div>`;\n}\n\nexport function generateHtmlReport(report: ScanReport): string {\n const results = report.results.map((r, i) => renderResult(r, i)).join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>GraphQL Sentinel Security Report</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 2rem; }\n .container { max-width: 800px; margin: 0 auto; }\n h1 { color: #a78bfa; margin-bottom: 0.5rem; font-size: 1.5rem; }\n .meta { color: #94a3b8; font-size: 0.875rem; margin-bottom: 2rem; }\n .meta span { margin-right: 1.5rem; }\n .result { background: #1e293b; border-radius: 8px; margin-bottom: 0.75rem; border-left: 4px solid #475569; overflow: hidden; }\n .result.fail { border-left-color: #ef4444; }\n .result.pass { border-left-color: #22c55e; }\n .result-header { display: flex; align-items: center; padding: 0.75rem 1rem; cursor: pointer; gap: 0.75rem; }\n .result-header:hover { background: #334155; }\n .status-icon { font-size: 1.1rem; min-width: 1.5rem; text-align: center; }\n .pass .status-icon { color: #22c55e; }\n .fail .status-icon { color: #ef4444; }\n .severity-badge { color: white; padding: 0.15rem 0.5rem; border-radius: 4px; font-size: 0.7rem; font-weight: 600; text-transform: uppercase; }\n .result-title { font-weight: 600; }\n .result-body { padding: 0 1rem 0.75rem 3.25rem; }\n .description { color: #94a3b8; font-size: 0.875rem; margin-bottom: 0.5rem; }\n details { margin-top: 0.5rem; }\n summary { color: #60a5fa; cursor: pointer; font-size: 0.875rem; }\n summary:hover { color: #93c5fd; }\n .remediation { color: #86efac; font-size: 0.875rem; margin-top: 0.5rem; padding: 0.5rem; background: #1a2e1a; border-radius: 4px; }\n .summary-box { background: #1e293b; border-radius: 8px; padding: 1.5rem; margin-top: 1.5rem; }\n .summary-box h2 { color: #a78bfa; margin-bottom: 1rem; font-size: 1.1rem; }\n .summary-stats { display: flex; gap: 2rem; flex-wrap: wrap; }\n .stat { text-align: center; }\n .stat-value { font-size: 1.5rem; font-weight: 700; }\n .stat-label { font-size: 0.75rem; color: #94a3b8; }\n .stat-pass .stat-value { color: #22c55e; }\n .stat-fail .stat-value { color: #ef4444; }\n .severity-counts { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem; }\n .severity-count { padding: 0.25rem 0.75rem; border-radius: 4px; font-size: 0.8rem; color: white; }\n footer { text-align: center; color: #64748b; margin-top: 2rem; font-size: 0.75rem; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <h1>GraphQL Sentinel Security Report</h1>\n <div class=\"meta\">\n <span>Target: ${escapeHtml(report.target)}</span>\n <span>Date: ${escapeHtml(report.timestamp)}</span>\n <span>Duration: ${report.duration}ms</span>\n </div>\n\n ${results}\n\n <div class=\"summary-box\">\n <h2>Summary</h2>\n <div class=\"summary-stats\">\n <div class=\"stat\">\n <div class=\"stat-value\">${report.summary.total}</div>\n <div class=\"stat-label\">Total Checks</div>\n </div>\n <div class=\"stat stat-pass\">\n <div class=\"stat-value\">${report.summary.passed}</div>\n <div class=\"stat-label\">Passed</div>\n </div>\n <div class=\"stat stat-fail\">\n <div class=\"stat-value\">${report.summary.failed}</div>\n <div class=\"stat-label\">Failed</div>\n </div>\n </div>\n ${\n report.summary.failed > 0\n ? `<div class=\"severity-counts\">\n ${Object.entries(report.summary.bySeverity)\n .filter(([_, count]) => count > 0)\n .map(\n ([severity, count]) =>\n `<span class=\"severity-count\" style=\"background-color: ${severityColor(severity as Severity)}\">${severity}: ${count}</span>`,\n )\n .join('\\n ')}\n </div>`\n : ''\n }\n </div>\n\n <footer>Generated by GraphQL Sentinel v0.1.0</footer>\n </div>\n <script>\n function toggleDetails(id) {\n const el = document.getElementById(id);\n if (el) { el.open = !el.open; }\n }\n </script>\n</body>\n</html>`;\n}\n","import type { ScanReport, Severity } from '../types/index.js';\n\nfunction mapSeverityToSarif(severity: Severity): 'error' | 'warning' | 'note' {\n switch (severity) {\n case 'critical':\n case 'high':\n return 'error';\n case 'medium':\n return 'warning';\n case 'low':\n case 'info':\n return 'note';\n }\n}\n\nexport function generateSarifReport(report: ScanReport): string {\n const sarif = {\n version: '2.1.0' as const,\n $schema:\n 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',\n runs: [\n {\n tool: {\n driver: {\n name: 'graphql-sentinel',\n version: '0.1.0',\n informationUri: 'https://github.com/mstuart/graphql-sentinel',\n rules: report.results.map((r) => ({\n id: r.check,\n name: r.title,\n shortDescription: { text: r.title },\n fullDescription: { text: r.description },\n helpUri: 'https://github.com/mstuart/graphql-sentinel',\n defaultConfiguration: {\n level: mapSeverityToSarif(r.severity),\n },\n properties: {\n tags: ['security', 'graphql'],\n },\n })),\n },\n },\n results: report.results\n .filter((r) => !r.passed)\n .map((r) => ({\n ruleId: r.check,\n level: mapSeverityToSarif(r.severity),\n message: { text: `${r.title}: ${r.description}` },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: report.target },\n },\n },\n ],\n ...(r.remediation\n ? {\n fixes: [\n {\n description: { text: r.remediation },\n },\n ],\n }\n : {}),\n })),\n },\n ],\n };\n\n return JSON.stringify(sarif, null, 2);\n}\n","import type { ScanReport, ScanResult, Severity } from '../types/index.js';\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nconst SEVERITY_WEIGHTS: Record<Severity, number> = {\n critical: 25,\n high: 20,\n medium: 10,\n low: 5,\n info: 1,\n};\n\nconst SEVERITY_COLORS: Record<Severity, string> = {\n critical: '#dc2626',\n high: '#ea580c',\n medium: '#ca8a04',\n low: '#2563eb',\n info: '#6b7280',\n};\n\nconst CATEGORY_MAP: Record<string, string> = {\n introspection: 'Information Disclosure',\n 'field-suggestion': 'Information Disclosure',\n 'depth-limit': 'Denial of Service',\n 'batch-attack': 'Denial of Service',\n 'alias-overloading': 'Denial of Service',\n csrf: 'Authorization',\n 'auth-bypass': 'Authorization',\n};\n\nexport function calculatePostureScore(results: ScanResult[]): number {\n if (results.length === 0) return 100;\n\n let totalWeight = 0;\n let failedWeight = 0;\n\n for (const result of results) {\n const weight = SEVERITY_WEIGHTS[result.severity];\n totalWeight += weight;\n if (!result.passed) {\n failedWeight += weight;\n }\n }\n\n if (totalWeight === 0) return 100;\n const score = Math.round(((totalWeight - failedWeight) / totalWeight) * 100);\n return Math.max(0, Math.min(100, score));\n}\n\nfunction getScoreColor(score: number): string {\n if (score >= 80) return '#22c55e';\n if (score >= 60) return '#ca8a04';\n if (score >= 40) return '#ea580c';\n return '#dc2626';\n}\n\nfunction getScoreLabel(score: number): string {\n if (score >= 90) return 'Excellent';\n if (score >= 80) return 'Good';\n if (score >= 60) return 'Fair';\n if (score >= 40) return 'Poor';\n return 'Critical';\n}\n\nfunction generateExecutiveSummary(report: ScanReport, score: number): string {\n const { summary } = report;\n const criticalHigh =\n (summary.bySeverity.critical || 0) + (summary.bySeverity.high || 0);\n\n if (score >= 90) {\n return `The GraphQL endpoint at ${escapeHtml(report.target)} demonstrates strong security posture with a score of ${score}/100. All ${summary.total} security checks were evaluated, with ${summary.passed} passing. No critical remediation is required at this time.`;\n }\n if (score >= 60) {\n return `The GraphQL endpoint at ${escapeHtml(report.target)} has a moderate security posture with a score of ${score}/100. Out of ${summary.total} checks, ${summary.failed} issues were identified. ${criticalHigh > 0 ? `${criticalHigh} high-severity issue(s) require immediate attention.` : 'Issues found are of moderate severity and should be addressed in the near term.'}`;\n }\n return `The GraphQL endpoint at ${escapeHtml(report.target)} requires immediate security attention with a score of ${score}/100. ${summary.failed} out of ${summary.total} checks failed, including ${criticalHigh} high or critical severity issue(s). Immediate remediation is strongly recommended to protect against known attack vectors.`;\n}\n\nfunction generateCategoryBreakdown(results: ScanResult[]): Record<string, ScanResult[]> {\n const categories: Record<string, ScanResult[]> = {};\n for (const result of results) {\n const category = CATEGORY_MAP[result.check] || 'Other';\n if (!categories[category]) {\n categories[category] = [];\n }\n categories[category].push(result);\n }\n return categories;\n}\n\nfunction generateTimelineSvg(reports: ScanReport[]): string {\n if (reports.length < 2) return '';\n\n const width = 600;\n const height = 200;\n const padding = 40;\n const chartWidth = width - padding * 2;\n const chartHeight = height - padding * 2;\n\n const scores = reports.map((r) => calculatePostureScore(r.results));\n const maxScore = 100;\n const minScore = 0;\n\n const points = scores.map((score, i) => {\n const x = padding + (i / (scores.length - 1)) * chartWidth;\n const y = padding + chartHeight - ((score - minScore) / (maxScore - minScore)) * chartHeight;\n return { x, y, score };\n });\n\n const pathData = points\n .map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`)\n .join(' ');\n\n const labels = reports.map((r, i) => {\n const x = padding + (i / (reports.length - 1)) * chartWidth;\n const date = new Date(r.timestamp);\n const label = `${date.getMonth() + 1}/${date.getDate()}`;\n return `<text x=\"${x}\" y=\"${height - 5}\" text-anchor=\"middle\" fill=\"#94a3b8\" font-size=\"10\">${label}</text>`;\n });\n\n const dots = points.map(\n (p) =>\n `<circle cx=\"${p.x}\" cy=\"${p.y}\" r=\"4\" fill=\"${getScoreColor(p.score)}\" />\n <text x=\"${p.x}\" y=\"${p.y - 10}\" text-anchor=\"middle\" fill=\"#e2e8f0\" font-size=\"11\">${p.score}</text>`,\n );\n\n // Grid lines\n const gridLines = [0, 25, 50, 75, 100].map((v) => {\n const y = padding + chartHeight - (v / 100) * chartHeight;\n return `<line x1=\"${padding}\" y1=\"${y}\" x2=\"${width - padding}\" y2=\"${y}\" stroke=\"#334155\" stroke-width=\"0.5\" />\n <text x=\"${padding - 5}\" y=\"${y + 4}\" text-anchor=\"end\" fill=\"#64748b\" font-size=\"10\">${v}</text>`;\n });\n\n return `\n <svg viewBox=\"0 0 ${width} ${height}\" xmlns=\"http://www.w3.org/2000/svg\" style=\"width:100%;max-width:${width}px;height:auto;\">\n <rect width=\"${width}\" height=\"${height}\" fill=\"#0f172a\" rx=\"8\" />\n ${gridLines.join('\\n')}\n <path d=\"${pathData}\" fill=\"none\" stroke=\"#a78bfa\" stroke-width=\"2\" />\n ${dots.join('\\n')}\n ${labels.join('\\n')}\n </svg>`;\n}\n\nfunction renderCheckDetail(result: ScanResult, index: number): string {\n const color = SEVERITY_COLORS[result.severity];\n const statusClass = result.passed ? 'pass' : 'fail';\n const category = CATEGORY_MAP[result.check] || 'Other';\n\n return `\n <div class=\"check-card ${statusClass}\">\n <div class=\"check-header\" onclick=\"toggleCheck(${index})\">\n <span class=\"check-status\">${result.passed ? '✔' : '✘'}</span>\n <span class=\"sev-badge\" style=\"background:${color}\">${result.severity.toUpperCase()}</span>\n <span class=\"check-name\">${escapeHtml(result.title)}</span>\n <span class=\"check-category\">${escapeHtml(category)}</span>\n <span class=\"check-chevron\" id=\"chevron-${index}\">▶</span>\n </div>\n <div class=\"check-details\" id=\"check-${index}\" style=\"display:none;\">\n <p class=\"check-desc\">${escapeHtml(result.description)}</p>\n ${!result.passed ? `<div class=\"remediation-box\"><strong>Remediation:</strong> ${escapeHtml(result.remediation)}</div>` : ''}\n </div>\n </div>`;\n}\n\nexport function generateDashboard(\n reports: ScanReport[],\n config?: { title?: string },\n): string {\n if (reports.length === 0) {\n return '<html><body>No reports provided</body></html>';\n }\n\n const latestReport = reports[reports.length - 1];\n const score = calculatePostureScore(latestReport.results);\n const scoreColor = getScoreColor(score);\n const scoreLabel = getScoreLabel(score);\n const executiveSummary = generateExecutiveSummary(latestReport, score);\n const categories = generateCategoryBreakdown(latestReport.results);\n const timelineSvg = generateTimelineSvg(reports);\n const title = config?.title || 'GraphQL Sentinel Security Dashboard';\n\n const checkCards = latestReport.results\n .map((r, i) => renderCheckDetail(r, i))\n .join('\\n');\n\n const categoryCards = Object.entries(categories)\n .map(([cat, results]) => {\n const catPassed = results.filter((r) => r.passed).length;\n const catFailed = results.filter((r) => !r.passed).length;\n const catColor = catFailed > 0 ? '#ef4444' : '#22c55e';\n return `\n <div class=\"cat-card\">\n <div class=\"cat-header\">\n <span class=\"cat-icon\" style=\"color:${catColor}\">${catFailed > 0 ? '⚠' : '✔'}</span>\n <span class=\"cat-name\">${escapeHtml(cat)}</span>\n </div>\n <div class=\"cat-stats\">\n <span class=\"cat-passed\">${catPassed} passed</span>\n <span class=\"cat-failed\">${catFailed} failed</span>\n </div>\n </div>`;\n })\n .join('\\n');\n\n const severityCounts = Object.entries(latestReport.summary.bySeverity)\n .filter(([_, count]) => count > 0)\n .map(\n ([sev, count]) =>\n `<span class=\"sev-count\" style=\"background:${SEVERITY_COLORS[sev as Severity]}\">${sev}: ${count}</span>`,\n )\n .join('\\n');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${escapeHtml(title)}</title>\n <style>\n *{margin:0;padding:0;box-sizing:border-box}\n body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0f172a;color:#e2e8f0;padding:1.5rem;min-height:100vh}\n .dashboard{max-width:1000px;margin:0 auto}\n h1{color:#a78bfa;font-size:1.4rem;margin-bottom:.25rem}\n .subtitle{color:#64748b;font-size:.8rem;margin-bottom:1.5rem}\n .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1rem;margin-bottom:1.5rem}\n .card{background:#1e293b;border-radius:8px;padding:1.25rem}\n .score-card{text-align:center;position:relative}\n .score-ring{position:relative;width:120px;height:120px;margin:0 auto .75rem}\n .score-ring svg{transform:rotate(-90deg)}\n .score-value{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:2rem;font-weight:700}\n .score-label{font-size:.85rem;color:#94a3b8;margin-bottom:.5rem}\n .summary-card p{color:#94a3b8;font-size:.85rem;line-height:1.6}\n .stats-row{display:flex;gap:1.5rem;flex-wrap:wrap;margin-top:1rem}\n .stat{text-align:center}\n .stat-val{font-size:1.3rem;font-weight:700}\n .stat-lbl{font-size:.7rem;color:#94a3b8;text-transform:uppercase;letter-spacing:.5px}\n .stat-pass .stat-val{color:#22c55e}\n .stat-fail .stat-val{color:#ef4444}\n .severity-row{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.75rem}\n .sev-count{padding:.15rem .6rem;border-radius:4px;font-size:.7rem;color:#fff;font-weight:600;text-transform:uppercase}\n .section-title{color:#a78bfa;font-size:1rem;font-weight:600;margin-bottom:.75rem;padding-bottom:.5rem;border-bottom:1px solid #334155}\n .timeline-card{margin-bottom:1.5rem}\n .cat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:.75rem;margin-bottom:1.5rem}\n .cat-card{background:#1e293b;border-radius:8px;padding:1rem}\n .cat-header{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}\n .cat-icon{font-size:1.1rem}\n .cat-name{font-weight:600;font-size:.85rem}\n .cat-stats{display:flex;gap:1rem;font-size:.75rem}\n .cat-passed{color:#22c55e}\n .cat-failed{color:#ef4444}\n .checks-section{margin-bottom:1.5rem}\n .check-card{background:#1e293b;border-radius:8px;margin-bottom:.5rem;overflow:hidden;border-left:4px solid #475569}\n .check-card.fail{border-left-color:#ef4444}\n .check-card.pass{border-left-color:#22c55e}\n .check-header{display:flex;align-items:center;padding:.75rem 1rem;cursor:pointer;gap:.75rem;user-select:none}\n .check-header:hover{background:#334155}\n .check-status{font-size:1rem;min-width:1.25rem;text-align:center}\n .pass .check-status{color:#22c55e}\n .fail .check-status{color:#ef4444}\n .sev-badge{color:#fff;padding:.1rem .45rem;border-radius:3px;font-size:.65rem;font-weight:600;text-transform:uppercase}\n .check-name{font-weight:600;font-size:.85rem;flex:1}\n .check-category{font-size:.7rem;color:#64748b;background:#0f172a;padding:.15rem .5rem;border-radius:3px}\n .check-chevron{color:#64748b;font-size:.7rem;transition:transform .2s}\n .check-chevron.open{transform:rotate(90deg)}\n .check-details{padding:.75rem 1rem .75rem 3.5rem;border-top:1px solid #334155}\n .check-desc{color:#94a3b8;font-size:.8rem;line-height:1.5;margin-bottom:.5rem}\n .remediation-box{background:#1a2e1a;color:#86efac;font-size:.8rem;padding:.5rem .75rem;border-radius:4px;line-height:1.5}\n footer{text-align:center;color:#475569;font-size:.7rem;margin-top:2rem;padding-top:1rem;border-top:1px solid #1e293b}\n </style>\n</head>\n<body>\n <div class=\"dashboard\">\n <h1>${escapeHtml(title)}</h1>\n <div class=\"subtitle\">Target: ${escapeHtml(latestReport.target)} | ${escapeHtml(latestReport.timestamp)} | ${latestReport.duration}ms</div>\n\n <div class=\"grid\">\n <div class=\"card score-card\">\n <div class=\"section-title\">Security Posture</div>\n <div class=\"score-ring\">\n <svg viewBox=\"0 0 120 120\">\n <circle cx=\"60\" cy=\"60\" r=\"52\" fill=\"none\" stroke=\"#334155\" stroke-width=\"8\"/>\n <circle cx=\"60\" cy=\"60\" r=\"52\" fill=\"none\" stroke=\"${scoreColor}\" stroke-width=\"8\" stroke-dasharray=\"${(score / 100) * 327} 327\" stroke-linecap=\"round\"/>\n </svg>\n <div class=\"score-value\" style=\"color:${scoreColor}\">${score}</div>\n </div>\n <div class=\"score-label\">${scoreLabel}</div>\n <div class=\"stats-row\">\n <div class=\"stat\"><div class=\"stat-val\">${latestReport.summary.total}</div><div class=\"stat-lbl\">Total</div></div>\n <div class=\"stat stat-pass\"><div class=\"stat-val\">${latestReport.summary.passed}</div><div class=\"stat-lbl\">Passed</div></div>\n <div class=\"stat stat-fail\"><div class=\"stat-val\">${latestReport.summary.failed}</div><div class=\"stat-lbl\">Failed</div></div>\n </div>\n ${severityCounts ? `<div class=\"severity-row\">${severityCounts}</div>` : ''}\n </div>\n\n <div class=\"card summary-card\">\n <div class=\"section-title\">Executive Summary</div>\n <p>${executiveSummary}</p>\n </div>\n </div>\n\n ${timelineSvg ? `\n <div class=\"card timeline-card\">\n <div class=\"section-title\">Vulnerability Timeline</div>\n ${timelineSvg}\n </div>` : ''}\n\n <div class=\"section-title\">Category Breakdown</div>\n <div class=\"cat-grid\">\n ${categoryCards}\n </div>\n\n <div class=\"checks-section\">\n <div class=\"section-title\">Check Details</div>\n ${checkCards}\n </div>\n\n <footer>Generated by GraphQL Sentinel v${process.env.PACKAGE_VERSION || '0.1.0'}</footer>\n </div>\n\n <script>\n function toggleCheck(idx){\n var el=document.getElementById('check-'+idx);\n var ch=document.getElementById('chevron-'+idx);\n if(el.style.display==='none'){el.style.display='block';ch.classList.add('open');}\n else{el.style.display='none';ch.classList.remove('open');}\n }\n\n // Persist scan results in localStorage for timeline tracking\n (function(){\n try{\n var key='graphql-sentinel-history';\n var current=${JSON.stringify({\n target: latestReport.target,\n timestamp: latestReport.timestamp,\n score: score,\n passed: latestReport.summary.passed,\n failed: latestReport.summary.failed,\n total: latestReport.summary.total,\n })};\n var history=JSON.parse(localStorage.getItem(key)||'[]');\n // Avoid duplicates by timestamp\n if(!history.some(function(h){return h.timestamp===current.timestamp;})){\n history.push(current);\n // Keep last 50 entries\n if(history.length>50)history=history.slice(-50);\n localStorage.setItem(key,JSON.stringify(history));\n }\n }catch(e){/* ignore storage errors */}\n })();\n </script>\n</body>\n</html>`;\n}\n","import type { ScanReport } from '../types/index.js';\nimport { generateJsonReport } from './json.js';\nimport { generateTerminalReport } from './terminal.js';\nimport { generateHtmlReport } from './html.js';\nimport { generateSarifReport } from './sarif.js';\nimport { generateDashboard } from './dashboard.js';\n\nexport type ReportFormat = 'json' | 'terminal' | 'html' | 'sarif' | 'dashboard';\n\nexport function generateReport(report: ScanReport, format: ReportFormat): string {\n switch (format) {\n case 'json':\n return generateJsonReport(report);\n case 'terminal':\n return generateTerminalReport(report);\n case 'html':\n return generateHtmlReport(report);\n case 'sarif':\n return generateSarifReport(report);\n case 'dashboard':\n return generateDashboard([report]);\n default:\n throw new Error(`Unknown report format: ${format}`);\n }\n}\n\nexport { generateJsonReport } from './json.js';\nexport { generateTerminalReport } from './terminal.js';\nexport { generateHtmlReport } from './html.js';\nexport { generateSarifReport } from './sarif.js';\nexport { generateDashboard } from './dashboard.js';\n","import { Command } from 'commander';\nimport { startProxy } from '../proxy/server.js';\nimport type { ShieldConfig } from '../types/index.js';\n\nexport function createProxyCommand(): Command {\n return new Command('proxy')\n .description('Start a security proxy in front of a GraphQL endpoint')\n .argument('<target>', 'Upstream GraphQL endpoint URL')\n .option('-p, --port <port>', 'Proxy listening port', '4000')\n .option('--max-depth <depth>', 'Maximum query depth')\n .option('--max-complexity <complexity>', 'Maximum query complexity')\n .option('--max-aliases <aliases>', 'Maximum number of aliases')\n .option('--disable-introspection', 'Block introspection queries')\n .option('--rate-limit-window <ms>', 'Rate limit window in milliseconds')\n .option('--rate-limit-max <max>', 'Maximum requests per window')\n .option(\n '-H, --header <header...>',\n 'Headers to forward to upstream (format: \"Key: Value\")',\n )\n .option('--no-cors', 'Disable CORS headers')\n .action(\n async (\n target: string,\n options: {\n port: string;\n maxDepth?: string;\n maxComplexity?: string;\n maxAliases?: string;\n disableIntrospection?: boolean;\n rateLimitWindow?: string;\n rateLimitMax?: string;\n header?: string[];\n cors?: boolean;\n },\n ) => {\n const shieldConfig: ShieldConfig = {};\n\n if (options.maxDepth) {\n shieldConfig.maxDepth = parseInt(options.maxDepth, 10);\n }\n if (options.maxComplexity) {\n shieldConfig.maxComplexity = parseInt(options.maxComplexity, 10);\n }\n if (options.maxAliases) {\n shieldConfig.maxAliases = parseInt(options.maxAliases, 10);\n }\n if (options.disableIntrospection) {\n shieldConfig.disableIntrospection = true;\n }\n if (options.rateLimitWindow && options.rateLimitMax) {\n shieldConfig.rateLimit = {\n window: parseInt(options.rateLimitWindow, 10),\n max: parseInt(options.rateLimitMax, 10),\n };\n }\n\n const headers: Record<string, string> = {};\n if (options.header) {\n for (const h of options.header) {\n const colonIdx = h.indexOf(':');\n if (colonIdx > 0) {\n const key = h.substring(0, colonIdx).trim();\n const value = h.substring(colonIdx + 1).trim();\n headers[key] = value;\n }\n }\n }\n\n try {\n await startProxy({\n target,\n port: parseInt(options.port, 10),\n shield: shieldConfig,\n headers: Object.keys(headers).length > 0 ? headers : undefined,\n cors: options.cors,\n });\n } catch (error) {\n console.error(\n `Failed to start proxy: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exit(1);\n }\n },\n );\n}\n","import http from 'node:http';\nimport { parse } from 'graphql';\nimport type { ShieldConfig } from '../types/index.js';\nimport { createShield } from '../shield/index.js';\n\nexport interface ProxyConfig {\n /** Upstream GraphQL endpoint URL */\n target: string;\n /** Proxy listening port (default 4000) */\n port: number;\n /** Shield configuration for query validation */\n shield: ShieldConfig;\n /** Headers to forward to the upstream */\n headers?: Record<string, string>;\n /** Enable CORS headers (default true) */\n cors?: boolean;\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => (body += chunk));\n req.on('end', () => resolve(body));\n req.on('error', reject);\n });\n}\n\nfunction setCorsHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n}\n\nexport function createProxyServer(config: ProxyConfig): http.Server {\n const shield = createShield(config.shield);\n const enableCors = config.cors !== false;\n\n const server = http.createServer(async (req, res) => {\n // Handle CORS preflight\n if (enableCors) {\n setCorsHeaders(res);\n }\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.method !== 'POST') {\n res.writeHead(405, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: [{ message: 'Only POST method is allowed' }] }));\n return;\n }\n\n try {\n const body = await readBody(req);\n let parsed: { query?: string; variables?: Record<string, unknown>; operationName?: string };\n\n try {\n parsed = JSON.parse(body);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: [{ message: 'Invalid JSON in request body' }] }));\n return;\n }\n\n if (!parsed.query || typeof parsed.query !== 'string') {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ errors: [{ message: 'Missing or invalid query field' }] }));\n return;\n }\n\n // Parse the GraphQL document\n let document;\n try {\n document = parse(parsed.query);\n } catch (parseError) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n errors: [\n {\n message: `GraphQL parse error: ${parseError instanceof Error ? parseError.message : String(parseError)}`,\n },\n ],\n }),\n );\n return;\n }\n\n // Apply shield validation rules\n // We don't have a full schema to validate against, so we validate using only\n // the custom rules that don't need schema context (depth, aliases, introspection)\n const validationErrors = validateWithRules(document, shield.validationRules);\n\n if (validationErrors.length > 0) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n errors: validationErrors.map((e) => ({\n message: e.message,\n extensions: { code: 'GRAPHQL_SENTINEL_BLOCKED' },\n })),\n }),\n );\n return;\n }\n\n // Check rate limiter\n if (shield.rateLimiter) {\n const clientIp =\n (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim() ||\n req.socket.remoteAddress ||\n 'unknown';\n const result = shield.rateLimiter.check(clientIp);\n if (!result.allowed) {\n res.writeHead(429, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n errors: [\n {\n message: 'Rate limit exceeded',\n extensions: { code: 'RATE_LIMITED', remaining: result.remaining },\n },\n ],\n }),\n );\n return;\n }\n }\n\n // Forward request to upstream\n const forwardHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...config.headers,\n };\n\n // Forward auth headers from original request\n if (req.headers['authorization']) {\n forwardHeaders['Authorization'] = req.headers['authorization'] as string;\n }\n\n const upstreamResponse = await fetch(config.target, {\n method: 'POST',\n headers: forwardHeaders,\n body: JSON.stringify({\n query: parsed.query,\n variables: parsed.variables,\n operationName: parsed.operationName,\n }),\n });\n\n const upstreamBody = await upstreamResponse.text();\n\n // Forward upstream response headers\n const contentType = upstreamResponse.headers.get('content-type');\n if (contentType) {\n res.setHeader('Content-Type', contentType);\n } else {\n res.setHeader('Content-Type', 'application/json');\n }\n\n res.writeHead(upstreamResponse.status);\n res.end(upstreamBody);\n } catch (error) {\n res.writeHead(502, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n errors: [\n {\n message: `Proxy error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n }),\n );\n }\n });\n\n return server;\n}\n\n/**\n * Validate a document using custom validation rules without requiring a schema.\n * Each rule is called with a minimal validation context.\n */\nfunction validateWithRules(\n document: ReturnType<typeof parse>,\n \n rules: Array<(context: any) => any>,\n): Array<{ message: string }> {\n const errors: Array<{ message: string }> = [];\n\n // Create a minimal context-like object that collects errors\n const mockContext = {\n reportError(error: { message: string }) {\n errors.push(error);\n },\n getSchema() {\n return {\n getQueryType() {\n return { name: 'Query' };\n },\n getMutationType() {\n return null;\n },\n getSubscriptionType() {\n return null;\n },\n };\n },\n getFieldDef() {\n return null;\n },\n };\n\n for (const rule of rules) {\n const visitor = rule(mockContext);\n visitNode(document, visitor);\n }\n\n return errors;\n}\n\n \nfunction visitNode(node: any, visitor: any): void {\n if (!node || typeof node !== 'object') return;\n\n const kind = node.kind;\n if (!kind) return;\n\n // Enter\n const kindVisitor = visitor[kind];\n if (kindVisitor) {\n if (typeof kindVisitor === 'function') {\n kindVisitor(node);\n } else if (kindVisitor.enter) {\n kindVisitor.enter(node);\n }\n }\n\n // Visit children\n for (const key of Object.keys(node)) {\n const value = node[key];\n if (Array.isArray(value)) {\n for (const child of value) {\n if (child && typeof child === 'object' && child.kind) {\n visitNode(child, visitor);\n }\n }\n } else if (value && typeof value === 'object' && value.kind) {\n visitNode(value, visitor);\n }\n }\n\n // Leave\n if (kindVisitor) {\n if (kindVisitor.leave) {\n kindVisitor.leave(node);\n }\n }\n}\n\nexport async function startProxy(config: ProxyConfig): Promise<http.Server> {\n const server = createProxyServer(config);\n return new Promise((resolve) => {\n server.listen(config.port, () => {\n console.log(`GraphQL Sentinel proxy running on port ${config.port}`);\n console.log(`Forwarding to ${config.target}`);\n resolve(server);\n });\n });\n}\n","import type { ASTVisitor, ValidationContext } from 'graphql';\nimport { GraphQLError } from 'graphql';\n\nexport function createDepthLimitRule(maxDepth: number = 10) {\n return function DepthLimitRule(context: ValidationContext): ASTVisitor {\n return {\n Document: {\n enter(node) {\n const depth = measureDepth(node);\n if (depth > maxDepth) {\n context.reportError(\n new GraphQLError(\n `Query depth of ${depth} exceeds maximum allowed depth of ${maxDepth}.`,\n ),\n );\n }\n },\n },\n };\n };\n}\n\nfunction measureDepth(node: { kind: string; selectionSet?: unknown; selections?: unknown[] } | Record<string, unknown>, currentDepth: number = 0): number {\n if (!node || typeof node !== 'object') {\n return currentDepth;\n }\n\n const selectionSet = (node as Record<string, unknown>).selectionSet as { selections?: unknown[] } | undefined;\n if (selectionSet && Array.isArray(selectionSet.selections)) {\n let maxChildDepth = currentDepth + 1;\n for (const selection of selectionSet.selections) {\n const childDepth = measureDepth(selection as Record<string, unknown>, currentDepth + 1);\n if (childDepth > maxChildDepth) {\n maxChildDepth = childDepth;\n }\n }\n return maxChildDepth;\n }\n\n // Check definitions (Document node)\n const definitions = (node as Record<string, unknown>).definitions as unknown[] | undefined;\n if (Array.isArray(definitions)) {\n let maxDefDepth = 0;\n for (const def of definitions) {\n const defDepth = measureDepth(def as Record<string, unknown>, 0);\n if (defDepth > maxDefDepth) {\n maxDefDepth = defDepth;\n }\n }\n return maxDefDepth;\n }\n\n return currentDepth;\n}\n","import type { ASTVisitor, ValidationContext } from 'graphql';\nimport { GraphQLError } from 'graphql';\n\nexport interface ComplexityConfig {\n maxComplexity?: number;\n defaultFieldCost?: number;\n listFieldMultiplier?: number;\n}\n\nexport function createComplexityRule(config: ComplexityConfig = {}) {\n const {\n maxComplexity = 1000,\n defaultFieldCost = 1,\n listFieldMultiplier = 10,\n } = config;\n\n return function ComplexityRule(context: ValidationContext): ASTVisitor {\n let complexity = 0;\n const multiplierStack: number[] = [1];\n\n return {\n Field: {\n enter(_node) {\n const currentMultiplier = multiplierStack[multiplierStack.length - 1] || 1;\n complexity += defaultFieldCost * currentMultiplier;\n\n // Check if field returns a list type\n const fieldDef = context.getFieldDef();\n if (fieldDef) {\n const type = fieldDef.type;\n const typeName = type.toString();\n if (typeName.startsWith('[')) {\n multiplierStack.push(currentMultiplier * listFieldMultiplier);\n } else {\n multiplierStack.push(currentMultiplier);\n }\n } else {\n multiplierStack.push(currentMultiplier);\n }\n },\n leave() {\n multiplierStack.pop();\n },\n },\n Document: {\n leave() {\n if (complexity > maxComplexity) {\n context.reportError(\n new GraphQLError(\n `Query complexity of ${complexity} exceeds maximum allowed complexity of ${maxComplexity}.`,\n ),\n );\n }\n },\n },\n };\n };\n}\n","import type { ASTVisitor, ValidationContext } from 'graphql';\nimport { GraphQLError } from 'graphql';\n\nexport function createAliasLimitRule(maxAliases: number = 15) {\n return function AliasLimitRule(context: ValidationContext): ASTVisitor {\n let aliasCount = 0;\n\n return {\n Field: {\n enter(node) {\n if (node.alias) {\n aliasCount++;\n }\n },\n },\n Document: {\n leave() {\n if (aliasCount > maxAliases) {\n context.reportError(\n new GraphQLError(\n `Query contains ${aliasCount} aliases, exceeding the maximum of ${maxAliases}.`,\n ),\n );\n }\n },\n },\n };\n };\n}\n","import type { ASTVisitor, ValidationContext } from 'graphql';\nimport { GraphQLError } from 'graphql';\n\nexport function createIntrospectionControlRule() {\n return function IntrospectionControlRule(context: ValidationContext): ASTVisitor {\n return {\n Field(node) {\n const fieldName = node.name.value;\n if (fieldName === '__schema' || fieldName === '__type') {\n context.reportError(\n new GraphQLError(\n `Introspection query is not allowed. Field \"${fieldName}\" is disabled.`,\n ),\n );\n }\n },\n };\n };\n}\n","export interface RateLimitConfig {\n window: number; // window in milliseconds\n max: number; // max cost allowed per window\n}\n\nexport interface RateLimitResult {\n allowed: boolean;\n remaining: number;\n}\n\ninterface ClientRecord {\n entries: { timestamp: number; cost: number }[];\n}\n\nexport function createRateLimiter(config: RateLimitConfig) {\n const { window, max } = config;\n const clients = new Map<string, ClientRecord>();\n\n // Periodic cleanup\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, record] of clients.entries()) {\n record.entries = record.entries.filter((e) => now - e.timestamp < window);\n if (record.entries.length === 0) {\n clients.delete(key);\n }\n }\n }, window);\n\n // Allow cleanup timer to not prevent process exit\n if (cleanupInterval.unref) {\n cleanupInterval.unref();\n }\n\n return {\n check(key: string, cost: number = 1): RateLimitResult {\n const now = Date.now();\n\n if (!clients.has(key)) {\n clients.set(key, { entries: [] });\n }\n\n const record = clients.get(key)!;\n\n // Remove expired entries\n record.entries = record.entries.filter((e) => now - e.timestamp < window);\n\n // Calculate current total cost\n const currentCost = record.entries.reduce((sum, e) => sum + e.cost, 0);\n\n if (currentCost + cost > max) {\n return {\n allowed: false,\n remaining: Math.max(0, max - currentCost),\n };\n }\n\n record.entries.push({ timestamp: now, cost });\n\n return {\n allowed: true,\n remaining: max - currentCost - cost,\n };\n },\n\n reset(key?: string) {\n if (key) {\n clients.delete(key);\n } else {\n clients.clear();\n }\n },\n\n destroy() {\n clearInterval(cleanupInterval);\n clients.clear();\n },\n };\n}\n","import type { ASTVisitor, ValidationContext } from 'graphql';\nimport { GraphQLError } from 'graphql';\n\nexport interface FieldAuthRule {\n requireAuth: boolean;\n roles?: string[];\n permissions?: string[];\n}\n\nexport interface FieldAuthConfig {\n /** Map of TypeName.fieldName -> required roles/permissions */\n rules: Record<string, FieldAuthRule>;\n /** Function to extract user context from the GraphQL context */\n extractContext?: (context: unknown) => {\n authenticated: boolean;\n roles: string[];\n permissions: string[];\n } | null;\n}\n\nexport function createFieldAuthRule(config: FieldAuthConfig) {\n return function FieldAuthRule(context: ValidationContext): ASTVisitor {\n const typeStack: string[] = [];\n\n return {\n OperationDefinition: {\n enter() {\n const queryType = context.getSchema().getQueryType();\n // Push root type\n typeStack.push(queryType?.name || 'Query');\n },\n leave() {\n typeStack.pop();\n },\n },\n Field: {\n enter(node) {\n const fieldName = node.name.value;\n const parentType = typeStack[typeStack.length - 1] || 'Query';\n const ruleKey = `${parentType}.${fieldName}`;\n\n const rule = config.rules[ruleKey];\n if (!rule) {\n // Also check wildcard rules: *.fieldName or TypeName.*\n const wildcardField = config.rules[`*.${fieldName}`];\n const wildcardType = config.rules[`${parentType}.*`];\n const effectiveRule = wildcardField || wildcardType;\n if (effectiveRule) {\n checkRule(effectiveRule, ruleKey, context, config);\n }\n } else {\n checkRule(rule, ruleKey, context, config);\n }\n\n // Push the type of this field for nested field resolution\n const fieldDef = context.getFieldDef();\n if (fieldDef) {\n const namedType = getNamedType(fieldDef.type);\n if (namedType && 'name' in namedType) {\n typeStack.push(namedType.name);\n }\n }\n },\n leave() {\n // Pop the type we pushed\n const fieldDef = context.getFieldDef();\n if (fieldDef) {\n const namedType = getNamedType(fieldDef.type);\n if (namedType && 'name' in namedType) {\n typeStack.pop();\n }\n }\n },\n },\n };\n };\n}\n\nfunction checkRule(\n rule: FieldAuthRule,\n ruleKey: string,\n context: ValidationContext,\n config: FieldAuthConfig,\n): void {\n // Extract user context\n const userContext = config.extractContext\n ? config.extractContext((context as unknown as { _contextValue?: unknown })._contextValue)\n : null;\n\n if (rule.requireAuth) {\n if (!userContext || !userContext.authenticated) {\n context.reportError(\n new GraphQLError(\n `Access denied: field \"${ruleKey}\" requires authentication.`,\n ),\n );\n return;\n }\n }\n\n if (rule.roles && rule.roles.length > 0) {\n if (!userContext) {\n context.reportError(\n new GraphQLError(\n `Access denied: field \"${ruleKey}\" requires one of roles: ${rule.roles.join(', ')}.`,\n ),\n );\n return;\n }\n const hasRole = rule.roles.some((r) => userContext.roles.includes(r));\n if (!hasRole) {\n context.reportError(\n new GraphQLError(\n `Access denied: field \"${ruleKey}\" requires one of roles: ${rule.roles.join(', ')}.`,\n ),\n );\n return;\n }\n }\n\n if (rule.permissions && rule.permissions.length > 0) {\n if (!userContext) {\n context.reportError(\n new GraphQLError(\n `Access denied: field \"${ruleKey}\" requires one of permissions: ${rule.permissions.join(', ')}.`,\n ),\n );\n return;\n }\n const hasPermission = rule.permissions.some((p) =>\n userContext.permissions.includes(p),\n );\n if (!hasPermission) {\n context.reportError(\n new GraphQLError(\n `Access denied: field \"${ruleKey}\" requires one of permissions: ${rule.permissions.join(', ')}.`,\n ),\n );\n return;\n }\n }\n}\n\n \nfunction getNamedType(type: any): any {\n if (!type) return null;\n if (type.ofType) return getNamedType(type.ofType);\n return type;\n}\n","import type { ShieldConfig } from '../types/index.js';\nimport { createDepthLimitRule } from './depth-limiter.js';\nimport { createComplexityRule } from './complexity-analyzer.js';\nimport { createAliasLimitRule } from './alias-limiter.js';\nimport { createIntrospectionControlRule } from './introspection-control.js';\nimport { createRateLimiter } from './rate-limiter.js';\nimport { createFieldAuthRule } from './field-auth.js';\n\ntype ValidationRule = (context: import('graphql').ValidationContext) => import('graphql').ASTVisitor;\n\nexport interface Shield {\n validationRules: ValidationRule[];\n rateLimiter?: ReturnType<typeof createRateLimiter>;\n}\n\nexport function createShield(config: ShieldConfig): Shield {\n const validationRules: ValidationRule[] = [];\n\n if (config.maxDepth !== undefined) {\n validationRules.push(createDepthLimitRule(config.maxDepth));\n }\n\n if (config.maxComplexity !== undefined) {\n validationRules.push(\n createComplexityRule({\n maxComplexity: config.maxComplexity,\n }),\n );\n }\n\n if (config.maxAliases !== undefined) {\n validationRules.push(createAliasLimitRule(config.maxAliases));\n }\n\n if (config.disableIntrospection) {\n validationRules.push(createIntrospectionControlRule());\n }\n\n if (config.fieldAuth) {\n validationRules.push(createFieldAuthRule(config.fieldAuth));\n }\n\n let rateLimiter: ReturnType<typeof createRateLimiter> | undefined;\n if (config.rateLimit) {\n rateLimiter = createRateLimiter(config.rateLimit);\n }\n\n return { validationRules, rateLimiter };\n}\n\nexport { createDepthLimitRule } from './depth-limiter.js';\nexport { createComplexityRule } from './complexity-analyzer.js';\nexport { createAliasLimitRule } from './alias-limiter.js';\nexport { createIntrospectionControlRule } from './introspection-control.js';\nexport { createRateLimiter } from './rate-limiter.js';\nexport { createFieldAuthRule } from './field-auth.js';\n"],"mappings":"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","names":["import_commander","hasData","hasData","severityColor","escapeHtml","fs","import_commander","import_graphql","import_graphql","import_graphql","import_graphql","import_graphql","http"]}
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|