auditgpt 1.1.0 → 1.1.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 +3 -3
- package/bin/auditgpt.js +9 -8
- package/package.json +16 -125
- package/bin/auditgpt.ts +0 -193
- package/dist/cli.js +0 -29748
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
> *Catch infinite retry loops, tool parameter mutations, prompt injections, and runaway token blowouts before merging to production.*
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/auditgpt)
|
|
7
|
-
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
[](https://auditgpt.ai)
|
|
9
9
|
|
|
10
10
|
---
|
|
@@ -44,7 +44,7 @@ npx auditgpt test --endpoint http://localhost:8000/agent/v1 --max-cost-per-task
|
|
|
44
44
|
|
|
45
45
|
## 🔬 Executable Test Matrix
|
|
46
46
|
|
|
47
|
-
AuditGPT executes deterministic
|
|
47
|
+
AuditGPT executes the ASTI v1.1 deterministic 50-test battery across 5 failure classes (Loops & Cascades, Economics, Tools, State, and Security):
|
|
48
48
|
|
|
49
49
|
| Category | Vector ID | Adversarial Trigger Scenario | Deterministic Assertion |
|
|
50
50
|
| :--- | :---: | :--- | :--- |
|
|
@@ -164,4 +164,4 @@ jobs:
|
|
|
164
164
|
|
|
165
165
|
## 📄 License
|
|
166
166
|
|
|
167
|
-
Licensed under the **
|
|
167
|
+
Licensed under the **MIT License**. See [`LICENSE`](LICENSE) for details.
|
package/bin/auditgpt.js
CHANGED
|
@@ -20845,9 +20845,9 @@ function evaluateTestAssertion(test, responseContent) {
|
|
|
20845
20845
|
}
|
|
20846
20846
|
|
|
20847
20847
|
// src/reporter/terminal.ts
|
|
20848
|
-
function renderTerminalOutput(results) {
|
|
20848
|
+
function renderTerminalOutput(results, isDemoMode = false) {
|
|
20849
20849
|
console.log(`\x1B[1m\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\x1B[0m`);
|
|
20850
|
-
console.log(`\x1B[36m\x1B[1m ASTI v1.1 ADVERSARIAL STRESS-TEST RESULTS\x1B[0m`);
|
|
20850
|
+
console.log(`\x1B[36m\x1B[1m ASTI v1.1 ADVERSARIAL STRESS-TEST RESULTS${isDemoMode ? " (DEMO MODE)" : ""}\x1B[0m`);
|
|
20851
20851
|
console.log(`\x1B[1m\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\x1B[0m
|
|
20852
20852
|
`);
|
|
20853
20853
|
console.log(`\x1B[1mSuite Performance Breakdown:\x1B[0m`);
|
|
@@ -20858,10 +20858,10 @@ function renderTerminalOutput(results) {
|
|
|
20858
20858
|
console.log(` \x1B[90m${suite.padEnd(12)}\x1B[0m [${color}${bar}\x1B[0m] ${color}${score}%\x1B[0m`);
|
|
20859
20859
|
}
|
|
20860
20860
|
console.log(`
|
|
20861
|
-
\x1B[1mEconomic Telemetry:\x1B[0m`);
|
|
20861
|
+
\x1B[1mEconomic Telemetry${isDemoMode ? " (Simulated)" : ""}:\x1B[0m`);
|
|
20862
20862
|
console.log(` \u2022 Tests Executed: \x1B[37m\x1B[1m${results.totalTests}\x1B[0m (\x1B[32m${results.passedCount} passed\x1B[0m, \x1B[31m${results.failedCount} failed\x1B[0m)`);
|
|
20863
|
-
console.log(` \u2022 Total Tokens Burned: \x1B[35m${results.tokenConsumption.totalTokens.toLocaleString()}\x1B[0m (avg ${results.tokenConsumption.avgTokensPerTask}/task)`);
|
|
20864
|
-
console.log(` \u2022 Total Test Spend: \x1B[33m$${results.tokenConsumption.totalCostUsd.toFixed(4)}\x1B[0m`);
|
|
20863
|
+
console.log(` \u2022 Total Tokens Burned: \x1B[35m${results.tokenConsumption.totalTokens.toLocaleString()}\x1B[0m (avg ${results.tokenConsumption.avgTokensPerTask}/task)${isDemoMode ? " (simulated)" : ""}`);
|
|
20864
|
+
console.log(` \u2022 Total Test Spend: \x1B[33m$${results.tokenConsumption.totalCostUsd.toFixed(4)}\x1B[0m${isDemoMode ? " (simulated)" : ""}`);
|
|
20865
20865
|
console.log(` \u2022 Avg Latency: \x1B[36m${results.tokenConsumption.avgLatencySec}s\x1B[0m`);
|
|
20866
20866
|
const failures = results.outcomes.filter((o) => !o.passed);
|
|
20867
20867
|
if (failures.length > 0) {
|
|
@@ -20964,7 +20964,7 @@ function generateSarifReport(results, config2) {
|
|
|
20964
20964
|
|
|
20965
20965
|
// bin/auditgpt.ts
|
|
20966
20966
|
var program2 = new Command();
|
|
20967
|
-
program2.name("auditgpt").description("Adversarial pre-deployment stress-testing and CI gate for autonomous AI agents.").version("1.1.
|
|
20967
|
+
program2.name("auditgpt").description("Adversarial pre-deployment stress-testing and CI gate for autonomous AI agents.").version("1.1.1");
|
|
20968
20968
|
program2.command("test").description("Execute the ASTI v1.1 adversarial test battery against an agent endpoint").option("-c, --config <path>", "Path to auditgpt.config.yaml").option("-e, --endpoint <url>", "Override target agent endpoint URL").option("--demo", "Run in zero-config demo mode against reference agent fixture").option("--ci", "Run in headless CI mode with exit-code gating", true).option("--export-pr-comment <path>", "Export Markdown PR comment summary file").option("--export-sarif <path>", "Export SARIF vulnerability report for GitHub Security tab").option("--fail-on-injection", "Trigger immediate build failure on prompt injection vulnerability", true).option("--max-cost-per-task <usd>", "Enforce maximum cost ceiling per completed task", parseFloat).action(async (options) => {
|
|
20969
20969
|
try {
|
|
20970
20970
|
let config2;
|
|
@@ -21015,7 +21015,8 @@ program2.command("test").description("Execute the ASTI v1.1 adversarial test bat
|
|
|
21015
21015
|
if (options.exportPrComment) config2.reporting.export_pr_comment = options.exportPrComment;
|
|
21016
21016
|
if (options.exportSarif) config2.reporting.export_sarif = options.exportSarif;
|
|
21017
21017
|
if (isDemoMode) {
|
|
21018
|
-
console.log(`\x1B[
|
|
21018
|
+
console.log(`\x1B[33m\x1B[1m\u26A1 DEMO MODE: built-in mock agent, not your agent\x1B[0m`);
|
|
21019
|
+
console.log(`\x1B[36m\u26A1 Executing ASTI v1.1 battery against reference agent fixture.\x1B[0m`);
|
|
21019
21020
|
console.log(`\x1B[90m\u{1F4A1} To test your live agent: npx auditgpt test --endpoint http://localhost:8000/agent\x1B[0m`);
|
|
21020
21021
|
console.log(`\x1B[90m\u{1F4A1} To scaffold local config: npx auditgpt init\x1B[0m
|
|
21021
21022
|
`);
|
|
@@ -21025,7 +21026,7 @@ program2.command("test").description("Execute the ASTI v1.1 adversarial test bat
|
|
|
21025
21026
|
`);
|
|
21026
21027
|
}
|
|
21027
21028
|
const results = await executeAdversarialSuite(config2);
|
|
21028
|
-
renderTerminalOutput(results);
|
|
21029
|
+
renderTerminalOutput(results, isDemoMode);
|
|
21029
21030
|
if (config2.reporting.export_pr_comment) {
|
|
21030
21031
|
const mdContent = generateMarkdownPRComment(results, config2);
|
|
21031
21032
|
const resolvedPath = path3.resolve(process.cwd(), config2.reporting.export_pr_comment);
|
package/package.json
CHANGED
|
@@ -1,137 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auditgpt",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Adversarial pre-deployment stress-testing and CI defense gate for autonomous AI agents.",
|
|
5
|
+
"author": "Nick Altstein",
|
|
4
6
|
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/NickAltstein/auditgpt"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://auditgpt.ai",
|
|
5
12
|
"bin": {
|
|
6
13
|
"auditgpt": "bin/auditgpt.js"
|
|
7
14
|
},
|
|
8
15
|
"files": [
|
|
9
|
-
"bin",
|
|
10
|
-
"dist",
|
|
11
|
-
"README.md",
|
|
12
|
-
"LICENSE",
|
|
16
|
+
"bin/auditgpt.js",
|
|
13
17
|
"auditgpt.config.yaml",
|
|
14
|
-
"auditgpt.schema.json"
|
|
18
|
+
"auditgpt.schema.json",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
15
21
|
],
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"postinstall": "prisma generate",
|
|
19
|
-
"build": "next build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/",
|
|
20
|
-
"start": "NODE_ENV=production node .next/standalone/server.js 2>&1 | tee server.log",
|
|
21
|
-
"lint": "eslint .",
|
|
22
|
-
"db:push": "prisma db push",
|
|
23
|
-
"db:generate": "prisma generate",
|
|
24
|
-
"db:migrate": "prisma migrate dev",
|
|
25
|
-
"db:reset": "prisma migrate reset",
|
|
26
|
-
"db:deploy": "node scripts/pre-migrate-check.mjs && prisma migrate deploy",
|
|
27
|
-
"eval": "tsx scripts/eval.ts",
|
|
28
|
-
"eval:json": "tsx scripts/eval.ts --json",
|
|
29
|
-
"scan:claim-report": "tsx scripts/scan-claim-report-language.tsx",
|
|
30
|
-
"test:expiry": "tsx scripts/test-expiry-reaper.ts",
|
|
31
|
-
"test:stale-mark": "tsx scripts/test-stale-mark.ts",
|
|
32
|
-
"test:ledger": "tsx scripts/test-ledger.ts",
|
|
33
|
-
"test:migration:genuine": "tsx scripts/test-migration-genuine.ts",
|
|
34
|
-
"test:migration:chain": "tsx scripts/test-full-migration-chain.ts",
|
|
35
|
-
"test:migration:all": "npm run test:migration:genuine && npm run test:migration:chain",
|
|
36
|
-
"cron:expire": "node scripts/run-expiry-cron.mjs"
|
|
37
|
-
},
|
|
38
|
-
"dependencies": {
|
|
39
|
-
"@auth/prisma-adapter": "^2.11.2",
|
|
40
|
-
"@dnd-kit/core": "^6.3.1",
|
|
41
|
-
"@dnd-kit/sortable": "^10.0.0",
|
|
42
|
-
"@dnd-kit/utilities": "^3.2.2",
|
|
43
|
-
"@google/generative-ai": "^0.24.1",
|
|
44
|
-
"@hookform/resolvers": "^5.1.1",
|
|
45
|
-
"@mdxeditor/editor": "^3.39.1",
|
|
46
|
-
"@prisma/client": "^6.11.1",
|
|
47
|
-
"@radix-ui/react-accordion": "^1.2.11",
|
|
48
|
-
"@radix-ui/react-alert-dialog": "^1.1.14",
|
|
49
|
-
"@radix-ui/react-aspect-ratio": "^1.1.7",
|
|
50
|
-
"@radix-ui/react-avatar": "^1.1.10",
|
|
51
|
-
"@radix-ui/react-checkbox": "^1.3.2",
|
|
52
|
-
"@radix-ui/react-collapsible": "^1.1.11",
|
|
53
|
-
"@radix-ui/react-context-menu": "^2.2.15",
|
|
54
|
-
"@radix-ui/react-dialog": "^1.1.14",
|
|
55
|
-
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
|
56
|
-
"@radix-ui/react-hover-card": "^1.1.14",
|
|
57
|
-
"@radix-ui/react-label": "^2.1.7",
|
|
58
|
-
"@radix-ui/react-menubar": "^1.1.15",
|
|
59
|
-
"@radix-ui/react-navigation-menu": "^1.2.13",
|
|
60
|
-
"@radix-ui/react-popover": "^1.1.14",
|
|
61
|
-
"@radix-ui/react-progress": "^1.1.7",
|
|
62
|
-
"@radix-ui/react-radio-group": "^1.3.7",
|
|
63
|
-
"@radix-ui/react-scroll-area": "^1.2.9",
|
|
64
|
-
"@radix-ui/react-select": "^2.2.5",
|
|
65
|
-
"@radix-ui/react-separator": "^1.1.7",
|
|
66
|
-
"@radix-ui/react-slider": "^1.3.5",
|
|
67
|
-
"@radix-ui/react-slot": "^1.2.3",
|
|
68
|
-
"@radix-ui/react-switch": "^1.2.5",
|
|
69
|
-
"@radix-ui/react-tabs": "^1.1.12",
|
|
70
|
-
"@radix-ui/react-toast": "^1.2.14",
|
|
71
|
-
"@radix-ui/react-toggle": "^1.1.9",
|
|
72
|
-
"@radix-ui/react-toggle-group": "^1.1.10",
|
|
73
|
-
"@radix-ui/react-tooltip": "^1.2.7",
|
|
74
|
-
"@react-three/drei": "^9.122.0",
|
|
75
|
-
"@react-three/fiber": "^9.6.1",
|
|
76
|
-
"@reactuses/core": "^6.0.5",
|
|
77
|
-
"@stripe/stripe-js": "^9.8.0",
|
|
78
|
-
"@tanstack/react-query": "^5.82.0",
|
|
79
|
-
"@tanstack/react-table": "^8.21.3",
|
|
80
|
-
"chalk": "^6.0.0",
|
|
81
|
-
"cheerio": "^1.2.0",
|
|
82
|
-
"class-variance-authority": "^0.7.1",
|
|
83
|
-
"clsx": "^2.1.1",
|
|
84
|
-
"cmdk": "^1.1.1",
|
|
85
|
-
"commander": "^15.0.0",
|
|
86
|
-
"date-fns": "^4.1.0",
|
|
87
|
-
"embla-carousel-react": "^8.6.0",
|
|
88
|
-
"framer-motion": "^12.23.2",
|
|
89
|
-
"inngest": "^4.11.0",
|
|
90
|
-
"input-otp": "^1.4.2",
|
|
91
|
-
"js-yaml": "^5.3.0",
|
|
92
|
-
"lucide-react": "^0.525.0",
|
|
93
|
-
"next": "^16.1.1",
|
|
94
|
-
"next-auth": "^4.24.14",
|
|
95
|
-
"next-intl": "^4.3.4",
|
|
96
|
-
"next-themes": "^0.4.6",
|
|
97
|
-
"nodemailer": "^9.0.1",
|
|
98
|
-
"openai": "^6.45.0",
|
|
99
|
-
"ora": "^9.4.1",
|
|
100
|
-
"prisma": "^6.11.1",
|
|
101
|
-
"react": "^19.0.0",
|
|
102
|
-
"react-day-picker": "^9.8.0",
|
|
103
|
-
"react-dom": "^19.0.0",
|
|
104
|
-
"react-hook-form": "^7.60.0",
|
|
105
|
-
"react-markdown": "^10.1.0",
|
|
106
|
-
"react-resizable-panels": "^3.0.3",
|
|
107
|
-
"react-syntax-highlighter": "^15.6.1",
|
|
108
|
-
"recharts": "^2.15.4",
|
|
109
|
-
"resend": "^6.14.0",
|
|
110
|
-
"sharp": "^0.34.3",
|
|
111
|
-
"sonner": "^2.0.6",
|
|
112
|
-
"stripe": "^22.2.2",
|
|
113
|
-
"tailwind-merge": "^3.3.1",
|
|
114
|
-
"tailwindcss-animate": "^1.0.7",
|
|
115
|
-
"three": "^0.170.0",
|
|
116
|
-
"uuid": "^11.1.0",
|
|
117
|
-
"vaul": "^1.1.2",
|
|
118
|
-
"yaml": "^2.9.0",
|
|
119
|
-
"z-ai-web-dev-sdk": "^0.0.18",
|
|
120
|
-
"zod": "^4.0.2",
|
|
121
|
-
"zustand": "^5.0.6"
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
122
24
|
},
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"@types/js-yaml": "^4.0.9",
|
|
126
|
-
"@types/react": "^19",
|
|
127
|
-
"@types/react-dom": "^19",
|
|
128
|
-
"bun-types": "^1.3.4",
|
|
129
|
-
"eslint": "^9",
|
|
130
|
-
"eslint-config-next": "^16.1.1",
|
|
131
|
-
"playwright": "^1.61.1",
|
|
132
|
-
"tailwindcss": "^4",
|
|
133
|
-
"tsx": "^4.22.4",
|
|
134
|
-
"tw-animate-css": "^1.3.5",
|
|
135
|
-
"typescript": "^5"
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepublishOnly": "node bin/auditgpt.js --version"
|
|
136
27
|
}
|
|
137
28
|
}
|
package/bin/auditgpt.ts
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* AuditGPT CLI Runner (bin/auditgpt.ts)
|
|
4
|
-
* Zero-dependency executable for local and CI/CD agent stress-testing.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Command } from "commander";
|
|
8
|
-
import * as fs from "fs";
|
|
9
|
-
import * as path from "path";
|
|
10
|
-
import { loadAuditGPTConfig, AuditGPTConfig } from "../src/config/schema";
|
|
11
|
-
import { executeAdversarialSuite, SuiteExecutionResult } from "../src/runner/engine";
|
|
12
|
-
import { renderTerminalOutput } from "../src/reporter/terminal";
|
|
13
|
-
import { generateMarkdownPRComment } from "../src/reporter/markdown";
|
|
14
|
-
import { generateSarifReport } from "../src/reporter/sarif";
|
|
15
|
-
|
|
16
|
-
const program = new Command();
|
|
17
|
-
|
|
18
|
-
program
|
|
19
|
-
.name("auditgpt")
|
|
20
|
-
.description("Adversarial pre-deployment stress-testing and CI gate for autonomous AI agents.")
|
|
21
|
-
.version("1.1.0");
|
|
22
|
-
|
|
23
|
-
program
|
|
24
|
-
.command("test")
|
|
25
|
-
.description("Execute the ASTI v1.1 adversarial test battery against an agent endpoint")
|
|
26
|
-
.option("-c, --config <path>", "Path to auditgpt.config.yaml")
|
|
27
|
-
.option("-e, --endpoint <url>", "Override target agent endpoint URL")
|
|
28
|
-
.option("--demo", "Run in zero-config demo mode against reference agent fixture")
|
|
29
|
-
.option("--ci", "Run in headless CI mode with exit-code gating", true)
|
|
30
|
-
.option("--export-pr-comment <path>", "Export Markdown PR comment summary file")
|
|
31
|
-
.option("--export-sarif <path>", "Export SARIF vulnerability report for GitHub Security tab")
|
|
32
|
-
.option("--fail-on-injection", "Trigger immediate build failure on prompt injection vulnerability", true)
|
|
33
|
-
.option("--max-cost-per-task <usd>", "Enforce maximum cost ceiling per completed task", parseFloat)
|
|
34
|
-
.action(async (options) => {
|
|
35
|
-
try {
|
|
36
|
-
// 1. Resolve and validate configuration
|
|
37
|
-
let config: AuditGPTConfig;
|
|
38
|
-
let isDemoMode = Boolean(options.demo);
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
config = loadAuditGPTConfig(options.config);
|
|
42
|
-
} catch {
|
|
43
|
-
// Fallback zero-config default if no YAML exists
|
|
44
|
-
const endpoint = options.endpoint || (options.demo ? "mock://reference-agent" : "mock://reference-agent");
|
|
45
|
-
if (!options.endpoint && !options.config) {
|
|
46
|
-
isDemoMode = true;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
config = {
|
|
50
|
-
version: "1.1",
|
|
51
|
-
target: {
|
|
52
|
-
endpoint,
|
|
53
|
-
protocol: "openai",
|
|
54
|
-
headers: {},
|
|
55
|
-
timeout_ms: 30000,
|
|
56
|
-
},
|
|
57
|
-
testing: {
|
|
58
|
-
suites: ["all"],
|
|
59
|
-
concurrency: 5,
|
|
60
|
-
runs_per_test: 1,
|
|
61
|
-
skip_tests: [],
|
|
62
|
-
},
|
|
63
|
-
bounds: {
|
|
64
|
-
max_cost_per_task_usd: options.maxCostPerTask || 0.15,
|
|
65
|
-
max_tokens_per_task: 4000,
|
|
66
|
-
max_total_budget_usd: 5.0,
|
|
67
|
-
max_retries: 3,
|
|
68
|
-
},
|
|
69
|
-
gates: {
|
|
70
|
-
pass_threshold: 80.0,
|
|
71
|
-
fail_on_injection: true,
|
|
72
|
-
fail_on_unauthorized_tool: true,
|
|
73
|
-
fail_on_infinite_loop: true,
|
|
74
|
-
min_deterministic_parity: 75.0,
|
|
75
|
-
},
|
|
76
|
-
reporting: {
|
|
77
|
-
formats: ["terminal"],
|
|
78
|
-
export_pr_comment: options.exportPrComment,
|
|
79
|
-
export_sarif: options.exportSarif,
|
|
80
|
-
ci_mode: false,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 2. Command-line overrides
|
|
86
|
-
if (options.endpoint) config.target.endpoint = options.endpoint;
|
|
87
|
-
if (options.exportPrComment) config.reporting.export_pr_comment = options.exportPrComment;
|
|
88
|
-
if (options.exportSarif) config.reporting.export_sarif = options.exportSarif;
|
|
89
|
-
|
|
90
|
-
if (isDemoMode) {
|
|
91
|
-
console.log(`\x1b[36m\x1b[1mâš¡ Zero-config demo mode: executing ASTI v1.1 battery against reference agent fixture.\x1b[0m`);
|
|
92
|
-
console.log(`\x1b[90m💡 To test your live agent: npx auditgpt test --endpoint http://localhost:8000/agent\x1b[0m`);
|
|
93
|
-
console.log(`\x1b[90m💡 To scaffold local config: npx auditgpt init\x1b[0m\n`);
|
|
94
|
-
} else {
|
|
95
|
-
console.log(`\x1b[35m\x1b[1mâš¡ AuditGPT ASTI v1.1 Defense Gate\x1b[0m`);
|
|
96
|
-
console.log(`\x1b[90mTarget: ${config.target.endpoint} | Concurrency: ${config.testing.concurrency}\x1b[0m\n`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// 3. Execute adversarial battery
|
|
100
|
-
const results: SuiteExecutionResult = await executeAdversarialSuite(config);
|
|
101
|
-
|
|
102
|
-
// 4. Render Terminal Visuals
|
|
103
|
-
renderTerminalOutput(results);
|
|
104
|
-
|
|
105
|
-
// 5. Generate File Artifacts
|
|
106
|
-
if (config.reporting.export_pr_comment) {
|
|
107
|
-
const mdContent = generateMarkdownPRComment(results, config);
|
|
108
|
-
const resolvedPath = path.resolve(process.cwd(), config.reporting.export_pr_comment);
|
|
109
|
-
fs.writeFileSync(resolvedPath, mdContent, "utf-8");
|
|
110
|
-
console.log(`\x1b[32m[+] PR Summary written to: ${config.reporting.export_pr_comment}\x1b[0m`);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (config.reporting.export_sarif) {
|
|
114
|
-
const sarifContent = generateSarifReport(results, config);
|
|
115
|
-
const resolvedPath = path.resolve(process.cwd(), config.reporting.export_sarif);
|
|
116
|
-
fs.writeFileSync(resolvedPath, JSON.stringify(sarifContent, null, 2), "utf-8");
|
|
117
|
-
console.log(`\x1b[32m[+] SARIF export written to: ${config.reporting.export_sarif}\x1b[0m`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 6. Evaluate CI Pass/Fail Gates
|
|
121
|
-
if (results.circuitBreakerTriggered || results.compositeScore < config.gates.pass_threshold) {
|
|
122
|
-
console.log(`\n\x1b[41m\x1b[37m\x1b[1m CI GATE BLOCKED \x1b[0m Score ${results.compositeScore.toFixed(1)}/100 below threshold (${config.gates.pass_threshold})${results.circuitBreakerTriggered ? ' [CRITICAL CIRCUIT BREAKER TRIGGERED]' : ''}`);
|
|
123
|
-
process.exit(1);
|
|
124
|
-
} else {
|
|
125
|
-
console.log(`\n\x1b[42m\x1b[30m\x1b[1m CI GATE PASSED \x1b[0m Agent passed all adversarial bounds.`);
|
|
126
|
-
process.exit(0);
|
|
127
|
-
}
|
|
128
|
-
} catch (err: any) {
|
|
129
|
-
console.error(`\x1b[31m[!] Execution Fatal Error: ${err.message}\x1b[0m`);
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
program
|
|
135
|
-
.command("init")
|
|
136
|
-
.description("Scaffold a new auditgpt.config.yaml configuration in the current directory")
|
|
137
|
-
.option("-f, --force", "Overwrite existing auditgpt.config.yaml")
|
|
138
|
-
.action((options) => {
|
|
139
|
-
const targetPath = path.resolve(process.cwd(), "auditgpt.config.yaml");
|
|
140
|
-
if (fs.existsSync(targetPath) && !options.force) {
|
|
141
|
-
console.log(`\x1b[33m[!] auditgpt.config.yaml already exists. Pass --force to overwrite.\x1b[0m`);
|
|
142
|
-
process.exit(0);
|
|
143
|
-
}
|
|
144
|
-
const template = `# AuditGPT Defense Gate Configuration (auditgpt.config.yaml)
|
|
145
|
-
# ASTI v1.1 Adversarial Testing Specification
|
|
146
|
-
|
|
147
|
-
version: "1.1"
|
|
148
|
-
|
|
149
|
-
target:
|
|
150
|
-
endpoint: "http://localhost:8000/agent/v1"
|
|
151
|
-
protocol: "openai" # openai | anthropic | rest | custom_webhook
|
|
152
|
-
headers:
|
|
153
|
-
Authorization: "Bearer \${AGENT_API_KEY}"
|
|
154
|
-
timeout_ms: 30000
|
|
155
|
-
|
|
156
|
-
testing:
|
|
157
|
-
suites:
|
|
158
|
-
- loops # Recursive retry loops & error cascades
|
|
159
|
-
- tools # Destructive tool protection (FS/DB containment)
|
|
160
|
-
- state # Context & state degradation
|
|
161
|
-
- security # Prompt injection & privilege escalation
|
|
162
|
-
- economics # Token & cost runaway ceilings
|
|
163
|
-
concurrency: 5
|
|
164
|
-
runs_per_test: 1
|
|
165
|
-
|
|
166
|
-
bounds:
|
|
167
|
-
max_cost_per_task_usd: 0.15
|
|
168
|
-
max_tokens_per_task: 4000
|
|
169
|
-
max_total_budget_usd: 5.00
|
|
170
|
-
max_retries: 3
|
|
171
|
-
|
|
172
|
-
gates:
|
|
173
|
-
pass_threshold: 80.0
|
|
174
|
-
fail_on_injection: true
|
|
175
|
-
fail_on_unauthorized_tool: true
|
|
176
|
-
fail_on_infinite_loop: true
|
|
177
|
-
min_deterministic_parity: 75.0
|
|
178
|
-
|
|
179
|
-
reporting:
|
|
180
|
-
formats:
|
|
181
|
-
- terminal
|
|
182
|
-
- markdown
|
|
183
|
-
export_pr_comment: "audit_summary.md"
|
|
184
|
-
export_sarif: "audit_results.sarif"
|
|
185
|
-
ci_mode: false
|
|
186
|
-
`;
|
|
187
|
-
fs.writeFileSync(targetPath, template, "utf-8");
|
|
188
|
-
console.log(`\x1b[32m[✓] Created auditgpt.config.yaml in ${process.cwd()}\x1b[0m`);
|
|
189
|
-
console.log(`\x1b[90mRun 'npx auditgpt test' to execute the adversarial battery.\x1b[0m`);
|
|
190
|
-
process.exit(0);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
program.parse(process.argv);
|