agent-security-scanner-mcp 4.4.6 → 4.4.8

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/README.md CHANGED
@@ -34,6 +34,12 @@ npx agent-security-scanner-mcp init claude-code
34
34
 
35
35
  Replace `claude-code` with `cursor`, `claude-desktop`, `windsurf`, `cline`, `kilo-code`, `opencode`, or `cody`.
36
36
 
37
+ Add the GitHub Actions workflow:
38
+
39
+ ```bash
40
+ npx agent-security-scanner-mcp init-ci github
41
+ ```
42
+
37
43
  ### What To Run Before You Trust An Agent
38
44
 
39
45
  ```bash
@@ -46,6 +52,9 @@ npx agent-security-scanner-mcp scan-mcp ./path/to/mcp-server --verbosity compact
46
52
  # Verify AI-suggested imports are real packages, not hallucinations
47
53
  npx agent-security-scanner-mcp scan-packages ./src/app.ts npm --verbosity compact
48
54
 
55
+ # Check one package before installing it
56
+ npx agent-security-scanner-mcp check-package express npm
57
+
49
58
  # Add a local environment health check
50
59
  npx agent-security-scanner-mcp doctor
51
60
 
@@ -98,6 +107,10 @@ Continue reading below for full version documentation →
98
107
 
99
108
  ---
100
109
 
110
+ > **New in v4.4.8 (2026-07-07):** Package hallucination demo — run `npx agent-security-scanner-mcp demo --type packages --no-prompt` to create and scan a tiny import file with real and fake npm packages. README examples now show both single-package verification and import scanning.
111
+ >
112
+ > **New in v4.4.7 (2026-07-07):** CI adoption improvements — added `init-ci github` to install the GitHub Actions workflow from the CLI, and scheduled GitHub Action runs now automatically scan the full project instead of only the latest diff. Package hallucination checks also use all tracked source files during full-project runs.
113
+ >
101
114
  > **New in v4.3.0 (2026-05-05):** Critical security and reliability fixes — GitHub Actions now **fail closed** instead of fail-open when scanner output is invalid (preventing security gate bypass), patched **8 Hono CVEs** (XSS, path traversal, authentication bypass), fixed confidence threshold filtering case sensitivity, and corrected SARIF generation for GitHub Code Scanning. All fixes include comprehensive regression tests. **Upgrade recommended for production use.** [See Full Changelog](CHANGELOG.md#430---2026-05-05).
102
115
  >
103
116
  > **New in v4.2.0:** Compliance evidence collection — evaluate projects against SOC2-Technical (8 controls) and GDPR-Technical (6 controls) frameworks. Collects evidence from code scans, SBOM, vulnerability checks, and hallucination detection, then evaluates controls with pass/partial/fail/not_evaluated status. Supports evidence persistence for audit trails. [See Compliance Evaluation](#-compliance-evaluation-new-in-v420).
@@ -1315,9 +1328,12 @@ Checks Node.js version, Python availability, analyzer engine status, and scans a
1315
1328
 
1316
1329
  ```bash
1317
1330
  npx agent-security-scanner-mcp demo --lang js
