argus-ci 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/.cursorrules +29 -0
- package/CLAUDE.md +39 -0
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/bin/argus-ci.js +2 -0
- package/dist/agent/index.d.ts +15 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +208 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +133 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/detector.d.ts +11 -0
- package/dist/core/detector.d.ts.map +1 -0
- package/dist/core/detector.js +69 -0
- package/dist/core/detector.js.map +1 -0
- package/dist/core/github.d.ts +41 -0
- package/dist/core/github.d.ts.map +1 -0
- package/dist/core/github.js +97 -0
- package/dist/core/github.js.map +1 -0
- package/dist/core/reporter.d.ts +8 -0
- package/dist/core/reporter.d.ts.map +1 -0
- package/dist/core/reporter.js +98 -0
- package/dist/core/reporter.js.map +1 -0
- package/dist/core/scanner.d.ts +19 -0
- package/dist/core/scanner.d.ts.map +1 -0
- package/dist/core/scanner.js +173 -0
- package/dist/core/scanner.js.map +1 -0
- package/dist/hooks/setup.d.ts +7 -0
- package/dist/hooks/setup.d.ts.map +1 -0
- package/dist/hooks/setup.js +117 -0
- package/dist/hooks/setup.js.map +1 -0
- package/dist/mcp/server.d.ts +18 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +141 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/types.d.ts +79 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep CLI wrapper.
|
|
3
|
+
* Runs `semgrep --json` on a set of files and returns normalised Issue[].
|
|
4
|
+
*
|
|
5
|
+
* Semgrep must be installed: pip install semgrep OR brew install semgrep
|
|
6
|
+
* We check for it on first run and give a clear install message if missing.
|
|
7
|
+
*/
|
|
8
|
+
import { execSync, spawnSync } from "child_process";
|
|
9
|
+
import { existsSync, readFileSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
const DEFAULT_RULESETS = ["p/secrets", "p/owasp-top-ten"];
|
|
12
|
+
const DEFAULT_EXCLUDE = ["node_modules", "dist", ".git", "coverage", "build", ".next", "vendor"];
|
|
13
|
+
// ─── Main export ─────────────────────────────────────────────────────────────
|
|
14
|
+
export async function scanFiles(files, cwd, config = {}) {
|
|
15
|
+
const t0 = Date.now();
|
|
16
|
+
// Check semgrep is available
|
|
17
|
+
const semgrepPath = findSemgrep();
|
|
18
|
+
if (!semgrepPath) {
|
|
19
|
+
return {
|
|
20
|
+
issues: [], skipped: true, filesScanned: 0, durationMs: 0, rulesets: [],
|
|
21
|
+
skipReason: "semgrep not found. Install with: pip install semgrep or brew install semgrep",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// Filter to files that exist and are under size limit
|
|
25
|
+
const maxBytes = (config.maxFileSizeKb ?? 500) * 1024;
|
|
26
|
+
const eligible = files
|
|
27
|
+
.filter((f) => {
|
|
28
|
+
const abs = f.startsWith("/") ? f : join(cwd, f);
|
|
29
|
+
if (!existsSync(abs))
|
|
30
|
+
return false;
|
|
31
|
+
try {
|
|
32
|
+
const stat = readFileSync(abs);
|
|
33
|
+
return stat.length <= maxBytes;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (eligible.length === 0) {
|
|
40
|
+
return { issues: [], skipped: true, skipReason: "No eligible files to scan", filesScanned: 0, durationMs: 0, rulesets: [] };
|
|
41
|
+
}
|
|
42
|
+
const rulesets = config.rulesets ?? DEFAULT_RULESETS;
|
|
43
|
+
const excludes = [...DEFAULT_EXCLUDE, ...(config.exclude ?? [])];
|
|
44
|
+
// Build semgrep command
|
|
45
|
+
const args = [
|
|
46
|
+
...rulesets.flatMap((r) => ["--config", r]),
|
|
47
|
+
"--json",
|
|
48
|
+
"--no-git-ignore", // we control which files to scan explicitly
|
|
49
|
+
"--quiet",
|
|
50
|
+
...excludes.flatMap((e) => ["--exclude", e]),
|
|
51
|
+
"--",
|
|
52
|
+
...eligible,
|
|
53
|
+
];
|
|
54
|
+
const result = spawnSync(semgrepPath, args, {
|
|
55
|
+
cwd,
|
|
56
|
+
encoding: "utf8",
|
|
57
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB
|
|
58
|
+
});
|
|
59
|
+
// semgrep exits 1 when findings are present — that's normal
|
|
60
|
+
const stdout = result.stdout ?? "";
|
|
61
|
+
const stderr = result.stderr ?? "";
|
|
62
|
+
if (result.status !== 0 && result.status !== 1) {
|
|
63
|
+
// Real error (exit 2+)
|
|
64
|
+
return {
|
|
65
|
+
issues: [], skipped: true, filesScanned: eligible.length, durationMs: Date.now() - t0, rulesets,
|
|
66
|
+
skipReason: `semgrep failed (exit ${result.status}): ${stderr.slice(0, 300)}`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = JSON.parse(stdout);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return {
|
|
75
|
+
issues: [], skipped: true, filesScanned: eligible.length, durationMs: Date.now() - t0, rulesets,
|
|
76
|
+
skipReason: `Failed to parse semgrep output: ${stdout.slice(0, 200)}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const issues = raw.results.map((f) => mapFinding(f, cwd));
|
|
80
|
+
return {
|
|
81
|
+
issues,
|
|
82
|
+
skipped: false,
|
|
83
|
+
filesScanned: eligible.length,
|
|
84
|
+
durationMs: Date.now() - t0,
|
|
85
|
+
rulesets,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Scans only the git-staged files in cwd.
|
|
90
|
+
* Used by the pre-commit hook.
|
|
91
|
+
*/
|
|
92
|
+
export async function scanStaged(cwd, config = {}) {
|
|
93
|
+
let staged;
|
|
94
|
+
try {
|
|
95
|
+
const out = execSync("git diff --name-only --cached --diff-filter=ACM", { cwd, encoding: "utf8" });
|
|
96
|
+
staged = out.trim().split("\n").filter(Boolean);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return { issues: [], skipped: true, skipReason: "Not a git repository or no staged files", filesScanned: 0, durationMs: 0, rulesets: [] };
|
|
100
|
+
}
|
|
101
|
+
if (staged.length === 0) {
|
|
102
|
+
return { issues: [], skipped: true, skipReason: "No staged files", filesScanned: 0, durationMs: 0, rulesets: [] };
|
|
103
|
+
}
|
|
104
|
+
return scanFiles(staged, cwd, config);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Scans files changed on a branch vs a base branch.
|
|
108
|
+
*/
|
|
109
|
+
export async function scanBranch(cwd, branch, base = "main", config = {}) {
|
|
110
|
+
let files;
|
|
111
|
+
try {
|
|
112
|
+
// Files changed on branch compared to base
|
|
113
|
+
const out = execSync(`git diff --name-only --diff-filter=ACM $(git merge-base ${base} ${branch}) ${branch}`, { cwd, encoding: "utf8" });
|
|
114
|
+
files = out.trim().split("\n").filter(Boolean);
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
// Fallback: diff between branch and base directly
|
|
118
|
+
try {
|
|
119
|
+
const out = execSync(`git diff --name-only --diff-filter=ACM ${base}...${branch}`, { cwd, encoding: "utf8" });
|
|
120
|
+
files = out.trim().split("\n").filter(Boolean);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return { issues: [], skipped: true, skipReason: `Could not diff ${branch} vs ${base}: ${String(e).slice(0, 200)}`, filesScanned: 0, durationMs: 0, rulesets: [] };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (files.length === 0) {
|
|
127
|
+
return { issues: [], skipped: true, skipReason: `No changed files between ${base} and ${branch}`, filesScanned: 0, durationMs: 0, rulesets: [] };
|
|
128
|
+
}
|
|
129
|
+
// Checkout the branch content to a temp worktree isn't practical;
|
|
130
|
+
// scan the working tree files (they may be on that branch already)
|
|
131
|
+
return scanFiles(files, cwd, config);
|
|
132
|
+
}
|
|
133
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
134
|
+
function findSemgrep() {
|
|
135
|
+
for (const candidate of ["semgrep", "/usr/local/bin/semgrep", "/opt/homebrew/bin/semgrep"]) {
|
|
136
|
+
try {
|
|
137
|
+
const r = spawnSync(candidate, ["--version"], { encoding: "utf8" });
|
|
138
|
+
if (r.status === 0)
|
|
139
|
+
return candidate;
|
|
140
|
+
}
|
|
141
|
+
catch { /* continue */ }
|
|
142
|
+
}
|
|
143
|
+
// Try python-installed semgrep
|
|
144
|
+
try {
|
|
145
|
+
const r = spawnSync("python3", ["-m", "semgrep", "--version"], { encoding: "utf8" });
|
|
146
|
+
if (r.status === 0)
|
|
147
|
+
return "python3 -m semgrep"; // caller handles space
|
|
148
|
+
}
|
|
149
|
+
catch { /* continue */ }
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function mapFinding(f, cwd) {
|
|
153
|
+
return {
|
|
154
|
+
ruleId: f.check_id,
|
|
155
|
+
path: f.path,
|
|
156
|
+
line: f.start.line,
|
|
157
|
+
col: f.start.col,
|
|
158
|
+
severity: mapSeverity(f.extra.severity),
|
|
159
|
+
message: f.extra.message,
|
|
160
|
+
sourceLine: f.extra.lines?.trim(),
|
|
161
|
+
cwe: f.extra.metadata?.cwe,
|
|
162
|
+
owasp: f.extra.metadata?.owasp,
|
|
163
|
+
references: f.extra.metadata?.references,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function mapSeverity(s) {
|
|
167
|
+
if (s === "ERROR")
|
|
168
|
+
return "error";
|
|
169
|
+
if (s === "WARNING")
|
|
170
|
+
return "warning";
|
|
171
|
+
return "info";
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/core/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/hooks/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkCH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D1D"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-commit hook installer.
|
|
3
|
+
* Writes a git hook that runs `argus-ci scan --staged`
|
|
4
|
+
* and blocks the commit if any ERROR-severity findings are found.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, writeFileSync, chmodSync, readFileSync } from "fs";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
const HOOK_MARKER = "# argus-ci-hook";
|
|
9
|
+
const HOOK_SCRIPT = `#!/usr/bin/env sh
|
|
10
|
+
${HOOK_MARKER}
|
|
11
|
+
# Semgrep quality gate — runs on every commit.
|
|
12
|
+
# Remove with: argus-ci setup --remove
|
|
13
|
+
# Bypass (emergency only): git commit --no-verify
|
|
14
|
+
|
|
15
|
+
echo "🔍 Running Semgrep security scan on staged files..."
|
|
16
|
+
|
|
17
|
+
# Run argus-ci scan on staged files
|
|
18
|
+
# Exit code 1 = errors found → block commit
|
|
19
|
+
# Exit code 0 = clean → allow commit
|
|
20
|
+
npx --yes argus-ci scan --staged
|
|
21
|
+
|
|
22
|
+
EXIT_CODE=$?
|
|
23
|
+
|
|
24
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
25
|
+
echo ""
|
|
26
|
+
echo "❌ Semgrep found security issues — commit blocked."
|
|
27
|
+
echo " Fix the issues above, then run: git commit"
|
|
28
|
+
echo " To skip (not recommended): git commit --no-verify"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo "✅ Semgrep scan passed."
|
|
33
|
+
exit 0
|
|
34
|
+
`;
|
|
35
|
+
export async function setupHook(cwd) {
|
|
36
|
+
const remove = process.argv.includes("--remove");
|
|
37
|
+
// Find .git directory
|
|
38
|
+
const gitDir = join(cwd, ".git");
|
|
39
|
+
if (!existsSync(gitDir)) {
|
|
40
|
+
console.error("❌ Not a git repository. Run this from the repo root.");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
const hooksDir = join(gitDir, "hooks");
|
|
44
|
+
const hookPath = join(hooksDir, "pre-commit");
|
|
45
|
+
if (remove) {
|
|
46
|
+
await removeHook(hookPath);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Create hooks dir if needed
|
|
50
|
+
if (!existsSync(hooksDir))
|
|
51
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
52
|
+
// Check if a hook already exists (not ours)
|
|
53
|
+
if (existsSync(hookPath)) {
|
|
54
|
+
const existing = readFileSync(hookPath, "utf8");
|
|
55
|
+
if (existing.includes(HOOK_MARKER)) {
|
|
56
|
+
console.log("✅ argus-ci pre-commit hook already installed.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Append to existing hook
|
|
60
|
+
const appended = existing.trimEnd() + "\n\n" + HOOK_SCRIPT;
|
|
61
|
+
writeFileSync(hookPath, appended, "utf8");
|
|
62
|
+
chmodSync(hookPath, 0o755);
|
|
63
|
+
console.log("✅ argus-ci hook appended to existing pre-commit hook.");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
writeFileSync(hookPath, HOOK_SCRIPT, "utf8");
|
|
67
|
+
chmodSync(hookPath, 0o755);
|
|
68
|
+
console.log("✅ argus-ci pre-commit hook installed.");
|
|
69
|
+
}
|
|
70
|
+
// Verify semgrep is available
|
|
71
|
+
const { spawnSync } = await import("child_process");
|
|
72
|
+
const check = spawnSync("semgrep", ["--version"], { encoding: "utf8" });
|
|
73
|
+
if (check.status !== 0) {
|
|
74
|
+
console.log("\n⚠️ semgrep not found on PATH.");
|
|
75
|
+
console.log(" Install it before the hook will work:");
|
|
76
|
+
console.log(" → pip install semgrep");
|
|
77
|
+
console.log(" → brew install semgrep\n");
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const version = check.stdout.trim();
|
|
81
|
+
console.log(` Using semgrep ${version}`);
|
|
82
|
+
}
|
|
83
|
+
console.log("\nThe hook will:");
|
|
84
|
+
console.log(" • Run on every git commit automatically");
|
|
85
|
+
console.log(" • Scan only the files you're committing (fast)");
|
|
86
|
+
console.log(" • Block the commit if any ERROR-severity issues are found");
|
|
87
|
+
console.log(" • Allow commits with only warnings");
|
|
88
|
+
console.log("\nTo remove: argus-ci setup --remove");
|
|
89
|
+
console.log("To bypass: git commit --no-verify (emergency only)\n");
|
|
90
|
+
}
|
|
91
|
+
async function removeHook(hookPath) {
|
|
92
|
+
if (!existsSync(hookPath)) {
|
|
93
|
+
console.log("No pre-commit hook found.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const content = readFileSync(hookPath, "utf8");
|
|
97
|
+
if (!content.includes(HOOK_MARKER)) {
|
|
98
|
+
console.log("argus-ci hook not found in pre-commit hook.");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// If the entire file is our hook, delete it
|
|
102
|
+
if (content.trim() === HOOK_SCRIPT.trim()) {
|
|
103
|
+
const { unlinkSync } = await import("fs");
|
|
104
|
+
unlinkSync(hookPath);
|
|
105
|
+
console.log("✅ argus-ci pre-commit hook removed.");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
// Otherwise strip our section from the file
|
|
109
|
+
const lines = content.split("\n");
|
|
110
|
+
const markerIdx = lines.findIndex((l) => l.includes(HOOK_MARKER));
|
|
111
|
+
if (markerIdx > 0) {
|
|
112
|
+
const stripped = lines.slice(0, markerIdx).join("\n").trimEnd() + "\n";
|
|
113
|
+
writeFileSync(hookPath, stripped, "utf8");
|
|
114
|
+
console.log("✅ argus-ci section removed from pre-commit hook.");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/hooks/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep Agent — MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Exposes four tools to Cursor / Claude Code / any MCP client:
|
|
5
|
+
*
|
|
6
|
+
* scan_files — scan specific files (called post code-generation)
|
|
7
|
+
* scan_staged — scan git staged files (pre-commit check)
|
|
8
|
+
* scan_branch — scan changed files on a branch vs base
|
|
9
|
+
* scan_pr — scan a GitHub PR by URL
|
|
10
|
+
*
|
|
11
|
+
* Add to Cursor: Settings → MCP → add entry:
|
|
12
|
+
* { "command": "npx", "args": ["argus-ci"] }
|
|
13
|
+
*
|
|
14
|
+
* Add to Claude Code (~/.claude/settings.json):
|
|
15
|
+
* { "mcpServers": { "semgrep": { "command": "npx", "args": ["argus-ci"] } } }
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep Agent — MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Exposes four tools to Cursor / Claude Code / any MCP client:
|
|
5
|
+
*
|
|
6
|
+
* scan_files — scan specific files (called post code-generation)
|
|
7
|
+
* scan_staged — scan git staged files (pre-commit check)
|
|
8
|
+
* scan_branch — scan changed files on a branch vs base
|
|
9
|
+
* scan_pr — scan a GitHub PR by URL
|
|
10
|
+
*
|
|
11
|
+
* Add to Cursor: Settings → MCP → add entry:
|
|
12
|
+
* { "command": "npx", "args": ["argus-ci"] }
|
|
13
|
+
*
|
|
14
|
+
* Add to Claude Code (~/.claude/settings.json):
|
|
15
|
+
* { "mcpServers": { "semgrep": { "command": "npx", "args": ["argus-ci"] } } }
|
|
16
|
+
*/
|
|
17
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
19
|
+
import { z } from "zod";
|
|
20
|
+
import { scanFiles, scanStaged, scanBranch } from "../core/scanner.js";
|
|
21
|
+
import { fetchPRFiles, postPRComment } from "../core/github.js";
|
|
22
|
+
import { detectRulesets } from "../core/detector.js";
|
|
23
|
+
import { toMarkdown, toPRComment } from "../core/reporter.js";
|
|
24
|
+
const server = new McpServer({
|
|
25
|
+
name: "argus",
|
|
26
|
+
version: "1.0.0",
|
|
27
|
+
});
|
|
28
|
+
// ─── Tool: scan_files ─────────────────────────────────────────────────────────
|
|
29
|
+
// Called by AI agents right after generating/modifying code.
|
|
30
|
+
server.tool("scan_files", "Scan specific files with Semgrep for security vulnerabilities and quality issues. " +
|
|
31
|
+
"Call this immediately after generating or modifying code files.", {
|
|
32
|
+
files: z.array(z.string()).describe("List of file paths to scan (relative to cwd or absolute)"),
|
|
33
|
+
cwd: z.string().optional().describe("Working directory / repo root. Defaults to process.cwd()"),
|
|
34
|
+
rulesets: z.array(z.string()).optional().describe("Semgrep rulesets to use. Defaults to auto-detected from stack. " +
|
|
35
|
+
"Examples: p/secrets, p/owasp-top-ten, p/javascript"),
|
|
36
|
+
}, async ({ files, cwd, rulesets }) => {
|
|
37
|
+
const workdir = cwd ?? process.cwd();
|
|
38
|
+
const detected = detectRulesets(workdir);
|
|
39
|
+
const config = { rulesets: rulesets ?? detected.rulesets };
|
|
40
|
+
const result = await scanFiles(files, workdir, config);
|
|
41
|
+
const markdown = toMarkdown(result, `${files.length} file${files.length !== 1 ? "s" : ""}`);
|
|
42
|
+
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "text",
|
|
47
|
+
text: markdown,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
isError: hasErrors,
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
// ─── Tool: scan_staged ────────────────────────────────────────────────────────
|
|
54
|
+
// Scans only git-staged files. Designed for pre-commit hook integration.
|
|
55
|
+
server.tool("scan_staged", "Scan all git-staged files with Semgrep. Use this before committing to catch issues in code about to be committed.", {
|
|
56
|
+
cwd: z.string().optional().describe("Repo root directory. Defaults to process.cwd()"),
|
|
57
|
+
rulesets: z.array(z.string()).optional().describe("Semgrep rulesets to use. Defaults to auto-detected."),
|
|
58
|
+
}, async ({ cwd, rulesets }) => {
|
|
59
|
+
const workdir = cwd ?? process.cwd();
|
|
60
|
+
const detected = detectRulesets(workdir);
|
|
61
|
+
const config = { rulesets: rulesets ?? detected.rulesets };
|
|
62
|
+
const result = await scanStaged(workdir, config);
|
|
63
|
+
const markdown = toMarkdown(result, "staged files");
|
|
64
|
+
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: "text", text: markdown }],
|
|
67
|
+
isError: hasErrors,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
// ─── Tool: scan_branch ────────────────────────────────────────────────────────
|
|
71
|
+
server.tool("scan_branch", "Scan all files changed on a branch compared to a base branch (default: main). " +
|
|
72
|
+
"Use when asked to review a branch or check what a feature branch introduces.", {
|
|
73
|
+
branch: z.string().describe("Branch name to scan (e.g. feature/auth)"),
|
|
74
|
+
base: z.string().optional().default("main").describe("Base branch to compare against (default: main)"),
|
|
75
|
+
cwd: z.string().optional().describe("Repo root. Defaults to process.cwd()"),
|
|
76
|
+
rulesets: z.array(z.string()).optional().describe("Semgrep rulesets. Defaults to auto-detected."),
|
|
77
|
+
}, async ({ branch, base, cwd, rulesets }) => {
|
|
78
|
+
const workdir = cwd ?? process.cwd();
|
|
79
|
+
const detected = detectRulesets(workdir);
|
|
80
|
+
const config = { rulesets: rulesets ?? detected.rulesets };
|
|
81
|
+
const result = await scanBranch(workdir, branch, base ?? "main", config);
|
|
82
|
+
const markdown = toMarkdown(result, `branch \`${branch}\` vs \`${base ?? "main"}\``);
|
|
83
|
+
const hasErrors = result.issues.some((i) => i.severity === "error");
|
|
84
|
+
return {
|
|
85
|
+
content: [{ type: "text", text: markdown }],
|
|
86
|
+
isError: hasErrors,
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
// ─── Tool: scan_pr ────────────────────────────────────────────────────────────
|
|
90
|
+
server.tool("scan_pr", "Scan a GitHub Pull Request by URL. Fetches the changed files and runs Semgrep on them. " +
|
|
91
|
+
"Optionally posts results as a PR comment.", {
|
|
92
|
+
pr_url: z.string().describe("Full GitHub PR URL, e.g. https://github.com/owner/repo/pull/142"),
|
|
93
|
+
cwd: z.string().optional().describe("Local repo root to scan files from. Required if repo is cloned locally. " +
|
|
94
|
+
"If not provided, files are reported by path only."),
|
|
95
|
+
rulesets: z.array(z.string()).optional().describe("Semgrep rulesets. Defaults to auto-detected."),
|
|
96
|
+
post_comment: z.boolean().optional().default(false).describe("Post scan results as a comment on the PR (requires GITHUB_TOKEN env var)"),
|
|
97
|
+
}, async ({ pr_url, cwd, rulesets, post_comment }) => {
|
|
98
|
+
// Fetch PR info from GitHub
|
|
99
|
+
let prInfo;
|
|
100
|
+
try {
|
|
101
|
+
prInfo = await fetchPRFiles(pr_url);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: `❌ Failed to fetch PR: ${String(err)}` }],
|
|
106
|
+
isError: true,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (!prInfo) {
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: "text", text: `❌ Could not parse PR URL: ${pr_url}` }],
|
|
112
|
+
isError: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const workdir = cwd ?? process.cwd();
|
|
116
|
+
const detected = detectRulesets(workdir);
|
|
117
|
+
const config = { rulesets: rulesets ?? detected.rulesets };
|
|
118
|
+
const result = await scanFiles(prInfo.files, workdir, config);
|
|
119
|
+
const context = `PR #${prInfo.meta.number}: ${prInfo.meta.title}`;
|
|
120
|
+
const markdown = toMarkdown(result, context);
|
|
121
|
+
// Optionally post to GitHub
|
|
122
|
+
if (post_comment) {
|
|
123
|
+
const comment = toPRComment(result, prInfo.meta.title, prInfo.meta.url);
|
|
124
|
+
const posted = await postPRComment(prInfo.owner, prInfo.repo, prInfo.meta.number, comment);
|
|
125
|
+
const postNote = posted
|
|
126
|
+
? "\n\n✅ Results posted as PR comment."
|
|
127
|
+
: "\n\n⚠️ Could not post PR comment — check GITHUB_TOKEN.";
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: "text", text: markdown + postNote }],
|
|
130
|
+
isError: result.issues.some((i) => i.severity === "error"),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
content: [{ type: "text", text: markdown }],
|
|
135
|
+
isError: result.issues.some((i) => i.severity === "error"),
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
// ─── Start ────────────────────────────────────────────────────────────────────
|
|
139
|
+
const transport = new StdioServerTransport();
|
|
140
|
+
await server.connect(transport);
|
|
141
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export interface SemgrepRawResult {
|
|
2
|
+
results: SemgrepFinding[];
|
|
3
|
+
errors: SemgrepError[];
|
|
4
|
+
stats?: {
|
|
5
|
+
total_time?: number;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export interface SemgrepFinding {
|
|
9
|
+
check_id: string;
|
|
10
|
+
path: string;
|
|
11
|
+
start: {
|
|
12
|
+
line: number;
|
|
13
|
+
col: number;
|
|
14
|
+
};
|
|
15
|
+
end: {
|
|
16
|
+
line: number;
|
|
17
|
+
col: number;
|
|
18
|
+
};
|
|
19
|
+
extra: {
|
|
20
|
+
message: string;
|
|
21
|
+
severity: "ERROR" | "WARNING" | "INFO";
|
|
22
|
+
lines?: string;
|
|
23
|
+
metadata?: {
|
|
24
|
+
cwe?: string[];
|
|
25
|
+
owasp?: string[];
|
|
26
|
+
references?: string[];
|
|
27
|
+
category?: string;
|
|
28
|
+
technology?: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface SemgrepError {
|
|
33
|
+
code: number;
|
|
34
|
+
level: string;
|
|
35
|
+
message: string;
|
|
36
|
+
type: string;
|
|
37
|
+
}
|
|
38
|
+
export type Severity = "error" | "warning" | "info";
|
|
39
|
+
export interface Issue {
|
|
40
|
+
ruleId: string;
|
|
41
|
+
path: string;
|
|
42
|
+
line: number;
|
|
43
|
+
col: number;
|
|
44
|
+
severity: Severity;
|
|
45
|
+
message: string;
|
|
46
|
+
sourceLine?: string;
|
|
47
|
+
cwe?: string[];
|
|
48
|
+
owasp?: string[];
|
|
49
|
+
references?: string[];
|
|
50
|
+
}
|
|
51
|
+
export interface ScanResult {
|
|
52
|
+
issues: Issue[];
|
|
53
|
+
skipped: boolean;
|
|
54
|
+
skipReason?: string;
|
|
55
|
+
filesScanned: number;
|
|
56
|
+
durationMs: number;
|
|
57
|
+
rulesets: string[];
|
|
58
|
+
}
|
|
59
|
+
export interface ScanConfig {
|
|
60
|
+
/** Semgrep rulesets to run — defaults to auto-detected from stack */
|
|
61
|
+
rulesets?: string[];
|
|
62
|
+
/** Fail (exit 1) if any issue of these severities is found */
|
|
63
|
+
failOn?: Severity[];
|
|
64
|
+
/** Max file size in KB to scan — default 500 */
|
|
65
|
+
maxFileSizeKb?: number;
|
|
66
|
+
/** Directories to exclude */
|
|
67
|
+
exclude?: string[];
|
|
68
|
+
/** GITHUB_TOKEN for private repo PR access */
|
|
69
|
+
githubToken?: string;
|
|
70
|
+
/** Anthropic API key for the agent interface */
|
|
71
|
+
anthropicKey?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface ToolResponse {
|
|
74
|
+
success: boolean;
|
|
75
|
+
result?: ScanResult;
|
|
76
|
+
markdown?: string;
|
|
77
|
+
error?: string;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAG,YAAY,EAAE,CAAC;IACxB,KAAK,CAAC,EAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAM,MAAM,CAAC;IACjB,KAAK,EAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,GAAG,EAAO;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,EAAE;QACL,OAAO,EAAI,MAAM,CAAC;QAClB,QAAQ,EAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;QACxC,KAAK,CAAC,EAAK,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE;YACT,GAAG,CAAC,EAAS,MAAM,EAAE,CAAC;YACtB,KAAK,CAAC,EAAO,MAAM,EAAE,CAAC;YACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;YACtB,QAAQ,CAAC,EAAI,MAAM,CAAC;YACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;SACvB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAK,MAAM,CAAC;IAChB,KAAK,EAAI,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAK,MAAM,CAAC;CACjB;AAID,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,KAAK;IACpB,MAAM,EAAO,MAAM,CAAC;IACpB,IAAI,EAAS,MAAM,CAAC;IACpB,IAAI,EAAS,MAAM,CAAC;IACpB,GAAG,EAAU,MAAM,CAAC;IACpB,QAAQ,EAAK,QAAQ,CAAC;IACtB,OAAO,EAAM,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAS,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAO,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAID,MAAM,WAAW,UAAU;IACzB,MAAM,EAAM,KAAK,EAAE,CAAC;IACpB,OAAO,EAAK,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAG,MAAM,CAAC;IACpB,QAAQ,EAAK,MAAM,EAAE,CAAC;CACvB;AAID,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAI,QAAQ,EAAE,CAAC;IACtB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,OAAO,CAAC,EAAG,MAAM,EAAE,CAAC;IACpB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAG,OAAO,CAAC;IAClB,MAAM,CAAC,EAAG,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAI,MAAM,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,iFAAiF"}
|