awguard 1.5.0 → 1.7.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 (75) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/Dockerfile +15 -0
  3. package/README.md +230 -10
  4. package/action.yml +7 -3
  5. package/docs/assets/terminal-demo.svg +19 -0
  6. package/docs/comparison.md +168 -0
  7. package/docs/launch-plan.md +35 -17
  8. package/docs/market-analysis.md +3 -1
  9. package/docs/marketplace-listing.md +59 -0
  10. package/docs/npm-publishing.md +68 -0
  11. package/docs/release-checklist.md +71 -0
  12. package/docs/report-gallery.md +166 -0
  13. package/docs/roadmap.md +41 -7
  14. package/docs/rule-authoring.md +99 -0
  15. package/docs/schemas.md +16 -0
  16. package/docs/setup-recipes.md +199 -0
  17. package/docs/site/index.html +280 -0
  18. package/examples/.gitlab-ci.yml +6 -0
  19. package/examples/.vscode/tasks.json +33 -0
  20. package/examples/README.md +11 -0
  21. package/examples/awguard.config.example.json +14 -0
  22. package/examples/corpus/.cursor/rules/autonomy.mdc +3 -0
  23. package/examples/corpus/.github/prompts/auto-fix.prompt.md +3 -0
  24. package/examples/corpus/.github/workflows/agentic-pr-review.yml +20 -0
  25. package/examples/corpus/.github/workflows/pull-request-target-head.yml +13 -0
  26. package/examples/corpus/.mcp.json +15 -0
  27. package/examples/corpus/AGENTS.md +5 -0
  28. package/examples/corpus/README.md +23 -0
  29. package/examples/dashboard/README.md +55 -0
  30. package/examples/dashboard/index.html +313 -0
  31. package/examples/dashboard/sample-history.json +53 -0
  32. package/examples/lab/README.md +33 -0
  33. package/examples/lab/fixed/.github/workflows/ai-triage.yml +20 -0
  34. package/examples/lab/fixed/.mcp.json +12 -0
  35. package/examples/lab/fixed/AGENTS.md +5 -0
  36. package/examples/lab/unsafe/.github/workflows/ai-triage.yml +16 -0
  37. package/examples/lab/unsafe/.mcp.json +11 -0
  38. package/examples/lab/unsafe/AGENTS.md +4 -0
  39. package/examples/pr-comment-bot.yml +43 -0
  40. package/examples/pre-commit-config.yaml +8 -0
  41. package/examples/pull-request-target.yml +1 -1
  42. package/examples/safe-agent.yml +1 -1
  43. package/examples/unsafe-agent.yml +1 -1
  44. package/examples/vscode-extension/README.md +49 -0
  45. package/examples/vscode-extension/assets/problems-panel.svg +23 -0
  46. package/examples/vscode-extension/package.json +68 -0
  47. package/examples/vscode-extension/src/extension.js +116 -0
  48. package/package.json +3 -1
  49. package/schemas/awguard.badge.schema.json +25 -0
  50. package/schemas/awguard.baseline.schema.json +40 -0
  51. package/schemas/awguard.comparison.schema.json +146 -0
  52. package/schemas/awguard.config.schema.json +167 -0
  53. package/schemas/awguard.inventory.schema.json +124 -0
  54. package/schemas/awguard.report.schema.json +121 -0
  55. package/src/autofix.js +201 -0
  56. package/src/badges.js +63 -0
  57. package/src/baseline.js +77 -0
  58. package/src/cli.js +281 -5
  59. package/src/compare.js +166 -0
  60. package/src/config.js +58 -2
  61. package/src/demo.js +90 -0
  62. package/src/doctor.js +189 -0
  63. package/src/explain.js +147 -0
  64. package/src/graph.js +6 -1
  65. package/src/init.js +84 -0
  66. package/src/inventory.js +11 -0
  67. package/src/migration.js +10 -0
  68. package/src/policy-packs.js +99 -0
  69. package/src/policy-wizard.js +165 -0
  70. package/src/presets.js +2 -1
  71. package/src/remediation.js +92 -1
  72. package/src/reporters.js +92 -5
  73. package/src/scanner.js +295 -10
  74. package/src/score.js +3 -0
  75. package/src/templates.js +132 -0