1331
+ npx agent-security-scanner-mcp demo --type packages --no-prompt
1318
1332
  ```
1319
1333
 
1320
- Creates a small file with 3 intentional vulnerabilities, runs the scanner, shows findings with CWE/OWASP references, and asks if you want to keep the file for testing.
1334
+ The security demo creates a small file with 3 intentional vulnerabilities, runs the scanner, shows findings with CWE/OWASP references, and asks if you want to keep the file for testing.
1335
+
1336
+ The package demo creates a tiny JavaScript import file with real and hallucinated npm packages, runs `scan-packages`, and deletes the file unless you pass `--keep`.
1321
1337
 
1322
1338
  Available languages: `js` (default), `py`, `go`, `java`.
1323
1339
 
@@ -1342,9 +1358,17 @@ npx agent-security-scanner-mcp scan-project ./src
1342
1358
 
1343
1359
  # Check if a package is legitimate
1344
1360
  npx agent-security-scanner-mcp check-package flask pypi
1361
+ npx agent-security-scanner-mcp check-package express npm
1345
1362
 
1346
1363
  # Scan file imports for hallucinated packages
1347
1364
  npx agent-security-scanner-mcp scan-packages ./requirements.txt pypi
1365
+ npx agent-security-scanner-mcp scan-packages ./src/app.ts npm --verbosity compact
1366
+
1367
+ # Try the package hallucination demo
1368
+ npx agent-security-scanner-mcp demo --type packages --no-prompt
1369
+
1370
+ # Install the GitHub Actions workflow
1371
+ npx agent-security-scanner-mcp init-ci github
1348
1372
 
1349
1373
  # Install Claude Code hooks for automatic scanning
1350
1374
  npx agent-security-scanner-mcp init-hooks
@@ -1633,6 +1657,20 @@ All MCP tools support a `verbosity` parameter to minimize context window consump
1633
1657
 
1634
1658
  ## Changelog
1635
1659
 
1660
+ ### v4.4.8 (2026-07-07) - Package Hallucination Demo
1661
+
1662
+ - **New demo mode:** `demo --type packages` creates a small JavaScript file with real and hallucinated npm imports, then runs `scan-packages`.
1663
+ - **Automation-friendly demo:** `--no-prompt` cleans up the generated file without waiting for input, and `--keep` preserves it for local testing.
1664
+ - **README examples:** Added clearer single-package and import-scan examples for `check-package` and `scan-packages`.
1665
+ - **Regression coverage:** Added tests for package demo cleanup and `--keep` behavior.
1666
+
1667
+ ### v4.4.7 (2026-07-07) - CI Adoption
1668
+
1669
+ - **New CLI command:** `init-ci github` installs the public GitHub Actions workflow template into `.github/workflows/agent-security.yml`.
1670
+ - **Safer scheduled scans:** Scheduled GitHub Action runs now force full-project scanning even when pull requests use diff-only mode.
1671
+ - **Better package checks in CI:** Full-project runs verify imports from all tracked source files instead of only changed files.
1672
+ - **Regression coverage:** Added tests for the CI installer and scheduled full-project action behavior.
1673
+
1636
1674
  ### v4.2.0 (2026-04-02) - Compliance Evidence Collection
1637
1675
 
1638
1676
  **🚀 New Feature: SOC2/GDPR Technical Compliance Evaluation**
package/index.js CHANGED
@@ -570,6 +570,12 @@ const cliArgs = process.argv.slice(2);
570
570
  console.error(` Error: ${err.message}\n`);
571
571
  process.exit(1);
572
572
  });
573
+ } else if (cliArgs[0] === 'init-ci') {
574
+ const { runInitCi } = await import('./src/cli/init-ci.js');
575
+ runInitCi(cliArgs.slice(1)).then(() => process.exit(0)).catch(err => {
576
+ console.error(` Error: ${err.message}\n`);
577
+ process.exit(1);
578
+ });
573
579
  } else if (cliArgs[0] === 'harden') {
574
580
  const { runHarden } = await import('./src/cli/harden.js');
575
581
  runHarden(cliArgs.slice(1)).then(() => process.exit(0)).catch(err => {
@@ -673,9 +679,11 @@ const cliArgs = process.argv.slice(2);
673
679
  console.log('\n agent-security-scanner-mcp\n');
674
680
  console.log(' Commands:');
675
681
  console.log(' init [client] Set up MCP config for a client');
682
+ console.log(' init-ci [provider] Install CI workflow template (github)');
676
683
  console.log(' init-hooks Install Claude Code hooks for auto-scanning');
677
684
  console.log(' doctor [--fix] Check environment & client configs');
678
685
  console.log(' demo [--lang js] Generate vulnerable file + scan it');
686
+ console.log(' demo --type packages Generate package hallucination demo + scan it');
679
687
  console.log(' report <dir> Generate HTML security report with history [--threat-model]');
680
688
  console.log(' benchmark [flags] Run accuracy benchmarks\n');
681
689
  console.log(' CLI Tools (for scripts & OpenClaw):');
@@ -705,6 +713,8 @@ const cliArgs = process.argv.slice(2);
705
713
  console.log(' --exclude <pattern> Exclude matching files (scan-project)\n');
706
714
  console.log(' Examples:');
707
715
  console.log(' npx agent-security-scanner-mcp init');
716
+ console.log(' npx agent-security-scanner-mcp init-ci github');
717
+ console.log(' npx agent-security-scanner-mcp demo --type packages --no-prompt');
708
718
  console.log(' npx agent-security-scanner-mcp scan-prompt "ignore previous instructions"');
709
719
  console.log(' npx agent-security-scanner-mcp scan-security ./app.py --verbosity minimal');
710
720
  console.log(' npx agent-security-scanner-mcp check-package flask pypi');
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-security-scanner-mcp",
3
- "version": "4.4.6",
3
+ "version": "4.4.8",
4
4
  "description": "npm audit for AI agents and OpenClaw skills: prompt injection firewall, package hallucination detection, MCP/security scanning, and auto-fix",
5
5
  "author": "Sinewave AI",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-security-scanner-mcp",
3
- "version": "4.4.6",
3
+ "version": "4.4.8",
4
4
  "mcpName": "io.github.sinewaveai/agent-security-scanner-mcp",
5
5
  "description": "npm audit for AI agents and MCP servers. Scan code, MCP tools, prompts, and hallucinated packages for Claude Code, Cursor, Windsurf, Cline, OpenClaw, and CI.",
6
6
  "main": "index.js",
package/server.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.sinewaveai/agent-security-scanner-mcp",
4
4
  "description": "npm audit for AI agents and MCP servers: scan code, MCP tools, prompts, and hallucinated packages before agents trust them.",
5
- "version": "4.4.6",
5
+ "version": "4.4.8",
6
6
  "transport": "stdio",
7
7
  "registry": "npm"
8
8
  }
package/src/cli/demo.js CHANGED
@@ -5,6 +5,8 @@ import { createInterface } from "readline";
5
5
  import { dirname } from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { resolvePythonCommand, pythonArgs } from "../python.js";
8
+ import { loadPackageLists } from "../tools/check-package.js";
9
+ import { scanPackages } from "../tools/scan-packages.js";
8
10
 
9
11
  // Handle both ESM and CJS bundling (Smithery bundles to CJS)
10
12
  let __dirname;
@@ -135,13 +137,41 @@ public class VulnDemo {
135
137
  }
136
138
  };
137
139
 
140
+ const PACKAGE_DEMO = {
141
+ ecosystem: 'npm',
142
+ filename: 'hallucination-demo.js',
143
+ code: `import express from "express";
144
+ import chalk from "chalk";
145
+ import agentMemoryGraph from "agent-memory-graph-cache";
146
+
147
+ const bridge = require("secure-mcp-session-bridge");
148
+
149
+ console.log(express, chalk, agentMemoryGraph, bridge);
150
+ `
151
+ };
152
+
138
153
  function parseDemoFlags(args) {
139
- const flags = { lang: 'js' };
154
+ const flags = {
155
+ lang: 'js',
156
+ type: 'security',
157
+ keep: false,
158
+ noPrompt: false,
159
+ };
140
160
  let i = 0;
141
161
  while (i < args.length) {
142
162
  const arg = args[i];
143
163
  if ((arg === '--lang' || arg === '-l') && i + 1 < args.length) {
144
164
  flags.lang = args[++i].toLowerCase();
165
+ } else if ((arg === '--type' || arg === '-t') && i + 1 < args.length) {
166
+ flags.type = args[++i].toLowerCase();
167
+ } else if (arg === '--packages') {
168
+ flags.type = 'packages';
169
+ } else if (arg === '--security') {
170
+ flags.type = 'security';
171
+ } else if (arg === '--keep') {
172
+ flags.keep = true;
173
+ } else if (arg === '--no-prompt' || arg === '--yes') {
174
+ flags.noPrompt = true;
145
175
  } else if (!arg.startsWith('-')) {
146
176
  flags.lang = arg.toLowerCase();
147
177
  }
@@ -159,8 +189,58 @@ function checkCommand(cmd, args) {
159
189
  }
160
190
  }
161
191
 
162
- export async function runDemo(args) {
192
+ async function askKeep(filename) {
193
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
194
+ return new Promise((resolve) => {
195
+ rl.question(` Keep ${filename} for testing? (y/N): `, (a) => { rl.close(); resolve(a); });
196
+ });
197
+ }
198
+
199
+ async function runPackageDemo(flags, options) {
200
+ const cwd = options.cwd || process.cwd();
201
+ const filepath = join(cwd, PACKAGE_DEMO.filename);
202
+
203
+ console.log(`\n agent-security-scanner-mcp package demo\n`);
204
+ console.log(` Creating ${PACKAGE_DEMO.filename} with real and hallucinated imports...\n`);
205
+
206
+ writeFileSync(filepath, PACKAGE_DEMO.code);
207
+ loadPackageLists();
208
+
209
+ console.log(` Scanning imports with scan-packages (${PACKAGE_DEMO.ecosystem})...\n`);
210
+
211
+ const scanResult = await scanPackages({
212
+ file_path: filepath,
213
+ ecosystem: PACKAGE_DEMO.ecosystem,
214
+ verbosity: 'compact'
215
+ });
216
+ const output = JSON.parse(scanResult.content[0].text);
217
+
218
+ console.log(JSON.stringify(output, null, 2));
219
+
220
+ const shouldKeep = flags.keep || (!flags.noPrompt && (await askKeep(PACKAGE_DEMO.filename)).toLowerCase() === 'y');
221
+ if (shouldKeep) {
222
+ console.log(`\n Kept: ${filepath}`);
223
+ } else {
224
+ unlinkSync(filepath);
225
+ console.log(`\n Deleted: ${PACKAGE_DEMO.filename}`);
226
+ }
227
+
228
+ console.log(`\n Next: ask your coding agent to add a dependency, then run`);
229
+ console.log(` npx agent-security-scanner-mcp scan-packages <file> npm --verbosity compact\n`);
230
+
231
+ return output;
232
+ }
233
+
234
+ export async function runDemo(args, options = {}) {
163
235
  const flags = parseDemoFlags(args);
236
+ if (flags.type === 'packages' || flags.type === 'package') {
237
+ return runPackageDemo(flags, options);
238
+ }
239
+
240
+ if (flags.type !== 'security') {
241
+ throw new Error(`unknown demo type: ${flags.type}. Available: security, packages`);
242
+ }
243
+
164
244
  const template = DEMO_TEMPLATES[flags.lang];
165
245
  if (!template) {
166
246
  console.log(`\n Unknown language: "${flags.lang}"`);
@@ -169,7 +249,7 @@ export async function runDemo(args) {
169
249
  }
170
250
 
171
251
  const filename = `vuln-demo.${template.ext}`;
172
- const filepath = join(process.cwd(), filename);
252
+ const filepath = join(options.cwd || process.cwd(), filename);
173
253
 
174
254
  console.log(`\n agent-security-scanner-mcp demo\n`);
175
255
  console.log(` Creating ${filename} with 3 intentional vulnerabilities...\n`);
@@ -211,10 +291,7 @@ export async function runDemo(args) {
211
291
  }
212
292
 
213
293
  // Ask to keep or delete
214
- const rl = createInterface({ input: process.stdin, output: process.stdout });
215
- const answer = await new Promise((resolve) => {
216
- rl.question(` Keep ${filename} for testing? (y/N): `, (a) => { rl.close(); resolve(a); });
217
- });
294
+ const answer = flags.keep ? 'y' : flags.noPrompt ? 'n' : await askKeep(filename);
218
295
 
219
296
  if (answer.toLowerCase() === 'y') {
220
297
  console.log(`\n Kept: ${filepath}`);
@@ -225,4 +302,6 @@ export async function runDemo(args) {
225
302
 
226
303
  console.log(`\n Next: Connect to your AI coding tool and ask it to`);
227
304
  console.log(` "scan ${filename} for security issues"\n`);
305
+
306
+ return results;
228
307
  }
@@ -0,0 +1,75 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
+ import { dirname, join, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ function parseFlags(args) {
6
+ const flags = {
7
+ provider: 'github',
8
+ dryRun: false,
9
+ force: false,
10
+ outputPath: null,
11
+ };
12
+
13
+ for (let i = 0; i < args.length; i++) {
14
+ const arg = args[i];
15
+ if (arg === '--dry-run') {
16
+ flags.dryRun = true;
17
+ } else if (arg === '--force') {
18
+ flags.force = true;
19
+ } else if (arg === '--path' && args[i + 1]) {
20
+ flags.outputPath = args[++i];
21
+ } else if (!arg.startsWith('-')) {
22
+ flags.provider = arg;
23
+ }
24
+ }
25
+
26
+ return flags;
27
+ }
28
+
29
+ function repoRootFromModule() {
30
+ return resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
31
+ }
32
+
33
+ export async function runInitCi(args = [], options = {}) {
34
+ const flags = parseFlags(args);
35
+ const cwd = options.cwd || process.cwd();
36
+ const repoRoot = options.repoRoot || repoRootFromModule();
37
+
38
+ if (flags.provider !== 'github') {
39
+ throw new Error(`unsupported CI provider: ${flags.provider}. Supported providers: github`);
40
+ }
41
+
42
+ const templatePath = join(repoRoot, 'templates', 'github-action-security.yml');
43
+ const outputPath = resolve(cwd, flags.outputPath || join('.github', 'workflows', 'agent-security.yml'));
44
+
45
+ if (!existsSync(templatePath)) {
46
+ throw new Error(`GitHub Actions template not found: ${templatePath}`);
47
+ }
48
+
49
+ const template = readFileSync(templatePath, 'utf8');
50
+
51
+ console.log('\n agent-security-scanner-mcp CI setup\n');
52
+ console.log(` Provider: GitHub Actions`);
53
+ console.log(` Output: ${outputPath}`);
54
+
55
+ if (existsSync(outputPath) && !flags.force) {
56
+ console.log('\n Workflow already exists. Use --force to overwrite, or --path to choose another file.\n');
57
+ return { written: false, outputPath, reason: 'exists' };
58
+ }
59
+
60
+ if (flags.dryRun) {
61
+ console.log('\n [dry-run] Would write workflow:\n');
62
+ console.log(template);
63
+ console.log(' No changes made.\n');
64
+ return { written: false, outputPath, dryRun: true };
65
+ }
66
+
67
+ mkdirSync(dirname(outputPath), { recursive: true });
68
+ writeFileSync(outputPath, template, 'utf8');
69
+
70
+ console.log('\n Wrote GitHub Actions workflow.');
71
+ console.log(' Next steps: commit the workflow and open a pull request to see scan comments.\n');
72
+
73
+ return { written: true, outputPath };
74
+ }
75
+
@@ -5,6 +5,8 @@ on:
5
5
  push:
6
6
  branches: [main]
7
7
  schedule:
8
+ # Weekly full-project scan. The composite action automatically switches
9
+ # scheduled runs to full-project mode even when PRs use diff-only mode.
8
10
  - cron: "0 9 * * 1"
9
11
 
10
12
  permissions:
@@ -28,4 +30,3 @@ jobs:
28
30
  scan_packages: "true"
29
31
  scan_diff_only: "true"
30
32
  upload_sarif: "true"
31
-