@elliotllliu/agentshield 0.1.0 → 0.2.1
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 +207 -66
- package/README.zh-CN.md +129 -0
- package/dist/cli.js +175 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +24 -0
- package/dist/config.js +91 -0
- package/dist/config.js.map +1 -0
- package/dist/reporter/badge.d.ts +7 -0
- package/dist/reporter/badge.js +50 -0
- package/dist/reporter/badge.js.map +1 -0
- package/dist/rules/index.js +2 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/mcp-manifest.d.ts +2 -0
- package/dist/rules/mcp-manifest.js +195 -0
- package/dist/rules/mcp-manifest.js.map +1 -0
- package/dist/scanner/index.d.ts +2 -2
- package/dist/scanner/index.js +33 -3
- package/dist/scanner/index.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/yaml-simple.d.ts +6 -0
- package/dist/yaml-simple.js +98 -0
- package/dist/yaml-simple.js.map +1 -0
- package/package.json +42 -3
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** AgentShield configuration */
|
|
2
|
+
export interface ScanConfig {
|
|
3
|
+
/** Rules to enable (default: all) */
|
|
4
|
+
rules?: {
|
|
5
|
+
enable?: string[];
|
|
6
|
+
disable?: string[];
|
|
7
|
+
};
|
|
8
|
+
/** Severity overrides: rule-id → severity */
|
|
9
|
+
severity?: Record<string, "critical" | "warning" | "info">;
|
|
10
|
+
/** Score threshold for CI (same as --fail-under) */
|
|
11
|
+
failUnder?: number;
|
|
12
|
+
/** Glob patterns to ignore */
|
|
13
|
+
ignore?: string[];
|
|
14
|
+
}
|
|
15
|
+
/** Load config from target directory or parents */
|
|
16
|
+
export declare function loadConfig(dir: string): ScanConfig;
|
|
17
|
+
/** Load .agentshieldignore patterns */
|
|
18
|
+
export declare function loadIgnorePatterns(dir: string): string[];
|
|
19
|
+
/** Check if a file path matches any ignore pattern */
|
|
20
|
+
export declare function isIgnored(filePath: string, patterns: string[]): boolean;
|
|
21
|
+
/** Default config content for `agentshield init` */
|
|
22
|
+
export declare const DEFAULT_CONFIG = "# AgentShield Configuration\n# https://github.com/elliotllliu/agentshield\n\nrules:\n # disable:\n # - supply-chain # skip npm audit\n # - phone-home # allow periodic HTTP\n\n# severity:\n# sensitive-read: info # downgrade to info\n\n# failUnder: 70 # CI threshold\n\n# ignore:\n# - \"tests/**\"\n# - \"*.test.ts\"\n";
|
|
23
|
+
/** Default ignore content */
|
|
24
|
+
export declare const DEFAULT_IGNORE = "# AgentShield Ignore\n# Patterns here will be excluded from scanning\n\nnode_modules/\ndist/\nbuild/\n.git/\n*.test.ts\n*.test.js\n*.spec.ts\n*.spec.js\n__tests__/\ncoverage/\n";
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { parse as parseYaml } from "./yaml-simple.js";
|
|
4
|
+
const CONFIG_NAMES = [".agentshield.yml", ".agentshield.yaml", "agentshield.config.yml"];
|
|
5
|
+
/** Load config from target directory or parents */
|
|
6
|
+
export function loadConfig(dir) {
|
|
7
|
+
for (const name of CONFIG_NAMES) {
|
|
8
|
+
const configPath = join(dir, name);
|
|
9
|
+
if (existsSync(configPath)) {
|
|
10
|
+
try {
|
|
11
|
+
const content = readFileSync(configPath, "utf-8");
|
|
12
|
+
return parseYaml(content);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// invalid config, use defaults
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
/** Load .agentshieldignore patterns */
|
|
22
|
+
export function loadIgnorePatterns(dir) {
|
|
23
|
+
const ignorePath = join(dir, ".agentshieldignore");
|
|
24
|
+
if (!existsSync(ignorePath))
|
|
25
|
+
return [];
|
|
26
|
+
try {
|
|
27
|
+
return readFileSync(ignorePath, "utf-8")
|
|
28
|
+
.split("\n")
|
|
29
|
+
.map((line) => line.trim())
|
|
30
|
+
.filter((line) => line && !line.startsWith("#"));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Check if a file path matches any ignore pattern */
|
|
37
|
+
export function isIgnored(filePath, patterns) {
|
|
38
|
+
for (const pattern of patterns) {
|
|
39
|
+
// Simple glob matching: support * and **
|
|
40
|
+
if (pattern.endsWith("/")) {
|
|
41
|
+
// Directory pattern
|
|
42
|
+
if (filePath.startsWith(pattern) || filePath.includes("/" + pattern))
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
else if (pattern.includes("*")) {
|
|
46
|
+
const regex = new RegExp("^" + pattern.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
47
|
+
if (regex.test(filePath))
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Exact match or suffix match
|
|
52
|
+
if (filePath === pattern || filePath.endsWith("/" + pattern) || filePath.endsWith(pattern))
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
/** Default config content for `agentshield init` */
|
|
59
|
+
export const DEFAULT_CONFIG = `# AgentShield Configuration
|
|
60
|
+
# https://github.com/elliotllliu/agentshield
|
|
61
|
+
|
|
62
|
+
rules:
|
|
63
|
+
# disable:
|
|
64
|
+
# - supply-chain # skip npm audit
|
|
65
|
+
# - phone-home # allow periodic HTTP
|
|
66
|
+
|
|
67
|
+
# severity:
|
|
68
|
+
# sensitive-read: info # downgrade to info
|
|
69
|
+
|
|
70
|
+
# failUnder: 70 # CI threshold
|
|
71
|
+
|
|
72
|
+
# ignore:
|
|
73
|
+
# - "tests/**"
|
|
74
|
+
# - "*.test.ts"
|
|
75
|
+
`;
|
|
76
|
+
/** Default ignore content */
|
|
77
|
+
export const DEFAULT_IGNORE = `# AgentShield Ignore
|
|
78
|
+
# Patterns here will be excluded from scanning
|
|
79
|
+
|
|
80
|
+
node_modules/
|
|
81
|
+
dist/
|
|
82
|
+
build/
|
|
83
|
+
.git/
|
|
84
|
+
*.test.ts
|
|
85
|
+
*.test.js
|
|
86
|
+
*.spec.ts
|
|
87
|
+
*.spec.js
|
|
88
|
+
__tests__/
|
|
89
|
+
coverage/
|
|
90
|
+
`;
|
|
91
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAiBtD,MAAM,YAAY,GAAG,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,wBAAwB,CAAC,CAAC;AAEzF,mDAAmD;AACnD,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAClD,OAAO,SAAS,CAAC,OAAO,CAAe,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC;aACrC,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,QAAkB;IAC5D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,yCAAyC;QACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,oBAAoB;YACpB,IAAI,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC;gBAAE,OAAO,IAAI,CAAC;QACpF,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,GAAG,CACzF,CAAC;YACF,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,8BAA8B;YAC9B,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC1G,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;CAgB7B,CAAC;AAEF,6BAA6B;AAC7B,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;CAa7B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ScanResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Generate a shields.io-style SVG badge for the security score.
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateBadgeSvg(result: ScanResult): string;
|
|
6
|
+
/** Generate a markdown badge string */
|
|
7
|
+
export declare function generateBadgeMarkdown(score: number, repoUrl?: string): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a shields.io-style SVG badge for the security score.
|
|
3
|
+
*/
|
|
4
|
+
export function generateBadgeSvg(result) {
|
|
5
|
+
const score = result.score;
|
|
6
|
+
const { color, label } = getBadgeStyle(score);
|
|
7
|
+
const scoreText = `${score}/100`;
|
|
8
|
+
// Shield dimensions
|
|
9
|
+
const labelWidth = 90;
|
|
10
|
+
const valueWidth = 60;
|
|
11
|
+
const totalWidth = labelWidth + valueWidth;
|
|
12
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20" role="img" aria-label="AgentShield: ${scoreText}">
|
|
13
|
+
<title>AgentShield: ${scoreText} (${label})</title>
|
|
14
|
+
<linearGradient id="s" x2="0" y2="100%">
|
|
15
|
+
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
16
|
+
<stop offset="1" stop-opacity=".1"/>
|
|
17
|
+
</linearGradient>
|
|
18
|
+
<clipPath id="r">
|
|
19
|
+
<rect width="${totalWidth}" height="20" rx="3" fill="#fff"/>
|
|
20
|
+
</clipPath>
|
|
21
|
+
<g clip-path="url(#r)">
|
|
22
|
+
<rect width="${labelWidth}" height="20" fill="#555"/>
|
|
23
|
+
<rect x="${labelWidth}" width="${valueWidth}" height="20" fill="${color}"/>
|
|
24
|
+
<rect width="${totalWidth}" height="20" fill="url(#s)"/>
|
|
25
|
+
</g>
|
|
26
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
|
|
27
|
+
<text aria-hidden="true" x="${labelWidth * 5}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">${"🛡️ AgentShield"}</text>
|
|
28
|
+
<text x="${labelWidth * 5}" y="140" transform="scale(.1)">${"🛡️ AgentShield"}</text>
|
|
29
|
+
<text aria-hidden="true" x="${(labelWidth + valueWidth / 2) * 10}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">${scoreText}</text>
|
|
30
|
+
<text x="${(labelWidth + valueWidth / 2) * 10}" y="140" transform="scale(.1)">${scoreText}</text>
|
|
31
|
+
</g>
|
|
32
|
+
</svg>`;
|
|
33
|
+
}
|
|
34
|
+
/** Generate a markdown badge string */
|
|
35
|
+
export function generateBadgeMarkdown(score, repoUrl) {
|
|
36
|
+
const { color, label } = getBadgeStyle(score);
|
|
37
|
+
const badgeUrl = `https://img.shields.io/badge/AgentShield-${score}%2F100-${color.replace("#", "")}?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0xMiAxTDMgNXY2YzAgNS41NSAzLjg0IDEwLjc0IDkgMTIgNS4xNi0xLjI2IDktNi40NSA5LTEyVjVsLTktNHoiLz48L3N2Zz4=`;
|
|
38
|
+
const link = repoUrl || "https://github.com/elliotllliu/agentshield";
|
|
39
|
+
return `[](${link})`;
|
|
40
|
+
}
|
|
41
|
+
function getBadgeStyle(score) {
|
|
42
|
+
if (score >= 90)
|
|
43
|
+
return { color: "#4c1", label: "Low Risk" };
|
|
44
|
+
if (score >= 70)
|
|
45
|
+
return { color: "#dfb317", label: "Moderate Risk" };
|
|
46
|
+
if (score >= 40)
|
|
47
|
+
return { color: "#fe7d37", label: "High Risk" };
|
|
48
|
+
return { color: "#e05d44", label: "Critical Risk" };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../../src/reporter/badge.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAkB;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,GAAG,KAAK,MAAM,CAAC;IAEjC,oBAAoB;IACpB,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAE3C,OAAO,kDAAkD,UAAU,qDAAqD,SAAS;wBAC3G,SAAS,KAAK,KAAK;;;;;;mBAMxB,UAAU;;;mBAGV,UAAU;eACd,UAAU,YAAY,UAAU,uBAAuB,KAAK;mBACxD,UAAU;;;kCAGK,UAAU,GAAG,CAAC,oEAAoE,iBAAiB;eACtH,UAAU,GAAG,CAAC,mCAAmC,iBAAiB;kCAC/C,CAAC,UAAU,GAAG,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,oEAAoE,SAAS;eAClI,CAAC,UAAU,GAAG,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,mCAAmC,SAAS;;OAEtF,CAAC;AACR,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,OAAgB;IACnE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,4CAA4C,KAAK,UAAU,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,oPAAoP,CAAC;IACvV,MAAM,IAAI,GAAG,OAAO,IAAI,4CAA4C,CAAC;IACrE,OAAO,kBAAkB,KAAK,SAAS,QAAQ,MAAM,IAAI,GAAG,CAAC;AAC/D,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC7D,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IACrE,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;AACtD,CAAC"}
|
package/dist/rules/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { excessivePermsRule } from "./excessive-perms.js";
|
|
|
13
13
|
import { phoneHomeRule } from "./phone-home.js";
|
|
14
14
|
import { credentialHardcodeRule } from "./credential-hardcode.js";
|
|
15
15
|
import { networkSsrfRule } from "./network-ssrf.js";
|
|
16
|
+
import { mcpManifestRule } from "./mcp-manifest.js";
|
|
16
17
|
/** All registered rules */
|
|
17
18
|
export const rules = [
|
|
18
19
|
// Original 5
|
|
@@ -32,6 +33,7 @@ export const rules = [
|
|
|
32
33
|
phoneHomeRule,
|
|
33
34
|
credentialHardcodeRule,
|
|
34
35
|
networkSsrfRule,
|
|
36
|
+
mcpManifestRule,
|
|
35
37
|
];
|
|
36
38
|
/** Get a rule by ID */
|
|
37
39
|
export function getRule(id) {
|
package/dist/rules/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,2BAA2B;AAC3B,MAAM,CAAC,MAAM,KAAK,GAAW;IAC3B,aAAa;IACb,aAAa;IACb,YAAY;IACZ,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,SAAS;IACT,eAAe;IACf,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,eAAe;IACf,kBAAkB;IAClB,aAAa;IACb,sBAAsB;IACtB,eAAe;CAChB,CAAC;AAEF,uBAAuB;AACvB,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACxC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,2BAA2B;AAC3B,MAAM,CAAC,MAAM,KAAK,GAAW;IAC3B,aAAa;IACb,aAAa;IACb,YAAY;IACZ,aAAa;IACb,eAAe;IACf,iBAAiB;IACjB,SAAS;IACT,eAAe;IACf,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,eAAe;IACf,kBAAkB;IAClB,aAAa;IACb,sBAAsB;IACtB,eAAe;IACf,eAAe;CAChB,CAAC;AAEF,uBAAuB;AACvB,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: mcp-manifest
|
|
3
|
+
* Validates MCP (Model Context Protocol) server configurations.
|
|
4
|
+
*
|
|
5
|
+
* Checks:
|
|
6
|
+
* 1. Declared tools/resources vs actual code behavior
|
|
7
|
+
* 2. Overly broad tool descriptions that could mislead agents
|
|
8
|
+
* 3. Undeclared file system / network / exec capabilities
|
|
9
|
+
* 4. Suspicious tool names or descriptions
|
|
10
|
+
*/
|
|
11
|
+
// Patterns indicating MCP server tool registration
|
|
12
|
+
const TOOL_REGISTER_RE = /\.tool\s*\(|addTool\s*\(|registerTool\s*\(|server\.setRequestHandler.*ListTools|tools:\s*\[/;
|
|
13
|
+
// Patterns for MCP resource registration
|
|
14
|
+
const RESOURCE_REGISTER_RE = /\.resource\s*\(|addResource\s*\(|registerResource\s*\(|server\.setRequestHandler.*ListResources|resources:\s*\[/;
|
|
15
|
+
// Dangerous patterns in tool implementations
|
|
16
|
+
const DANGEROUS_TOOL_PATTERNS = [
|
|
17
|
+
{ pattern: /child_process|execSync|exec\(|spawn\(/, desc: "Tool executes shell commands", severity: "critical" },
|
|
18
|
+
{ pattern: /fs\.unlink|fs\.rmdir|fs\.rm\b|rimraf/, desc: "Tool deletes files", severity: "warning" },
|
|
19
|
+
{ pattern: /fs\.writeFile|fs\.appendFile|fs\.createWriteStream/, desc: "Tool writes to file system", severity: "warning" },
|
|
20
|
+
{ pattern: /fetch\s*\(|axios|http\.request|https\.request/, desc: "Tool makes outbound HTTP requests", severity: "warning" },
|
|
21
|
+
{ pattern: /eval\s*\(|new\s+Function\s*\(/, desc: "Tool uses dynamic code execution", severity: "critical" },
|
|
22
|
+
{ pattern: /\.ssh|\.aws|\.env\b|credentials|secret/i, desc: "Tool accesses sensitive paths/credentials", severity: "critical" },
|
|
23
|
+
];
|
|
24
|
+
// Suspicious tool name/description patterns
|
|
25
|
+
const SUSPICIOUS_TOOL_DESC = [
|
|
26
|
+
{ pattern: /run.*any.*command|execute.*arbitrary|shell.*access/i, desc: "Tool claims unrestricted command execution" },
|
|
27
|
+
{ pattern: /access.*all.*files|read.*entire.*filesystem/i, desc: "Tool claims full filesystem access" },
|
|
28
|
+
{ pattern: /send.*data.*to|upload.*to|transmit.*to/i, desc: "Tool description mentions data transmission" },
|
|
29
|
+
{ pattern: /modify.*system|change.*config/i, desc: "Tool claims system modification capability" },
|
|
30
|
+
];
|
|
31
|
+
export const mcpManifestRule = {
|
|
32
|
+
id: "mcp-manifest",
|
|
33
|
+
name: "MCP Server Validation",
|
|
34
|
+
description: "Validates MCP server tool/resource declarations against actual code behavior",
|
|
35
|
+
run(files) {
|
|
36
|
+
const findings = [];
|
|
37
|
+
// Detect if this is an MCP server project
|
|
38
|
+
const isMcpServer = detectMcpServer(files);
|
|
39
|
+
if (!isMcpServer)
|
|
40
|
+
return findings;
|
|
41
|
+
// Check for MCP manifest/config files
|
|
42
|
+
checkMcpConfig(files, findings);
|
|
43
|
+
// Analyze tool implementations for dangerous patterns
|
|
44
|
+
checkToolImplementations(files, findings);
|
|
45
|
+
// Check tool descriptions for suspicious claims
|
|
46
|
+
checkToolDescriptions(files, findings);
|
|
47
|
+
// Check if tools are registered but have no input validation
|
|
48
|
+
checkInputValidation(files, findings);
|
|
49
|
+
return findings;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
function detectMcpServer(files) {
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
// Check package.json for MCP-related deps
|
|
55
|
+
if (file.relativePath === "package.json") {
|
|
56
|
+
try {
|
|
57
|
+
const pkg = JSON.parse(file.content);
|
|
58
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
59
|
+
if (allDeps["@modelcontextprotocol/sdk"] ||
|
|
60
|
+
allDeps["@anthropic-ai/sdk"] ||
|
|
61
|
+
pkg.mcp) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// ignore parse errors
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Check for MCP imports in code
|
|
70
|
+
if (file.ext === ".ts" || file.ext === ".js" || file.ext === ".mjs") {
|
|
71
|
+
if (file.content.includes("@modelcontextprotocol/sdk") ||
|
|
72
|
+
file.content.includes("McpServer") ||
|
|
73
|
+
file.content.includes("createMcpServer") ||
|
|
74
|
+
TOOL_REGISTER_RE.test(file.content)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Check for mcp.json or similar config
|
|
79
|
+
if (file.relativePath === "mcp.json" ||
|
|
80
|
+
file.relativePath.endsWith("/mcp.json")) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function checkMcpConfig(files, findings) {
|
|
87
|
+
const mcpConfig = files.find((f) => f.relativePath === "mcp.json" || f.relativePath.endsWith("/mcp.json"));
|
|
88
|
+
if (mcpConfig) {
|
|
89
|
+
try {
|
|
90
|
+
const config = JSON.parse(mcpConfig.content);
|
|
91
|
+
// Check for overly broad permissions
|
|
92
|
+
if (config.permissions) {
|
|
93
|
+
const perms = Array.isArray(config.permissions)
|
|
94
|
+
? config.permissions
|
|
95
|
+
: Object.keys(config.permissions);
|
|
96
|
+
if (perms.length > 5) {
|
|
97
|
+
findings.push({
|
|
98
|
+
rule: "mcp-manifest",
|
|
99
|
+
severity: "warning",
|
|
100
|
+
file: mcpConfig.relativePath,
|
|
101
|
+
message: `MCP config declares ${perms.length} permissions — consider reducing scope`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Check for wildcard or dangerous permissions
|
|
106
|
+
const configStr = JSON.stringify(config);
|
|
107
|
+
if (configStr.includes('"*"') || configStr.includes('"all"')) {
|
|
108
|
+
findings.push({
|
|
109
|
+
rule: "mcp-manifest",
|
|
110
|
+
severity: "critical",
|
|
111
|
+
file: mcpConfig.relativePath,
|
|
112
|
+
message: "MCP config uses wildcard/all permissions",
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
findings.push({
|
|
118
|
+
rule: "mcp-manifest",
|
|
119
|
+
severity: "warning",
|
|
120
|
+
file: mcpConfig.relativePath,
|
|
121
|
+
message: "Invalid JSON in MCP config file",
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function checkToolImplementations(files, findings) {
|
|
127
|
+
const codeFiles = files.filter((f) => f.ext === ".ts" || f.ext === ".js" || f.ext === ".mjs" || f.ext === ".cjs");
|
|
128
|
+
for (const file of codeFiles) {
|
|
129
|
+
// Only check files that register tools
|
|
130
|
+
if (!TOOL_REGISTER_RE.test(file.content) && !RESOURCE_REGISTER_RE.test(file.content)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
134
|
+
const line = file.lines[i];
|
|
135
|
+
const trimmed = line.trimStart();
|
|
136
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*"))
|
|
137
|
+
continue;
|
|
138
|
+
for (const { pattern, desc, severity } of DANGEROUS_TOOL_PATTERNS) {
|
|
139
|
+
if (pattern.test(line)) {
|
|
140
|
+
findings.push({
|
|
141
|
+
rule: "mcp-manifest",
|
|
142
|
+
severity,
|
|
143
|
+
file: file.relativePath,
|
|
144
|
+
line: i + 1,
|
|
145
|
+
message: `MCP tool: ${desc}`,
|
|
146
|
+
evidence: line.trim().slice(0, 120),
|
|
147
|
+
});
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function checkToolDescriptions(files, findings) {
|
|
155
|
+
const codeFiles = files.filter((f) => f.ext === ".ts" || f.ext === ".js" || f.ext === ".mjs");
|
|
156
|
+
for (const file of codeFiles) {
|
|
157
|
+
// Look for tool description strings
|
|
158
|
+
for (let i = 0; i < file.lines.length; i++) {
|
|
159
|
+
const line = file.lines[i];
|
|
160
|
+
for (const { pattern, desc } of SUSPICIOUS_TOOL_DESC) {
|
|
161
|
+
if (pattern.test(line)) {
|
|
162
|
+
findings.push({
|
|
163
|
+
rule: "mcp-manifest",
|
|
164
|
+
severity: "warning",
|
|
165
|
+
file: file.relativePath,
|
|
166
|
+
line: i + 1,
|
|
167
|
+
message: `Suspicious MCP tool description: ${desc}`,
|
|
168
|
+
evidence: line.trim().slice(0, 120),
|
|
169
|
+
});
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function checkInputValidation(files, findings) {
|
|
177
|
+
const codeFiles = files.filter((f) => f.ext === ".ts" || f.ext === ".js" || f.ext === ".mjs");
|
|
178
|
+
for (const file of codeFiles) {
|
|
179
|
+
if (!TOOL_REGISTER_RE.test(file.content))
|
|
180
|
+
continue;
|
|
181
|
+
// Check for tools that accept path inputs without validation
|
|
182
|
+
const hasPathInput = /path|file|dir|folder/i.test(file.content);
|
|
183
|
+
const hasPathValidation = /sanitize|validate|allowlist|whitelist|isAbsolute|normalize|resolve/i.test(file.content);
|
|
184
|
+
const hasTraversalCheck = /\.\.\//i.test(file.content) || /path.*traversal/i.test(file.content);
|
|
185
|
+
if (hasPathInput && !hasPathValidation && !hasTraversalCheck) {
|
|
186
|
+
findings.push({
|
|
187
|
+
rule: "mcp-manifest",
|
|
188
|
+
severity: "warning",
|
|
189
|
+
file: file.relativePath,
|
|
190
|
+
message: "MCP tool accepts path inputs but has no visible path validation/sanitization",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=mcp-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-manifest.js","sourceRoot":"","sources":["../../src/rules/mcp-manifest.ts"],"names":[],"mappings":"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"}
|
package/dist/scanner/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { ScanResult } from "../types.js";
|
|
1
|
+
import type { ScanResult, ScanConfig } from "../types.js";
|
|
2
2
|
/** Run all rules against a target directory */
|
|
3
|
-
export declare function scan(targetDir: string): ScanResult;
|
|
3
|
+
export declare function scan(targetDir: string, configOverride?: Partial<ScanConfig>): ScanResult;
|
package/dist/scanner/index.js
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
1
|
import { collectFiles, totalLines } from "./files.js";
|
|
2
2
|
import { rules } from "../rules/index.js";
|
|
3
3
|
import { computeScore } from "../score.js";
|
|
4
|
+
import { loadConfig, loadIgnorePatterns, isIgnored } from "../config.js";
|
|
4
5
|
/** Run all rules against a target directory */
|
|
5
|
-
export function scan(targetDir) {
|
|
6
|
+
export function scan(targetDir, configOverride) {
|
|
6
7
|
const start = Date.now();
|
|
7
|
-
|
|
8
|
+
// Load config
|
|
9
|
+
const fileConfig = loadConfig(targetDir);
|
|
10
|
+
const config = { ...fileConfig, ...configOverride };
|
|
11
|
+
// Load ignore patterns
|
|
12
|
+
const ignorePatterns = loadIgnorePatterns(targetDir);
|
|
13
|
+
if (config.ignore) {
|
|
14
|
+
ignorePatterns.push(...config.ignore);
|
|
15
|
+
}
|
|
16
|
+
// Collect and filter files
|
|
17
|
+
let files = collectFiles(targetDir);
|
|
18
|
+
if (ignorePatterns.length > 0) {
|
|
19
|
+
files = files.filter((f) => !isIgnored(f.relativePath, ignorePatterns));
|
|
20
|
+
}
|
|
21
|
+
// Filter rules based on config
|
|
22
|
+
let activeRules = [...rules];
|
|
23
|
+
if (config.rules?.enable) {
|
|
24
|
+
activeRules = activeRules.filter((r) => config.rules.enable.includes(r.id));
|
|
25
|
+
}
|
|
26
|
+
if (config.rules?.disable) {
|
|
27
|
+
activeRules = activeRules.filter((r) => !config.rules.disable.includes(r.id));
|
|
28
|
+
}
|
|
29
|
+
// Run rules
|
|
8
30
|
const findings = [];
|
|
9
|
-
for (const rule of
|
|
31
|
+
for (const rule of activeRules) {
|
|
10
32
|
findings.push(...rule.run(files));
|
|
11
33
|
}
|
|
34
|
+
// Apply severity overrides
|
|
35
|
+
if (config.severity) {
|
|
36
|
+
for (const finding of findings) {
|
|
37
|
+
if (config.severity[finding.rule]) {
|
|
38
|
+
finding.severity = config.severity[finding.rule];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
12
42
|
// Sort: critical first, then warning, then info
|
|
13
43
|
const severityOrder = { critical: 0, warning: 1, info: 2 };
|
|
14
44
|
findings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -40,3 +40,13 @@ export interface SkillMetadata {
|
|
|
40
40
|
permissions?: string[];
|
|
41
41
|
[key: string]: unknown;
|
|
42
42
|
}
|
|
43
|
+
/** Scan configuration from .agentshield.yml */
|
|
44
|
+
export interface ScanConfig {
|
|
45
|
+
rules?: {
|
|
46
|
+
enable?: string[];
|
|
47
|
+
disable?: string[];
|
|
48
|
+
};
|
|
49
|
+
severity?: Record<string, "critical" | "warning" | "info">;
|
|
50
|
+
failUnder?: number;
|
|
51
|
+
ignore?: string[];
|
|
52
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal YAML parser for simple config files.
|
|
3
|
+
* Supports: scalars, lists, nested objects (2 levels deep).
|
|
4
|
+
* For complex YAML, use the 'yaml' package.
|
|
5
|
+
*/
|
|
6
|
+
export function parse(input) {
|
|
7
|
+
const result = {};
|
|
8
|
+
const lines = input.split("\n");
|
|
9
|
+
let currentKey = "";
|
|
10
|
+
let currentSubKey = "";
|
|
11
|
+
let currentList = null;
|
|
12
|
+
for (const rawLine of lines) {
|
|
13
|
+
// Skip comments and empty lines
|
|
14
|
+
const line = rawLine.replace(/#.*$/, "");
|
|
15
|
+
if (!line.trim())
|
|
16
|
+
continue;
|
|
17
|
+
const indent = rawLine.search(/\S/);
|
|
18
|
+
// List item
|
|
19
|
+
if (line.trim().startsWith("- ")) {
|
|
20
|
+
const value = line.trim().slice(2).trim().replace(/^["']|["']$/g, "");
|
|
21
|
+
if (currentList) {
|
|
22
|
+
currentList.push(value);
|
|
23
|
+
}
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
// Key: value
|
|
27
|
+
const match = line.match(/^(\s*)(\w+)\s*:\s*(.*)/);
|
|
28
|
+
if (!match)
|
|
29
|
+
continue;
|
|
30
|
+
const [, , key, rawValue] = match;
|
|
31
|
+
const value = rawValue.trim().replace(/^["']|["']$/g, "");
|
|
32
|
+
if (indent === 0) {
|
|
33
|
+
// Top-level key
|
|
34
|
+
if (currentList && currentKey) {
|
|
35
|
+
// Save previous list
|
|
36
|
+
if (currentSubKey) {
|
|
37
|
+
result[currentKey][currentSubKey] = currentList;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
result[currentKey] = currentList;
|
|
41
|
+
}
|
|
42
|
+
currentList = null;
|
|
43
|
+
currentSubKey = "";
|
|
44
|
+
}
|
|
45
|
+
currentKey = key;
|
|
46
|
+
if (value) {
|
|
47
|
+
// Scalar value
|
|
48
|
+
result[currentKey] = parseScalar(value);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Object or list follows
|
|
52
|
+
if (!result[currentKey] || typeof result[currentKey] !== "object") {
|
|
53
|
+
result[currentKey] = {};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (indent === 2 && currentKey) {
|
|
58
|
+
// Sub-key
|
|
59
|
+
if (currentList && currentSubKey) {
|
|
60
|
+
result[currentKey][currentSubKey] = currentList;
|
|
61
|
+
currentList = null;
|
|
62
|
+
}
|
|
63
|
+
currentSubKey = key;
|
|
64
|
+
if (value) {
|
|
65
|
+
if (typeof result[currentKey] !== "object")
|
|
66
|
+
result[currentKey] = {};
|
|
67
|
+
result[currentKey][currentSubKey] = parseScalar(value);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// List follows
|
|
71
|
+
currentList = [];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Save trailing list
|
|
76
|
+
if (currentList) {
|
|
77
|
+
if (currentSubKey && currentKey) {
|
|
78
|
+
if (typeof result[currentKey] !== "object")
|
|
79
|
+
result[currentKey] = {};
|
|
80
|
+
result[currentKey][currentSubKey] = currentList;
|
|
81
|
+
}
|
|
82
|
+
else if (currentKey) {
|
|
83
|
+
result[currentKey] = currentList;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function parseScalar(value) {
|
|
89
|
+
if (value === "true")
|
|
90
|
+
return true;
|
|
91
|
+
if (value === "false")
|
|
92
|
+
return false;
|
|
93
|
+
const num = Number(value);
|
|
94
|
+
if (!isNaN(num) && value !== "")
|
|
95
|
+
return num;
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=yaml-simple.js.map
|