@@ -0,0 +1,23 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="920" height="430" viewBox="0 0 920 430" role="img" aria-labelledby="title desc">
2
+ <title id="title">AWGuard VS Code Problems panel capture</title>
3
+ <desc id="desc">A mocked VS Code Problems panel showing AWGuard diagnostics for AGENTS.md and an MCP config.</desc>
4
+ <rect width="920" height="430" fill="#f6f8fb"/>
5
+ <rect x="28" y="28" width="864" height="374" rx="8" fill="#ffffff" stroke="#d7dee8"/>
6
+ <rect x="28" y="28" width="864" height="42" rx="8" fill="#17212b"/>
7
+ <text x="50" y="55" font-family="Arial, sans-serif" font-size="15" fill="#ffffff" font-weight="700">AWGuard: Problems</text>
8
+ <rect x="50" y="92" width="820" height="44" rx="6" fill="#fff7ed" stroke="#fed7aa"/>
9
+ <circle cx="72" cy="114" r="8" fill="#b42318"/>
10
+ <text x="90" y="111" font-family="Arial, sans-serif" font-size="14" fill="#17212b" font-weight="700">AWG012 Agent instruction file weakens review or permission boundaries</text>
11
+ <text x="90" y="128" font-family="Arial, sans-serif" font-size="12" fill="#5f6b76">AGENTS.md:3 - persistent instruction bypasses approval checks</text>
12
+ <rect x="50" y="148" width="820" height="44" rx="6" fill="#fff7ed" stroke="#fed7aa"/>
13
+ <circle cx="72" cy="170" r="8" fill="#b42318"/>
14
+ <text x="90" y="167" font-family="Arial, sans-serif" font-size="14" fill="#17212b" font-weight="700">AWG014 MCP config hardcodes secrets or auth material</text>
15
+ <text x="90" y="184" font-family="Arial, sans-serif" font-size="12" fill="#5f6b76">.mcp.json:7 - move tokens into prompt input or managed secrets</text>
16
+ <rect x="50" y="204" width="820" height="44" rx="6" fill="#eef8ff" stroke="#bfdbfe"/>
17
+ <circle cx="72" cy="226" r="8" fill="#0f766e"/>
18
+ <text x="90" y="223" font-family="Arial, sans-serif" font-size="14" fill="#17212b" font-weight="700">AWGuard scan completed</text>
19
+ <text x="90" y="240" font-family="Arial, sans-serif" font-size="12" fill="#5f6b76">2 diagnostics published to the VS Code Problems panel</text>
20
+ <rect x="50" y="282" width="820" height="78" rx="6" fill="#0c1117"/>
21
+ <text x="72" y="312" font-family="Menlo, Consolas, monospace" font-size="13" fill="#9ae6b4">$ npx awguard@latest . --format json --fail-on none</text>
22
+ <text x="72" y="334" font-family="Menlo, Consolas, monospace" font-size="13" fill="#c9d1d9">Scanned 6 file(s). Findings: 2 total, highest severity: critical.</text>
23
+ </svg>
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "awguard-vscode-poc",
3
+ "displayName": "AWGuard POC",
4
+ "description": "Run Agentic Workflow Guard from VS Code and show findings as diagnostics.",
5
+ "version": "0.0.1",
6
+ "publisher": "mughal-baig",
7
+ "license": "MIT",
8
+ "engines": {
9
+ "vscode": "^1.101.0"
10
+ },
11
+ "categories": [
12
+ "Linters",
13
+ "Other"
14
+ ],
15
+ "activationEvents": [
16
+ "onCommand:awguard.scanWorkspace"
17
+ ],
18
+ "main": "./src/extension.js",
19
+ "contributes": {
20
+ "commands": [
21
+ {
22
+ "command": "awguard.scanWorkspace",
23
+ "title": "AWGuard: Scan Workspace"
24
+ }
25
+ ],
26
+ "configuration": {
27
+ "title": "AWGuard",
28
+ "properties": {
29
+ "awguard.command": {
30
+ "type": "string",
31
+ "default": "npx",
32
+ "description": "Command used to run AWGuard."
33
+ },
34
+ "awguard.args": {
35
+ "type": "array",
36
+ "default": ["awguard@latest"],
37
+ "items": {
38
+ "type": "string"
39
+ },
40
+ "description": "Arguments prepended before the workspace path and output flags."
41
+ }
42
+ }
43
+ },
44
+ "problemMatchers": [
45
+ {
46
+ "name": "awguard",
47
+ "owner": "awguard",
48
+ "fileLocation": ["relative", "${workspaceFolder}"],
49
+ "pattern": [
50
+ {
51
+ "regexp": "^\\[(?:CRITICAL|HIGH|MEDIUM|LOW)\\] (AWG\\d+) (.*)$",
52
+ "severity": "warning",
53
+ "code": 1,
54
+ "message": 2
55
+ },
56
+ {
57
+ "regexp": "^\\s+(.+):(\\d+)$",
58
+ "file": 1,
59
+ "line": 2
60
+ }
61
+ ]
62
+ }
63
+ ]
64
+ },
65
+ "devDependencies": {
66
+ "@types/vscode": "^1.101.0"
67
+ }
68
+ }
@@ -0,0 +1,116 @@
1
+ const cp = require('node:child_process');
2
+ const path = require('node:path');
3
+ const vscode = require('vscode');
4
+
5
+ const severityMap = {
6
+ critical: vscode.DiagnosticSeverity.Error,
7
+ high: vscode.DiagnosticSeverity.Error,
8
+ medium: vscode.DiagnosticSeverity.Warning,
9
+ low: vscode.DiagnosticSeverity.Information
10
+ };
11
+
12
+ function activate(context) {
13
+ const output = vscode.window.createOutputChannel('AWGuard');
14
+ const diagnostics = vscode.languages.createDiagnosticCollection('awguard');
15
+
16
+ context.subscriptions.push(output, diagnostics);
17
+ context.subscriptions.push(
18
+ vscode.commands.registerCommand('awguard.scanWorkspace', async () => {
19
+ const folder = vscode.workspace.workspaceFolders?.[0];
20
+ if (!folder) {
21
+ vscode.window.showWarningMessage('Open a workspace before running AWGuard.');
22
+ return;
23
+ }
24
+
25
+ diagnostics.clear();
26
+ output.clear();
27
+ output.show(true);
28
+ output.appendLine(`Scanning ${folder.uri.fsPath}`);
29
+
30
+ try {
31
+ const report = await runAwguard(folder.uri.fsPath, output);
32
+ publishDiagnostics(report, folder.uri.fsPath, diagnostics);
33
+ vscode.window.showInformationMessage(`AWGuard found ${report.findings.length} finding(s).`);
34
+ } catch (error) {
35
+ vscode.window.showErrorMessage(`AWGuard scan failed: ${error.message}`);
36
+ }
37
+ })
38
+ );
39
+ }
40
+
41
+ function runAwguard(workspacePath, output) {
42
+ const config = vscode.workspace.getConfiguration('awguard');
43
+ const command = config.get('command', 'npx');
44
+ const configuredArgs = config.get('args', ['awguard@latest']);
45
+ const args = [...configuredArgs, workspacePath, '--format', 'json', '--fail-on', 'none'];
46
+ const executable = process.platform === 'win32' && command === 'npx' ? 'npx.cmd' : command;
47
+
48
+ return new Promise((resolve, reject) => {
49
+ const child = cp.spawn(executable, args, {
50
+ cwd: workspacePath,
51
+ shell: false,
52
+ windowsHide: true
53
+ });
54
+
55
+ let stdout = '';
56
+ let stderr = '';
57
+
58
+ child.stdout.on('data', (chunk) => {
59
+ stdout += chunk;
60
+ output.append(chunk.toString());
61
+ });
62
+
63
+ child.stderr.on('data', (chunk) => {
64
+ stderr += chunk;
65
+ output.append(chunk.toString());
66
+ });
67
+
68
+ child.on('error', reject);
69
+ child.on('close', (code) => {
70
+ if (code !== 0) {
71
+ reject(new Error(stderr.trim() || `awguard exited with code ${code}`));
72
+ return;
73
+ }
74
+
75
+ try {
76
+ resolve(JSON.parse(stdout));
77
+ } catch (error) {
78
+ reject(new Error(`could not parse AWGuard JSON output: ${error.message}`));
79
+ }
80
+ });
81
+ });
82
+ }
83
+
84
+ function publishDiagnostics(report, workspacePath, diagnostics) {
85
+ const byFile = new Map();
86
+
87
+ for (const finding of report.findings || []) {
88
+ const file = path.resolve(workspacePath, finding.file);
89
+ const uri = vscode.Uri.file(file);
90
+ const line = Math.max(0, (finding.line || 1) - 1);
91
+ const column = Math.max(0, (finding.column || 1) - 1);
92
+ const range = new vscode.Range(line, column, line, column + 1);
93
+ const diagnostic = new vscode.Diagnostic(
94
+ range,
95
+ `${finding.ruleId}: ${finding.title}\n${finding.message}\nFix: ${finding.suggestion}`,
96
+ severityMap[finding.severity] || vscode.DiagnosticSeverity.Warning
97
+ );
98
+ diagnostic.code = finding.ruleId;
99
+ diagnostic.source = 'AWGuard';
100
+
101
+ const existing = byFile.get(uri.toString()) || { uri, diagnostics: [] };
102
+ existing.diagnostics.push(diagnostic);
103
+ byFile.set(uri.toString(), existing);
104
+ }
105
+
106
+ for (const item of byFile.values()) {
107
+ diagnostics.set(item.uri, item.diagnostics);
108
+ }
109
+ }
110
+
111
+ function deactivate() {}
112
+
113
+ module.exports = {
114
+ activate,
115
+ deactivate
116
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "awguard",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Scan GitHub Actions workflows, agent instructions, and MCP configs for AI-agent injection and unsafe tool boundaries.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Mughal-Baig/agentic-workflow-guard#readme",
@@ -37,9 +37,11 @@
37
37
  },
