// @bun
import {
  ProgressTracker,
  formatProgress,
  init_ProgressTracker
} from "./chunk-psc8avjs.js";
import {
  getProjectRoot,
  init_state
} from "./chunk-3j8w0rq8.js";
import"./chunk-tj0dzck2.js";
import"./chunk-nxzx0ey9.js";
import"./chunk-yes1my80.js";
import {
  __esm
} from "./chunk-hhsxm2yr.js";

// src/services/security/scanner.ts
import { readdir, readFile, stat } from "fs/promises";
import { join, relative, extname } from "path";
async function walkDir(dir, files = []) {
  const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
  for (const entry of entries) {
    if (SKIP_DIRS.has(entry.name))
      continue;
    if (files.length >= MAX_FILES)
      break;
    const fullPath = join(dir, entry.name);
    if (entry.isDirectory()) {
      await walkDir(fullPath, files);
    } else {
      const ext = extname(entry.name);
      if (SCAN_EXTENSIONS.has(ext) || entry.name === "Dockerfile" || entry.name === ".env") {
        const s = await stat(fullPath).catch(() => null);
        if (s && s.size <= MAX_FILE_SIZE)
          files.push(fullPath);
      }
    }
  }
  return files;
}
async function scanDirectory(dir, onProgress) {
  const root = dir || getProjectRoot();
  const files = await walkDir(root);
  const findings = [];
  for (let fileIndex = 0;fileIndex < files.length; fileIndex++) {
    const filePath = files[fileIndex];
    const relPath = relative(root, filePath);
    if (onProgress) {
      onProgress(fileIndex + 1, files.length, relPath);
    }
    const content = await readFile(filePath, "utf-8").catch(() => null);
    if (!content)
      continue;
    const lines = content.split(`
`);
    for (const rule of RULES) {
      if (rule.fileFilter && !rule.fileFilter.test(filePath))
        continue;
      for (let i = 0;i < lines.length; i++) {
        const line = lines[i];
        rule.pattern.lastIndex = 0;
        const match = rule.pattern.exec(line);
        if (match) {
          findings.push({
            file: relPath,
            line: i + 1,
            severity: rule.severity,
            rule: rule.id,
            message: rule.message,
            snippet: line.trim().slice(0, 120)
          });
        }
      }
    }
  }
  return findings.sort((a, b) => {
    const order = {
      critical: 0,
      high: 1,
      medium: 2,
      low: 3,
      info: 4
    };
    return order[a.severity] - order[b.severity];
  });
}
function formatFindings(findings) {
  if (findings.length === 0)
    return "\u2705 No security issues found!";
  const counts = {};
  for (const f of findings) {
    counts[f.severity] = (counts[f.severity] || 0) + 1;
  }
  const icons = {
    critical: "\uD83D\uDD34",
    high: "\uD83D\uDFE0",
    medium: "\uD83D\uDFE1",
    low: "\uD83D\uDD35",
    info: "\u26AA"
  };
  const lines = [
    "# Security Audit Report",
    "",
    `Found **${findings.length}** issues:`,
    "",
    ...Object.entries(counts).map(([sev, cnt]) => `- ${icons[sev]} ${sev}: ${cnt}`),
    "",
    "## Findings",
    ""
  ];
  for (const f of findings) {
    lines.push(`### ${icons[f.severity]} [${f.rule}] ${f.message}`);
    lines.push(`- **File:** \`${f.file}:${f.line}\``);
    lines.push(`- **Code:** \`${f.snippet}\``);
    lines.push("");
  }
  return lines.join(`
`);
}
var RULES, SKIP_DIRS, SCAN_EXTENSIONS, MAX_FILE_SIZE = 500000, MAX_FILES = 500;
var init_scanner = __esm(() => {
  init_state();
  RULES = [
    {
      id: "SECRET-KEY",
      pattern: /(?:api[_-]?key|secret|password|token|auth)\s*[:=]\s*['"][A-Za-z0-9_-]{16,}['"]/gi,
      severity: "critical",
      message: "Possible hardcoded secret or API key"
    },
    {
      id: "PRIVATE-KEY",
      pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----/g,
      severity: "critical",
      message: "Private key found in source code"
    },
    {
      id: "AWS-KEY",
      pattern: /AKIA[0-9A-Z]{16}/g,
      severity: "critical",
      message: "AWS access key detected"
    },
    {
      id: "SQL-INJECT",
      pattern: /(?:query|execute|raw)\s*\(\s*`[^`]*\$\{/g,
      severity: "high",
      message: "Possible SQL injection via template literal",
      fileFilter: /\.(ts|js)$/
    },
    {
      id: "EVAL",
      pattern: /\beval\s*\(/g,
      severity: "high",
      message: "eval() usage \u2014 potential code injection"
    },
    {
      id: "EXEC-SYNC",
      pattern: /execSync\s*\(/g,
      severity: "medium",
      message: "execSync usage \u2014 consider input validation"
    },
    {
      id: "CHILD-EXEC",
      pattern: /exec\s*\(\s*`/g,
      severity: "high",
      message: "Shell command with template literal \u2014 injection risk"
    },
    {
      id: "INNER-HTML",
      pattern: /\.innerHTML\s*=/g,
      severity: "high",
      message: "Direct innerHTML assignment \u2014 XSS risk",
      fileFilter: /\.(ts|tsx|js|jsx)$/
    },
    {
      id: "DANGEROUSLY-SET",
      pattern: /dangerouslySetInnerHTML/g,
      severity: "medium",
      message: "dangerouslySetInnerHTML usage \u2014 ensure sanitization"
    },
    {
      id: "WEAK-CRYPTO",
      pattern: /\b(?:md5|sha1)\b/gi,
      severity: "medium",
      message: "Weak cryptographic algorithm",
      fileFilter: /\.(ts|js)$/
    },
    {
      id: "MATH-RANDOM",
      pattern: /Math\.random\(\)/g,
      severity: "low",
      message: "Math.random() is not cryptographically secure"
    },
    {
      id: "PATH-TRAVERSAL",
      pattern: /(?:readFile|writeFile|createReadStream)\s*\([^)]*\.\.\//g,
      severity: "high",
      message: "Possible path traversal vulnerability"
    },
    {
      id: "JSON-PARSE-UNTRUSTED",
      pattern: /JSON\.parse\s*\(\s*(?:req\.|params\.|query\.|body\.)/g,
      severity: "medium",
      message: "JSON.parse on untrusted input without validation"
    },
    {
      id: "CONSOLE-LOG",
      pattern: /console\.(log|debug|info)\s*\(/g,
      severity: "info",
      message: "Console output \u2014 remove for production",
      fileFilter: /\.(ts|js)$/
    },
    {
      id: "TODO-FIXME",
      pattern: /(?:TODO|FIXME|HACK|XXX)\b/g,
      severity: "info",
      message: "Unresolved TODO/FIXME comment"
    }
  ];
  SKIP_DIRS = new Set([
    "node_modules",
    ".git",
    "dist",
    "build",
    ".next",
    "coverage",
    "__pycache__"
  ]);
  SCAN_EXTENSIONS = new Set([
    ".ts",
    ".tsx",
    ".js",
    ".jsx",
    ".py",
    ".rb",
    ".go",
    ".rs",
    ".java",
    ".php",
    ".env",
    ".json",
    ".yaml",
    ".yml",
    ".toml"
  ]);
});

// src/commands/audit/audit.ts
var call = async (args, context) => {
  const dir = args?.trim() || undefined;
  const progress = new ProgressTracker;
  progress.addStep("scan", "\u626B\u63CF\u6587\u4EF6");
  progress.addStep("analyze", "\u5206\u6790\u5B89\u5168\u95EE\u9898");
  progress.addStep("report", "\u751F\u6210\u62A5\u544A");
  try {
    progress.startStep("scan", "\u6B63\u5728\u626B\u63CF\u4EE3\u7801\u6587\u4EF6...");
    const findings = await scanDirectory(dir, (scanned, total, current) => {
      const percentage = Math.round(scanned / total * 100);
      progress.updateStep("scan", percentage, `\u626B\u63CF\u4E2D: ${current} (${scanned}/${total})`);
    });
    progress.completeStep("scan", `\u626B\u63CF\u5B8C\u6210\uFF0C\u68C0\u67E5\u4E86 ${findings.length} \u4E2A\u95EE\u9898`);
    progress.startStep("analyze", "\u5206\u6790\u53D1\u73B0\u7684\u95EE\u9898...");
    await new Promise((resolve) => setTimeout(resolve, 100));
    progress.completeStep("analyze", `\u5206\u6790\u5B8C\u6210`);
    progress.startStep("report", "\u751F\u6210\u62A5\u544A...");
    const report = formatFindings(findings);
    progress.completeStep("report", "\u62A5\u544A\u751F\u6210\u5B8C\u6210");
    const progressSummary = formatProgress(progress);
    let result = `${progressSummary}

${report}`;
    if (findings.some((f) => f.fix)) {
      result += `

\uD83D\uDCA1 \u63D0\u793A\uFF1A\u53D1\u73B0\u53EF\u81EA\u52A8\u4FEE\u590D\u7684\u95EE\u9898\uFF0C\u8FD0\u884C /audit --fix \u81EA\u52A8\u4FEE\u590D`;
    }
    if (findings.length > 10) {
      result += `
\uD83D\uDCA1 \u63D0\u793A\uFF1A\u95EE\u9898\u8F83\u591A\uFF0C\u53EF\u4EE5\u751F\u6210 HTML \u62A5\u544A\uFF1A/audit --report audit-report.html`;
    }
    const lowSeverity = findings.filter((f) => (f.level || f.severity) === "low").length;
    if (lowSeverity > findings.length * 0.6) {
      result += `
\uD83D\uDCA1 \u63D0\u793A\uFF1A\u5927\u90E8\u5206\u662F\u4F4E\u5371\u95EE\u9898\uFF0C\u53EF\u4EE5\u53EA\u663E\u793A\u9AD8\u5371\uFF1A/audit --severity high`;
    }
    return { type: "text", value: result };
  } catch (e) {
    return { type: "text", value: `\u2717 Audit failed: ${String(e)}` };
  }
};
var init_audit = __esm(() => {
  init_scanner();
  init_ProgressTracker();
});
init_audit();

export {
  call
};

//# debugId=A8491B821597E5DF64756E2164756E21
//# sourceMappingURL=chunk-e1drxpzc.js.map
