@riotprompt/riotprompt 0.0.21 → 1.0.1-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/MIGRATION.md +235 -0
- package/README.md +2 -0
- package/SECURITY.md +132 -0
- package/dist/builder.js +6 -0
- package/dist/builder.js.map +1 -1
- package/dist/cli.js +481 -22
- package/dist/context-manager.js +1 -1
- package/dist/conversation-logger.d.ts +17 -1
- package/dist/conversation-logger.js +21 -17
- package/dist/conversation-logger.js.map +1 -1
- package/dist/conversation.js +1 -1
- package/dist/error-handling.d.ts +52 -0
- package/dist/error-handling.js +132 -0
- package/dist/error-handling.js.map +1 -0
- package/dist/formatter.js +1 -1
- package/dist/iteration-strategy.js +1 -1
- package/dist/loader.js +60 -12
- package/dist/loader.js.map +1 -1
- package/dist/logger.d.ts +52 -0
- package/dist/logger.js +114 -14
- package/dist/logger.js.map +1 -1
- package/dist/logging-config.d.ts +84 -0
- package/dist/logging-config.js +116 -0
- package/dist/logging-config.js.map +1 -0
- package/dist/message-builder.js +1 -1
- package/dist/model-config.js +1 -1
- package/dist/override.js +10 -4
- package/dist/override.js.map +1 -1
- package/dist/recipes.js +6 -0
- package/dist/recipes.js.map +1 -1
- package/dist/reflection.js +1 -1
- package/dist/riotprompt.d.ts +9 -0
- package/dist/riotprompt.js +8 -0
- package/dist/riotprompt.js.map +1 -1
- package/dist/security/audit-logger.d.ts +61 -0
- package/dist/security/audit-logger.js +281 -0
- package/dist/security/audit-logger.js.map +1 -0
- package/dist/security/cli-security.d.ts +143 -0
- package/dist/security/cli-security.js +302 -0
- package/dist/security/cli-security.js.map +1 -0
- package/dist/security/defaults.d.ts +31 -0
- package/dist/security/defaults.js +72 -0
- package/dist/security/defaults.js.map +1 -0
- package/dist/security/events.d.ts +8 -0
- package/dist/security/index.d.ts +27 -0
- package/dist/security/index.js +22 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/path-guard.d.ts +161 -0
- package/dist/security/path-guard.js +327 -0
- package/dist/security/path-guard.js.map +1 -0
- package/dist/security/rate-limiter.d.ts +117 -0
- package/dist/security/rate-limiter.js +165 -0
- package/dist/security/rate-limiter.js.map +1 -0
- package/dist/security/serialization-schemas.d.ts +183 -0
- package/dist/security/serialization-schemas.js +174 -0
- package/dist/security/serialization-schemas.js.map +1 -0
- package/dist/security/timeout-guard.d.ts +123 -0
- package/dist/security/timeout-guard.js +223 -0
- package/dist/security/timeout-guard.js.map +1 -0
- package/dist/security/types.d.ts +86 -0
- package/dist/security/types.js +80 -0
- package/dist/security/types.js.map +1 -0
- package/dist/token-budget.js +1 -1
- package/dist/tools.js +1 -1
- package/guide/index.md +2 -0
- package/guide/integration.md +1109 -0
- package/guide/security.md +237 -0
- package/package.json +18 -11
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Security Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide covers security best practices when using RiotPrompt and related packages for AI/LLM workflows.
|
|
6
|
+
|
|
7
|
+
## Threat Model
|
|
8
|
+
|
|
9
|
+
### Assets to Protect
|
|
10
|
+
- **API Keys**: OpenAI, Anthropic, Gemini, and other provider credentials
|
|
11
|
+
- **User Data**: Prompts, conversations, and context containing sensitive information
|
|
12
|
+
- **File System**: Access to local files and directories
|
|
13
|
+
- **External APIs**: Network access to LLM providers and other services
|
|
14
|
+
|
|
15
|
+
### Threat Categories
|
|
16
|
+
|
|
17
|
+
| Threat | Description | Severity |
|
|
18
|
+
|--------|-------------|----------|
|
|
19
|
+
| Tool Injection | LLM generates malicious tool parameters | 🔴 Critical |
|
|
20
|
+
| Path Traversal | Accessing files outside intended directories | 🔴 Critical |
|
|
21
|
+
| Secret Leakage | API keys or sensitive data in logs/errors | 🔴 Critical |
|
|
22
|
+
| Resource Exhaustion | Infinite loops, ReDoS, timeout failures | 🟠 High |
|
|
23
|
+
| Prompt Injection | LLM output influences security-critical operations | 🟠 High |
|
|
24
|
+
| Information Disclosure | Error messages reveal system details | 🟡 Medium |
|
|
25
|
+
|
|
26
|
+
### Mitigations
|
|
27
|
+
|
|
28
|
+
| Threat | Mitigation | Package |
|
|
29
|
+
|--------|------------|---------|
|
|
30
|
+
| Tool Injection | ToolGuard with Zod schema validation | agentic |
|
|
31
|
+
| Path Traversal | PathGuard with base path restrictions | riotprompt |
|
|
32
|
+
| Secret Leakage | SecretGuard with automatic redaction | offrecord, spotclean |
|
|
33
|
+
| Resource Exhaustion | TimeoutGuard, SafeRegex, rate limiting | riotprompt, pressurelid |
|
|
34
|
+
| Prompt Injection | Careful tool design, output validation | Application level |
|
|
35
|
+
| Information Disclosure | Error sanitization in production | spotclean |
|
|
36
|
+
|
|
37
|
+
## Configuration Examples
|
|
38
|
+
|
|
39
|
+
### Development Mode
|
|
40
|
+
|
|
41
|
+
For local development with verbose logging:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { Security } from '@theunwalked/riotprompt';
|
|
45
|
+
|
|
46
|
+
// Permissive configuration for development
|
|
47
|
+
Security.configurePathGuard({
|
|
48
|
+
enabled: false, // Disable for easier development
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
Security.configureTimeoutGuard({
|
|
52
|
+
enabled: true,
|
|
53
|
+
llmTimeout: 300000, // 5 minutes for debugging
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Enable logging
|
|
57
|
+
process.env.RIOTPROMPT_LOGGING = 'true';
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Production Mode
|
|
61
|
+
|
|
62
|
+
Recommended configuration for production:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { Security, initializeErrorHandling } from '@theunwalked/riotprompt';
|
|
66
|
+
|
|
67
|
+
// Initialize error handling first
|
|
68
|
+
initializeErrorHandling({
|
|
69
|
+
environment: 'production',
|
|
70
|
+
basePaths: [process.cwd()],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Configure path security
|
|
74
|
+
Security.configurePathGuard({
|
|
75
|
+
enabled: true,
|
|
76
|
+
basePaths: [process.cwd()],
|
|
77
|
+
allowAbsolute: false,
|
|
78
|
+
allowSymlinks: false,
|
|
79
|
+
denyPatterns: [
|
|
80
|
+
'\\.\\.', // Parent directory
|
|
81
|
+
'~', // Home directory
|
|
82
|
+
'\\$\\{', // Variable expansion
|
|
83
|
+
'\\$\\(', // Command substitution
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Configure timeout protection
|
|
88
|
+
Security.configureTimeoutGuard({
|
|
89
|
+
enabled: true,
|
|
90
|
+
defaultTimeout: 30000,
|
|
91
|
+
llmTimeout: 120000,
|
|
92
|
+
toolTimeout: 30000,
|
|
93
|
+
fileTimeout: 5000,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Configure audit logging
|
|
97
|
+
Security.configureAuditLogger({
|
|
98
|
+
enabled: true,
|
|
99
|
+
logLevel: 'warning',
|
|
100
|
+
onEvent: (event) => {
|
|
101
|
+
// Send to monitoring system
|
|
102
|
+
if (event.severity === 'error') {
|
|
103
|
+
alertOps(event);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### High Security Mode
|
|
110
|
+
|
|
111
|
+
For handling PII or sensitive data:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { Security } from '@theunwalked/riotprompt';
|
|
115
|
+
import { ToolGuard, ToolSandbox } from '@theunwalked/agentic';
|
|
116
|
+
|
|
117
|
+
// Strict path security
|
|
118
|
+
Security.configurePathGuard({
|
|
119
|
+
enabled: true,
|
|
120
|
+
basePaths: ['./approved-prompts'],
|
|
121
|
+
allowAbsolute: false,
|
|
122
|
+
allowSymlinks: false,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Tool validation with strict schemas
|
|
126
|
+
const guard = new ToolGuard({
|
|
127
|
+
enabled: true,
|
|
128
|
+
validateParams: true,
|
|
129
|
+
detectPrototypePollution: true,
|
|
130
|
+
allowedTools: ['read_file', 'search'], // Explicit allowlist
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Sandboxed execution
|
|
134
|
+
const sandbox = new ToolSandbox({
|
|
135
|
+
enabled: true,
|
|
136
|
+
maxExecutionTime: 10000, // Shorter timeout
|
|
137
|
+
maxConcurrent: 2, // Limit concurrency
|
|
138
|
+
maxOutputSize: 100000, // 100KB max
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Rate limiting
|
|
142
|
+
Security.configureRateLimiter({
|
|
143
|
+
windowMs: 60000, // 1 minute
|
|
144
|
+
maxRequests: 10, // 10 requests per minute
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Best Practices
|
|
149
|
+
|
|
150
|
+
### API Key Management
|
|
151
|
+
|
|
152
|
+
1. **Never** pass API keys via CLI flags
|
|
153
|
+
```bash
|
|
154
|
+
# BAD - key visible in process list
|
|
155
|
+
riotprompt execute --api-key sk-xxx...
|
|
156
|
+
|
|
157
|
+
# GOOD - use environment variable
|
|
158
|
+
export OPENAI_API_KEY=sk-xxx...
|
|
159
|
+
riotprompt execute
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
2. Use environment variables or a secrets manager
|
|
163
|
+
3. Rotate keys regularly
|
|
164
|
+
4. Use separate keys for development and production
|
|
165
|
+
5. Monitor key usage for anomalies
|
|
166
|
+
|
|
167
|
+
### Tool Development
|
|
168
|
+
|
|
169
|
+
1. **Define Zod schemas** for all parameters:
|
|
170
|
+
```typescript
|
|
171
|
+
const schema = z.object({
|
|
172
|
+
path: z.string().max(1000).refine(
|
|
173
|
+
p => !p.includes('..'),
|
|
174
|
+
'Path traversal not allowed'
|
|
175
|
+
),
|
|
176
|
+
content: z.string().max(100000),
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
2. **Validate outputs** as well as inputs
|
|
181
|
+
3. **Implement proper error handling** that doesn't leak information
|
|
182
|
+
4. **Avoid shell commands** when possible
|
|
183
|
+
5. **Log security-relevant operations** to audit log
|
|
184
|
+
|
|
185
|
+
### Prompt Security
|
|
186
|
+
|
|
187
|
+
1. **Don't include secrets in prompts**
|
|
188
|
+
```typescript
|
|
189
|
+
// BAD
|
|
190
|
+
const prompt = `Use API key ${apiKey} to...`;
|
|
191
|
+
|
|
192
|
+
// GOOD - pass via secure context
|
|
193
|
+
const prompt = `Use the configured API key to...`;
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
2. **Sanitize user input** before including in prompts
|
|
197
|
+
3. **Be cautious with user-provided file paths**
|
|
198
|
+
4. **Review LLM outputs** before executing tools
|
|
199
|
+
5. **Use structured output** (JSON mode) for tool calls
|
|
200
|
+
|
|
201
|
+
### Logging Security
|
|
202
|
+
|
|
203
|
+
1. **Keep logging disabled** in production by default
|
|
204
|
+
2. **Use correlation IDs** for debugging without exposing details
|
|
205
|
+
3. **Monitor audit logs** for security events
|
|
206
|
+
4. **Set up alerts** for critical security events
|
|
207
|
+
|
|
208
|
+
## Security Events
|
|
209
|
+
|
|
210
|
+
The `SecurityAuditLogger` tracks these event types:
|
|
211
|
+
|
|
212
|
+
| Event Type | Description | Severity |
|
|
213
|
+
|------------|-------------|----------|
|
|
214
|
+
| `path_traversal_blocked` | Directory traversal attempt blocked | warning |
|
|
215
|
+
| `tool_validation_failed` | Tool parameter validation failed | warning |
|
|
216
|
+
| `tool_execution_timeout` | Tool execution timed out | warning |
|
|
217
|
+
| `secret_redacted` | Secret was redacted from output | info |
|
|
218
|
+
| `regex_blocked` | Unsafe regex pattern blocked | warning |
|
|
219
|
+
| `request_timeout` | External request timed out | warning |
|
|
220
|
+
| `api_key_used` | API key was used (for auditing) | info |
|
|
221
|
+
|
|
222
|
+
## Incident Response
|
|
223
|
+
|
|
224
|
+
If you suspect a security incident:
|
|
225
|
+
|
|
226
|
+
1. **Rotate all API keys** immediately
|
|
227
|
+
2. **Review audit logs** for suspicious activity
|
|
228
|
+
3. **Check for unauthorized file access**
|
|
229
|
+
4. **Review recent tool executions**
|
|
230
|
+
5. **Report the incident** following your organization's procedures
|
|
231
|
+
|
|
232
|
+
## Additional Resources
|
|
233
|
+
|
|
234
|
+
- [OWASP LLM Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/)
|
|
235
|
+
- [API Security Best Practices](https://owasp.org/www-project-api-security/)
|
|
236
|
+
- [Node.js Security Best Practices](https://nodejs.org/en/docs/guides/security/)
|
|
237
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riotprompt/riotprompt",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.1-dev.0",
|
|
4
|
+
"_versionReset": "2026-01-15",
|
|
4
5
|
"keywords": [
|
|
5
6
|
"prompt",
|
|
6
7
|
"llm",
|
|
@@ -35,11 +36,13 @@
|
|
|
35
36
|
"test": "npm run test:coverage",
|
|
36
37
|
"test:coverage": "vitest run --coverage",
|
|
37
38
|
"test:debug": "vitest --run --coverage --reporter verbose",
|
|
39
|
+
"test:security": "vitest run tests/security",
|
|
40
|
+
"test:security:watch": "vitest tests/security",
|
|
38
41
|
"test:readme": "doccident -c .markdown-doctest-setup.mjs README.md",
|
|
39
42
|
"lint": "eslint . --ext .ts",
|
|
40
43
|
"lint:fix": "eslint . --ext .ts --fix",
|
|
41
44
|
"clean": "rm -rf dist",
|
|
42
|
-
"precommit": "npm run lint && npm run test",
|
|
45
|
+
"precommit": "npm run build && npm run lint && npm run test",
|
|
43
46
|
"prepublishOnly": "npm run clean && npm run build",
|
|
44
47
|
"docs:dev": "cd docs && cp ../README.md public/ && npm install && npm run dev",
|
|
45
48
|
"docs:build": "cd docs && cp ../README.md public/ && npm install && npm run build",
|
|
@@ -50,7 +53,6 @@
|
|
|
50
53
|
"author": "Tim O'Brien <tobrien@discursive.com>",
|
|
51
54
|
"license": "Apache-2.0",
|
|
52
55
|
"devDependencies": {
|
|
53
|
-
"@anthropic-ai/sdk": "^0.71.2",
|
|
54
56
|
"@babel/core": "^7.28.0",
|
|
55
57
|
"@babel/plugin-transform-modules-commonjs": "^7.27.1",
|
|
56
58
|
"@babel/plugin-transform-typescript": "^7.28.0",
|
|
@@ -58,17 +60,16 @@
|
|
|
58
60
|
"@doccident/doccident": "^0.0.1",
|
|
59
61
|
"@eslint/eslintrc": "^3.3.1",
|
|
60
62
|
"@eslint/js": "^9.30.1",
|
|
61
|
-
"@google/generative-ai": "^0.24.1",
|
|
62
63
|
"@rollup/plugin-replace": "^6.0.2",
|
|
63
64
|
"@swc/core": "^1.12.11",
|
|
64
65
|
"@types/node": "^24.0.12",
|
|
65
66
|
"@typescript-eslint/eslint-plugin": "^8.36.0",
|
|
66
67
|
"@typescript-eslint/parser": "^8.36.0",
|
|
67
68
|
"@vitest/coverage-v8": "^3.2.4",
|
|
69
|
+
"ajv": "^8.17.1",
|
|
68
70
|
"eslint": "^9.30.1",
|
|
69
71
|
"eslint-plugin-import": "^2.32.0",
|
|
70
72
|
"globals": "^16.3.0",
|
|
71
|
-
"openai": "^6.15.0",
|
|
72
73
|
"typescript": "^5.8.3",
|
|
73
74
|
"vite": "^7.0.4",
|
|
74
75
|
"vite-plugin-dts": "^4.5.4",
|
|
@@ -76,25 +77,31 @@
|
|
|
76
77
|
"vitest": "^3.2.4"
|
|
77
78
|
},
|
|
78
79
|
"dependencies": {
|
|
79
|
-
"@
|
|
80
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
81
|
+
"@fjell/logging": "^4.4.68",
|
|
82
|
+
"@google/generative-ai": "^0.24.1",
|
|
83
|
+
"@theunwalked/cardigantime": "^0.0.22",
|
|
84
|
+
"@theunwalked/pressurelid": "^1.0.2",
|
|
85
|
+
"@theunwalked/spotclean": "^0.0.3",
|
|
80
86
|
"commander": "^14.0.2",
|
|
81
87
|
"dotenv": "^17.2.3",
|
|
82
88
|
"fast-xml-parser": "^5.3.3",
|
|
83
89
|
"glob": "^11.0.3",
|
|
84
90
|
"js-yaml": "^4.1.1",
|
|
85
91
|
"marked": "^16.0.0",
|
|
92
|
+
"openai": "^6.15.0",
|
|
86
93
|
"tiktoken": "^1.0.22",
|
|
87
94
|
"zod": "^4.0.2",
|
|
88
95
|
"zod-to-json-schema": "^3.25.1"
|
|
89
96
|
},
|
|
90
97
|
"peerDependencies": {
|
|
91
|
-
"@riotprompt/execution": "^0.0.4",
|
|
92
|
-
"@riotprompt/execution-openai": "^0.0.4",
|
|
93
|
-
"@riotprompt/execution-anthropic": "^0.0.4",
|
|
94
|
-
"@riotprompt/execution-gemini": "^0.0.4",
|
|
95
|
-
"@riotprompt/agentic": "^0.0.5",
|
|
96
98
|
"@anthropic-ai/sdk": "^0.71.2",
|
|
97
99
|
"@google/generative-ai": "^0.24.1",
|
|
100
|
+
"@riotprompt/agentic": "^1.0.2",
|
|
101
|
+
"@riotprompt/execution": "^1.0.1",
|
|
102
|
+
"@riotprompt/execution-anthropic": "^1.0.1",
|
|
103
|
+
"@riotprompt/execution-gemini": "^1.0.1",
|
|
104
|
+
"@riotprompt/execution-openai": "^1.0.1",
|
|
98
105
|
"openai": "^6.15.0",
|
|
99
106
|
"tiktoken": "^1.0.22"
|
|
100
107
|
},
|