38
38
  "files": [
39
39
  "action.yml",
40
+ "Dockerfile",
40
41
  "CHANGELOG.md",
41
42
  "bin",
42
43
  "src",
44
+ "schemas",
43
45
  "docs",
44
46
  "examples",
45
47
  "README.md",
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/Mughal-Baig/agentic-workflow-guard/main/schemas/awguard.badge.schema.json",
4
+ "title": "Agentic Workflow Guard Shields badge endpoint",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schemaVersion", "label", "message", "color"],
8
+ "properties": {
9
+ "schemaVersion": {
10
+ "const": 1
11
+ },
12
+ "label": {
13
+ "type": "string"
14
+ },
15
+ "message": {
16
+ "type": "string"
17
+ },
18
+ "color": {
19
+ "type": "string"
20
+ },
21
+ "namedLogo": {
22
+ "type": "string"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/Mughal-Baig/agentic-workflow-guard/main/schemas/awguard.baseline.schema.json",
4
+ "title": "Agentic Workflow Guard baseline",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "findings"],
8
+ "properties": {
9
+ "version": {
10
+ "const": 1
11
+ },
12
+ "findings": {
13
+ "type": "array",
14
+ "items": {
15
+ "type": "object",
16
+ "additionalProperties": false,
17
+ "required": ["fingerprint", "ruleId", "file", "line", "title"],
18
+ "properties": {
19
+ "fingerprint": {
20
+ "type": "string"
21
+ },
22
+ "ruleId": {
23
+ "type": "string",
24
+ "pattern": "^AWG[0-9]{3}$"
25
+ },
26
+ "file": {
27
+ "type": "string"
28
+ },
29
+ "line": {
30
+ "type": "integer",
31
+ "minimum": 1
32
+ },
33
+ "title": {
34
+ "type": "string"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,146 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/Mughal-Baig/agentic-workflow-guard/main/schemas/awguard.comparison.schema.json",
4
+ "title": "Agentic Workflow Guard comparison report",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "summary",
9
+ "introducedFindings",
10
+ "resolvedFindings",
11
+ "addedFiles",
12
+ "removedFiles",
13
+ "addedSurfaces",
14
+ "removedSurfaces"
15
+ ],
16
+ "properties": {
17
+ "summary": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "required": [
21
+ "previousFindings",
22
+ "currentFindings",
23
+ "introducedFindings",
24
+ "resolvedFindings",
25
+ "unchangedFindings",
26
+ "addedFiles",
27
+ "removedFiles",
28
+ "addedSurfaces",
29
+ "removedSurfaces"
30
+ ],
31
+ "properties": {
32
+ "previousFindings": {
33
+ "$ref": "#/$defs/count"
34
+ },
35
+ "currentFindings": {
36
+ "$ref": "#/$defs/count"
37
+ },
38
+ "introducedFindings": {
39
+ "$ref": "#/$defs/count"
40
+ },
41
+ "resolvedFindings": {
42
+ "$ref": "#/$defs/count"
43
+ },
44
+ "unchangedFindings": {
45
+ "$ref": "#/$defs/count"
46
+ },
47
+ "addedFiles": {
48
+ "$ref": "#/$defs/count"
49
+ },
50
+ "removedFiles": {
51
+ "$ref": "#/$defs/count"
52
+ },
53
+ "addedSurfaces": {
54
+ "$ref": "#/$defs/count"
55
+ },
56
+ "removedSurfaces": {
57
+ "$ref": "#/$defs/count"
58
+ }
59
+ }
60
+ },
61
+ "introducedFindings": {
62
+ "type": "array",
63
+ "items": {
64
+ "$ref": "#/$defs/finding"
65
+ }
66
+ },
67
+ "resolvedFindings": {
68
+ "type": "array",
69
+ "items": {
70
+ "$ref": "#/$defs/finding"
71
+ }
72
+ },
73
+ "addedFiles": {
74
+ "$ref": "#/$defs/fileList"
75
+ },
76
+ "removedFiles": {
77
+ "$ref": "#/$defs/fileList"
78
+ },
79
+ "addedSurfaces": {
80
+ "$ref": "#/$defs/surfaceList"
81
+ },
82
+ "removedSurfaces": {
83
+ "$ref": "#/$defs/surfaceList"
84
+ }
85
+ },
86
+ "$defs": {
87
+ "count": {
88
+ "type": "integer",
89
+ "minimum": 0
90
+ },
91
+ "fileList": {
92
+ "type": "array",
93
+ "items": {
94
+ "type": "string"
95
+ }
96
+ },
97
+ "surfaceList": {
98
+ "type": "array",
99
+ "items": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "required": ["surface", "label", "files"],
103
+ "properties": {
104
+ "surface": {
105
+ "type": "string",
106
+ "enum": ["github-workflow", "agent-context", "mcp-config", "other"]
107
+ },
108
+ "label": {
109
+ "type": "string"
110
+ },
111
+ "files": {
112
+ "$ref": "#/$defs/fileList"
113
+ }
114
+ }
115
+ }
116
+ },
117
+ "finding": {
118
+ "type": "object",
119
+ "additionalProperties": true,
120
+ "required": ["ruleId", "severity", "file", "line", "title"],
121
+ "properties": {
122
+ "ruleId": {
123
+ "type": "string",
124
+ "pattern": "^AWG[0-9]{3}$"
125
+ },
126
+ "severity": {
127
+ "type": "string",
128
+ "enum": ["low", "medium", "high", "critical"]
129
+ },
130
+ "file": {
131
+ "type": "string"
132
+ },
133
+ "line": {
134
+ "type": "integer",
135
+ "minimum": 1
136
+ },
137
+ "title": {
138
+ "type": "string"
139
+ },
140
+ "fingerprint": {
141
+ "type": "string"
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,167 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/Mughal-Baig/agentic-workflow-guard/main/schemas/awguard.config.schema.json",
4
+ "title": "Agentic Workflow Guard configuration",
5
+ "description": "Configuration for AWGuard rule severities, presets, suppression policy, and reviewed agentic surface allowlists.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "$schema": {
10
+ "type": "string"
11
+ },
12
+ "extends": {
13
+ "description": "Built-in preset name or list of preset names to merge before local settings.",
14
+ "oneOf": [
15
+ {
16
+ "$ref": "#/$defs/preset"
17
+ },
18
+ {
19
+ "type": "array",
20
+ "items": {
21
+ "$ref": "#/$defs/preset"
22
+ },
23
+ "uniqueItems": true
24
+ }
25
+ ]
26
+ },
27
+ "rules": {
28
+ "type": "object",
29
+ "description": "Rule severity overrides. Use \"off\" to disable a rule.",
30
+ "additionalProperties": false,
31
+ "patternProperties": {
32
+ "^AWG(00[1-9]|01[0-9])$": {
33
+ "oneOf": [
34
+ {
35
+ "$ref": "#/$defs/ruleSeverity"
36
+ },
37
+ {
38
+ "type": "object",
39
+ "additionalProperties": false,
40
+ "required": ["severity"],
41
+ "properties": {
42
+ "severity": {
43
+ "$ref": "#/$defs/ruleSeverity"
44
+ }
45
+ }
46
+ }
47
+ ]
48
+ }
49
+ }
50
+ },
51
+ "suppressions": {
52
+ "type": "object",
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "allow": {
56
+ "type": "boolean",
57
+ "description": "Set false to report every awguard-disable comment as invalid."
58
+ },
59
+ "allowedRules": {
60
+ "type": "array",
61
+ "description": "Optional list of rule IDs that may be suppressed inline.",
62
+ "items": {
63
+ "$ref": "#/$defs/ruleId"
64
+ },
65
+ "uniqueItems": true
66
+ },
67
+ "minimumReasonLength": {
68
+ "type": "integer",
69
+ "minimum": 1,
70
+ "description": "Minimum characters required after the suppression reason separator."
71
+ }
72
+ }
73
+ },
74
+ "scan": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "properties": {
78
+ "include": {
79
+ "$ref": "#/$defs/stringList",
80
+ "description": "Optional glob-style file patterns that narrow discovered AWGuard scan files."
81
+ },
82
+ "exclude": {
83
+ "$ref": "#/$defs/stringList",
84
+ "description": "Optional glob-style file patterns removed from discovered AWGuard scan files."
85
+ },
86
+ "maxFiles": {
87
+ "type": "integer",
88
+ "minimum": 1,
89
+ "description": "Optional cap on the number of discovered scan files."
90
+ },
91
+ "maxFileBytes": {
92
+ "type": "integer",
93
+ "minimum": 1,
94
+ "description": "Optional cap on the byte size of each scanned file."
95
+ }
96
+ }
97
+ },
98
+ "policy": {
99
+ "type": "object",
100
+ "additionalProperties": false,
101
+ "properties": {
102
+ "approvedFiles": {
103
+ "$ref": "#/$defs/stringList",
104
+ "description": "Reviewed workflow, instruction, prompt, skill, and MCP config files. Glob-style * suffixes are supported by AWGuard."
105
+ },
106
+ "approvedMcpServers": {
107
+ "$ref": "#/$defs/stringList",
108
+ "description": "Reviewed MCP server names."
109
+ },
110
+ "approvedMcpPackages": {
111
+ "$ref": "#/$defs/stringList",
112
+ "description": "Reviewed MCP package or container specs, preferably pinned to exact versions or digests."
113
+ },
114
+ "approvedMcpPackageScopes": {
115
+ "$ref": "#/$defs/stringList",
116
+ "description": "Reviewed npm package scopes or prefixes for optional offline MCP package reputation checks, for example @modelcontextprotocol/."
117
+ },
118
+ "approvedMcpCommands": {
119
+ "$ref": "#/$defs/stringList",
120
+ "description": "Reviewed MCP launch commands such as node, npx, uvx, or docker."
121
+ }
122
+ }
123
+ }
124
+ },
125
+ "$defs": {
126
+ "preset": {
127
+ "type": "string",
128
+ "enum": ["strict", "claude-code", "codex", "aider", "triage-bot"]
129
+ },
130
+ "ruleId": {
131
+ "type": "string",
132
+ "enum": [
133
+ "AWG001",
134
+ "AWG002",
135
+ "AWG003",
136
+ "AWG004",
137
+ "AWG005",
138
+ "AWG006",
139
+ "AWG007",
140
+ "AWG008",
141
+ "AWG009",
142
+ "AWG010",
143
+ "AWG011",
144
+ "AWG012",
145
+ "AWG013",
146
+ "AWG014",
147
+ "AWG015",
148
+ "AWG016",
149
+ "AWG017",
150
+ "AWG018",
151
+ "AWG019"
152
+ ]
153
+ },
154
+ "ruleSeverity": {
155
+ "type": "string",
156
+ "enum": ["off", "low", "medium", "high", "critical"]
157
+ },
158
+ "stringList": {
159
+ "type": "array",
160
+ "items": {
161
+ "type": "string",
162
+ "minLength": 1
163
+ },
164
+ "uniqueItems": true
165
+ }
166
+ }
167
+ }