@jigyasudham/veto 0.8.3 → 1.0.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 (111) hide show
  1. package/README.md +209 -52
  2. package/dist/agents/executor.js +36 -3
  3. package/dist/cli.js +246 -7
  4. package/dist/context/reader.js +113 -0
  5. package/dist/council/index.js +3 -1
  6. package/dist/plugins/loader.js +49 -0
  7. package/dist/router/index.js +2 -2
  8. package/dist/router/learning-updater.js +45 -1
  9. package/dist/server.js +478 -14
  10. package/dist/watcher/index.js +77 -0
  11. package/dist/workflow/pipeline.js +64 -0
  12. package/package.json +12 -3
  13. package/.claude/settings.local.json +0 -9
  14. package/src/adapters/claude.ts +0 -70
  15. package/src/adapters/codex.ts +0 -71
  16. package/src/adapters/gemini.ts +0 -71
  17. package/src/adapters/index.ts +0 -217
  18. package/src/agents/development/api.ts +0 -120
  19. package/src/agents/development/backend.ts +0 -85
  20. package/src/agents/development/coder.ts +0 -213
  21. package/src/agents/development/database.ts +0 -83
  22. package/src/agents/development/debugger.ts +0 -238
  23. package/src/agents/development/devops.ts +0 -86
  24. package/src/agents/development/frontend.ts +0 -85
  25. package/src/agents/development/migration.ts +0 -144
  26. package/src/agents/development/performance.ts +0 -144
  27. package/src/agents/development/refactor.ts +0 -86
  28. package/src/agents/development/reviewer.ts +0 -268
  29. package/src/agents/development/tester.ts +0 -151
  30. package/src/agents/executor.ts +0 -158
  31. package/src/agents/memory/context-manager.ts +0 -171
  32. package/src/agents/memory/decision-logger.ts +0 -160
  33. package/src/agents/memory/knowledge-base.ts +0 -124
  34. package/src/agents/memory/pattern-learner.ts +0 -143
  35. package/src/agents/memory/project-mapper.ts +0 -118
  36. package/src/agents/quality/accessibility.ts +0 -99
  37. package/src/agents/quality/code-quality.ts +0 -115
  38. package/src/agents/quality/compatibility.ts +0 -58
  39. package/src/agents/quality/documentation.ts +0 -105
  40. package/src/agents/quality/error-handling.ts +0 -96
  41. package/src/agents/research/competitor-analyzer.ts +0 -45
  42. package/src/agents/research/cost-analyzer.ts +0 -54
  43. package/src/agents/research/estimator.ts +0 -60
  44. package/src/agents/research/ethics-bias.ts +0 -113
  45. package/src/agents/research/researcher.ts +0 -114
  46. package/src/agents/research/risk-assessor.ts +0 -63
  47. package/src/agents/research/tech-advisor.ts +0 -55
  48. package/src/agents/security/auth.ts +0 -287
  49. package/src/agents/security/dependency-audit.ts +0 -337
  50. package/src/agents/security/penetration.ts +0 -262
  51. package/src/agents/security/privacy.ts +0 -285
  52. package/src/agents/security/scanner.ts +0 -322
  53. package/src/agents/security/secrets.ts +0 -249
  54. package/src/agents/types.ts +0 -66
  55. package/src/agents/workflow/automation.ts +0 -59
  56. package/src/agents/workflow/file-manager.ts +0 -52
  57. package/src/agents/workflow/git-agent.ts +0 -55
  58. package/src/agents/workflow/reporter.ts +0 -51
  59. package/src/agents/workflow/search-agent.ts +0 -40
  60. package/src/agents/workflow/task-coordinator.ts +0 -41
  61. package/src/agents/workflow/task-planner.ts +0 -47
  62. package/src/cli.ts +0 -204
  63. package/src/council/decision-engine.ts +0 -171
  64. package/src/council/devil-advocate.ts +0 -116
  65. package/src/council/index.ts +0 -44
  66. package/src/council/lead-developer.ts +0 -118
  67. package/src/council/legal-compliance.ts +0 -152
  68. package/src/council/product-manager.ts +0 -102
  69. package/src/council/security.ts +0 -172
  70. package/src/council/system-architect.ts +0 -132
  71. package/src/council/types.ts +0 -33
  72. package/src/council/ux-designer.ts +0 -121
  73. package/src/memory/local.ts +0 -305
  74. package/src/memory/schema.ts +0 -174
  75. package/src/memory/sync.ts +0 -274
  76. package/src/router/complexity-scorer.ts +0 -96
  77. package/src/router/context-compressor.ts +0 -74
  78. package/src/router/index.ts +0 -60
  79. package/src/router/learning-updater.ts +0 -271
  80. package/src/router/model-selector.ts +0 -83
  81. package/src/router/rate-monitor.ts +0 -103
  82. package/src/server.ts +0 -1038
  83. package/src/skills/development/skill-api-design.ts +0 -329
  84. package/src/skills/development/skill-auth.ts +0 -271
  85. package/src/skills/development/skill-ci-cd.ts +0 -0
  86. package/src/skills/development/skill-crud.ts +0 -209
  87. package/src/skills/development/skill-db-schema.ts +0 -0
  88. package/src/skills/development/skill-docker.ts +0 -0
  89. package/src/skills/development/skill-env-setup.ts +0 -0
  90. package/src/skills/development/skill-scaffold.ts +0 -323
  91. package/src/skills/intelligence/skill-complexity-score.ts +0 -69
  92. package/src/skills/intelligence/skill-cost-track.ts +0 -39
  93. package/src/skills/intelligence/skill-learning-loop.ts +0 -69
  94. package/src/skills/intelligence/skill-pattern-detect.ts +0 -38
  95. package/src/skills/intelligence/skill-rate-watch.ts +0 -61
  96. package/src/skills/memory/skill-context-compress.ts +0 -98
  97. package/src/skills/memory/skill-cross-sync.ts +0 -104
  98. package/src/skills/memory/skill-decision-log.ts +0 -119
  99. package/src/skills/memory/skill-session-restore.ts +0 -59
  100. package/src/skills/memory/skill-session-save.ts +0 -94
  101. package/src/skills/quality/skill-accessibility.ts +0 -0
  102. package/src/skills/quality/skill-code-review.ts +0 -84
  103. package/src/skills/quality/skill-docs-gen.ts +0 -0
  104. package/src/skills/quality/skill-perf-audit.ts +0 -0
  105. package/src/skills/quality/skill-security-scan.ts +0 -91
  106. package/src/skills/quality/skill-test-suite.ts +0 -290
  107. package/src/skills/workflow/skill-deploy.ts +0 -0
  108. package/src/skills/workflow/skill-git-workflow.ts +0 -0
  109. package/src/skills/workflow/skill-rollback.ts +0 -0
  110. package/src/skills/workflow/skill-task-breakdown.ts +0 -0
  111. package/tsconfig.json +0 -20
@@ -1,287 +0,0 @@
1
- import type { AgentPlan } from '../types.js';
2
-
3
- // ─── Auth-type detection ───────────────────────────────────────────────────
4
-
5
- type AuthType = 'jwt' | 'oauth' | 'session' | 'rbac' | 'mfa' | 'general';
6
-
7
- function detectAuthType(task: string): AuthType {
8
- const t = task.toLowerCase();
9
- if (/\bjwt\b|json\s*web\s*token|refresh\s*token/.test(t)) return 'jwt';
10
- if (/\boauth\b|oauth2|openid|pkce|authorization\s*code/.test(t)) return 'oauth';
11
- if (/\bsession\b|cookie\s*auth|server[\s-]?side\s*session/.test(t)) return 'session';
12
- if (/\brbac\b|role[\s-]?based|permission|access\s*control/.test(t)) return 'rbac';
13
- if (/\bmfa\b|multi[\s-]?factor|totp|authenticator|2fa/.test(t)) return 'mfa';
14
- return 'general';
15
- }
16
-
17
- // ─── Checklist builders ────────────────────────────────────────────────────
18
-
19
- const JWT_CHECKLIST = [
20
- 'Hash passwords with bcrypt (cost factor 12) before storing',
21
- 'Sign JWTs with RS256 (asymmetric) or HS256 with ≥256-bit secret',
22
- 'Set short access token expiry (15 minutes recommended)',
23
- 'Implement refresh token rotation: issue a new refresh token on every use',
24
- 'Store refresh tokens in the database and invalidate on logout',
25
- 'Store access tokens in memory only; deliver via httpOnly Secure cookies where possible',
26
- 'Never store JWTs in localStorage — XSS vulnerable',
27
- 'Validate alg header server-side; reject "none" algorithm',
28
- 'Verify iss, aud, exp, iat claims on every request',
29
- 'Implement token revocation list or short-TTL approach for logout',
30
- 'Apply rate limiting to /login, /token, and /refresh endpoints',
31
- 'Lock account after 5 consecutive failed login attempts; require email unlock',
32
- 'Log every successful and failed authentication attempt with IP and user-agent',
33
- 'Enforce password complexity: 12+ chars, mixed case, numbers, symbols',
34
- 'Provide a secure password reset flow: time-limited single-use token sent to verified email',
35
- ];
36
-
37
- const OAUTH_CHECKLIST = [
38
- 'Use PKCE (Proof Key for Code Exchange) for all public clients (SPAs, mobile apps)',
39
- 'Generate and verify a random state parameter to prevent CSRF',
40
- 'Store OAuth tokens server-side; never expose client_secret in frontend code',
41
- 'Validate the redirect_uri exactly against a pre-registered allow-list',
42
- 'Use the authorization_code flow; never implicit flow for new implementations',
43
- 'Scope tokens to the minimum permissions required by the application',
44
- 'Exchange the authorisation code for tokens server-side only',
45
- 'Store access tokens in httpOnly cookies or a secure backend session',
46
- 'Implement token refresh before expiry; handle refresh failures gracefully',
47
- 'Validate the id_token signature and claims (iss, aud, exp, nonce)',
48
- 'Bind the nonce in the id_token to the session nonce to prevent replay',
49
- "Revoke tokens on logout via the provider's revocation endpoint",
50
- 'Log all token issuance, refresh, and revocation events',
51
- 'Rotate client_secret periodically and after any suspected exposure',
52
- 'Enable provider-side suspicious-login alerts and enforce MFA at the IdP level',
53
- ];
54
-
55
- const SESSION_CHECKLIST = [
56
- 'Set session cookies with Secure, httpOnly, and SameSite=Strict attributes',
57
- 'Regenerate session ID on login to prevent session fixation',
58
- 'Regenerate session ID on privilege elevation (e.g., sudo confirmation)',
59
- 'Set absolute session timeout (e.g., 8 hours) and idle timeout (e.g., 30 minutes)',
60
- 'Store session data server-side (Redis, DB); never in the cookie itself',
61
- 'Sign or encrypt session data if stored client-side (use express-session + iron-session)',
62
- 'Invalidate all sessions on password change',
63
- 'Hash passwords with bcrypt (cost factor 12)',
64
- 'Apply rate limiting to login endpoint',
65
- 'Lock account after repeated failures; send email alert to account owner',
66
- 'Log session creation, expiry, and logout events with IP and timestamp',
67
- 'Implement CSRF protection for all state-changing requests (double-submit cookie or synchroniser token)',
68
- 'Expire password reset tokens after 1 hour and invalidate after use',
69
- 'Never transmit session IDs in URLs — use cookies only',
70
- 'Run session store cleanup job to purge expired sessions',
71
- ];
72
-
73
- const RBAC_CHECKLIST = [
74
- 'Define roles as discrete, named sets of permissions (e.g., admin, editor, viewer)',
75
- 'Assign roles to users, not permissions directly — avoid permission explosion',
76
- 'Enforce authorisation checks at the service layer, not only the UI layer',
77
- 'Use a middleware factory: requireRole("admin") applied to protected routes',
78
- 'Store roles in the database; load at session start; never trust client-supplied role',
79
- 'Implement resource-level ownership check in addition to role check (IDOR prevention)',
80
- 'Principle of least privilege: default to no access; grant explicitly',
81
- 'Audit all role assignments and revocations with actor, timestamp, and reason',
82
- 'Provide an admin interface to view and modify role assignments',
83
- 'Cache user permissions per request (not globally) to avoid stale privilege',
84
- 'Test permission boundaries: verify low-privilege users cannot access high-privilege routes',
85
- 'Implement deny-list for critical operations (e.g., delete user requires two-person approval)',
86
- 'Document the permission matrix in a roles.md or OpenAPI security scheme',
87
- 'Re-validate permissions on every sensitive operation, not only at login time',
88
- ];
89
-
90
- const MFA_CHECKLIST = [
91
- 'Implement TOTP (RFC 6238) using a well-audited library (otplib, speakeasy)',
92
- 'Generate a unique 80-bit (base32-encoded) secret per user during enrolment',
93
- 'Display QR code and allow manual key entry during setup; verify before saving',
94
- 'Require MFA confirmation before saving the MFA secret (prevent lock-out attacks)',
95
- 'Store MFA secret encrypted at rest; never log it',
96
- 'Generate 8–10 single-use backup codes on enrolment; hash them before storing',
97
- 'Apply a short time window (±30 seconds, 1 step) for TOTP validation',
98
- 'Rate-limit TOTP attempts: 5 failures lock MFA for 15 minutes',
99
- 'Allow account recovery via verified backup code + email confirmation',
100
- 'Log every MFA event: enrolment, verification, failure, backup-code use',
101
- 'Send email notification when MFA is disabled or backup codes are regenerated',
102
- 'Enforce re-authentication before sensitive operations (delete account, change email)',
103
- 'Support WebAuthn / passkeys as a stronger alternative to TOTP',
104
- 'Periodically prompt users to verify their MFA device is still accessible',
105
- ];
106
-
107
- const GENERAL_CHECKLIST = [
108
- 'Hash all passwords with bcrypt (cost factor 12) or argon2id',
109
- 'Never store plaintext passwords, even temporarily',
110
- 'Use HTTPS everywhere; redirect HTTP to HTTPS; set HSTS header',
111
- 'Implement account lockout after 5 failed attempts (exponential backoff)',
112
- 'Rate-limit all authentication endpoints (login, register, reset)',
113
- 'Use secure, random session IDs or JWTs with short expiry',
114
- 'Regenerate session ID on every privilege change',
115
- 'Protect against CSRF with SameSite cookies or CSRF token pattern',
116
- 'Store tokens in httpOnly, Secure cookies, not localStorage',
117
- 'Implement a secure password reset flow: single-use, time-limited, email-verified token',
118
- 'Send email notifications on password change and suspicious login',
119
- 'Log all auth events (login, logout, failure) with IP, timestamp, user-agent',
120
- 'Enforce strong password policy or passphrase with minimum entropy',
121
- 'Implement MFA as an option (or requirement for privileged accounts)',
122
- 'Run dependency audit (npm audit) to catch auth library CVEs',
123
- ];
124
-
125
- // ─── Pattern maps ──────────────────────────────────────────────────────────
126
-
127
- const APPROACH_MAP: Record<AuthType, string> = {
128
- jwt: 'Implement a stateless JWT auth system with short-lived access tokens, rotating refresh tokens, and httpOnly cookie storage.',
129
- oauth: 'Implement OAuth 2.0 with PKCE for public clients, state parameter for CSRF prevention, and server-side token storage.',
130
- session: 'Implement secure server-side sessions with session fixation prevention, absolute/idle timeouts, and SameSite cookie protection.',
131
- rbac: 'Design a role-based access control system with least-privilege defaults, resource-level ownership checks, and audit logging.',
132
- mfa: 'Add TOTP-based multi-factor authentication with backup codes, rate limiting, and account recovery flow.',
133
- general: 'Implement a comprehensive authentication system following OWASP Authentication Cheat Sheet guidance.',
134
- };
135
-
136
- const STEPS_MAP: Record<AuthType, string[]> = {
137
- jwt: [
138
- 'Set up user model with hashed password field (bcrypt)',
139
- 'Implement /register endpoint with input validation and duplicate check',
140
- 'Implement /login endpoint: verify password, issue access + refresh tokens',
141
- 'Store refresh tokens in the database with userId, token hash, expiry, revoked flag',
142
- 'Implement token verification middleware that validates access token on every protected route',
143
- 'Implement /refresh endpoint: validate refresh token, rotate it, issue new access token',
144
- 'Implement /logout endpoint: revoke refresh token in DB, clear cookies',
145
- 'Add rate limiting middleware to /login and /refresh',
146
- 'Add account lockout logic after repeated failures',
147
- 'Write integration tests covering happy path, expired token, revoked token, lockout',
148
- ],
149
- oauth: [
150
- 'Register application with OAuth provider and store client_id and client_secret in env vars',
151
- 'Implement /auth/start: generate state + PKCE code_verifier, store in session, redirect to provider',
152
- 'Implement /auth/callback: verify state, exchange code for tokens using PKCE verifier',
153
- 'Store access and refresh tokens server-side; set a session cookie',
154
- 'Implement token refresh middleware that silently refreshes before expiry',
155
- 'Implement /auth/logout: revoke tokens at provider, destroy session',
156
- 'Validate id_token claims: iss, aud, exp, nonce',
157
- 'Map provider user profile to local user record (create or update)',
158
- 'Write integration tests for callback, state mismatch, and token expiry scenarios',
159
- ],
160
- session: [
161
- 'Configure session middleware with Secure, httpOnly, SameSite=Strict cookie settings',
162
- 'Implement /register with bcrypt password hashing (cost 12)',
163
- 'Implement /login: verify password, regenerate session ID, set session data',
164
- 'Implement /logout: destroy session, clear session cookie',
165
- 'Add CSRF middleware (csurf or synchroniser token pattern)',
166
- 'Configure absolute and idle session timeouts in session store',
167
- 'Add rate limiting to /login',
168
- 'Implement account lockout and email alert on suspicious activity',
169
- 'Write tests for session fixation prevention, timeout, and CSRF rejection',
170
- ],
171
- rbac: [
172
- 'Define role enum and permission list; document in roles config file',
173
- 'Add role field to user model with default value of least-privileged role',
174
- 'Create requireRole(role) middleware that checks req.user.role',
175
- 'Create requireOwnership(getResource) middleware for resource-level checks',
176
- 'Apply role middleware to all protected routes',
177
- 'Build admin endpoint to assign/revoke roles with audit logging',
178
- 'Write tests for each role boundary: ensure lower roles cannot access higher-role routes',
179
- ],
180
- mfa: [
181
- 'Add mfa_secret (encrypted) and mfa_enabled fields to user model',
182
- 'Implement /mfa/setup: generate secret, return QR code URI to frontend',
183
- 'Implement /mfa/verify-setup: validate TOTP code, save secret, generate backup codes',
184
- 'Implement /mfa/challenge: post-password-check step, require TOTP code',
185
- 'Add rate limiting and lockout to /mfa/challenge',
186
- 'Implement /mfa/backup: accept backup code (hash-compare), mark used',
187
- 'Implement /mfa/disable: require password + current TOTP, log the event',
188
- 'Write tests for valid TOTP, expired TOTP, brute-force lockout, backup code use',
189
- ],
190
- general: [
191
- 'Choose and implement appropriate token/session strategy',
192
- 'Hash passwords with bcrypt (cost 12)',
193
- 'Set up login, register, logout, password-reset endpoints',
194
- 'Add rate limiting and account lockout',
195
- 'Configure secure cookie settings',
196
- 'Add audit logging for all auth events',
197
- 'Write comprehensive auth integration tests',
198
- ],
199
- };
200
-
201
- const PITFALLS_MAP: Record<AuthType, string[]> = {
202
- jwt: [
203
- 'Setting long access token expiry (hours/days) — defeats the purpose of short-lived tokens',
204
- 'Not rotating refresh tokens on use — stolen token can be used indefinitely',
205
- 'Accepting "alg":"none" — bypass all signature verification',
206
- 'Storing JWTs in localStorage — exposed to XSS attacks',
207
- ],
208
- oauth: [
209
- 'Omitting the state parameter — open to CSRF attacks on the OAuth flow',
210
- 'Not using PKCE for public clients — authorization code interception',
211
- 'Logging the OAuth access token or storing it client-side',
212
- 'Not validating the redirect_uri strictly — open redirect attack',
213
- ],
214
- session: [
215
- 'Not regenerating session ID on login — session fixation vulnerability',
216
- 'Missing SameSite cookie attribute — CSRF risk',
217
- 'Storing sensitive data in the cookie directly — tamper risk without signing/encryption',
218
- 'No idle timeout — abandoned sessions persist indefinitely',
219
- ],
220
- rbac: [
221
- 'Trusting client-supplied role value — privilege escalation',
222
- 'Checking role only at the route level, not the data layer — IDOR still possible',
223
- 'Overly broad roles — violates least-privilege principle',
224
- 'Caching permissions globally across requests — stale privilege after role change',
225
- ],
226
- mfa: [
227
- 'Allowing too large a time window for TOTP — makes brute force easier',
228
- 'Not rate-limiting TOTP attempts — allows exhaustive code search',
229
- 'Storing backup codes in plaintext — leaks allow full bypass',
230
- 'Not revoking MFA secret on account recovery — prior device retains access',
231
- ],
232
- general: [
233
- 'Using MD5 or SHA-1 for password hashing — trivially reversible',
234
- 'Implementing custom cryptography — use established libraries only',
235
- 'Sending password in plaintext over HTTP',
236
- 'Not invalidating sessions on password change',
237
- ],
238
- };
239
-
240
- const PATTERNS_MAP: Record<AuthType, string[]> = {
241
- jwt: ['Stateless JWT with rotating refresh tokens', 'httpOnly cookie token delivery', 'Token revocation via database allowlist/denylist'],
242
- oauth: ['Authorization Code + PKCE flow', 'State + nonce CSRF prevention', 'Server-side token storage proxy'],
243
- session: ['Server-side session with Redis store', 'Double-submit CSRF cookie', 'Session fixation prevention via regenerate()'],
244
- rbac: ['Middleware-based role enforcement', 'Resource ownership predicate', 'Least-privilege default with explicit grants'],
245
- mfa: ['TOTP (RFC 6238) with backup codes', 'Step-up authentication for sensitive operations', 'Enrolment verification before commitment'],
246
- general: ['Defence in depth: multiple auth layers', 'Principle of least privilege', 'Fail-secure: deny by default'],
247
- };
248
-
249
- // ─── Public API ────────────────────────────────────────────────────────────
250
-
251
- export function plan(task: string, context?: string): AgentPlan {
252
- const authType = detectAuthType(task);
253
-
254
- const checklistMap: Record<AuthType, string[]> = {
255
- jwt: JWT_CHECKLIST,
256
- oauth: OAUTH_CHECKLIST,
257
- session: SESSION_CHECKLIST,
258
- rbac: RBAC_CHECKLIST,
259
- mfa: MFA_CHECKLIST,
260
- general: GENERAL_CHECKLIST,
261
- };
262
-
263
- const tierMap: Record<AuthType, 1 | 2 | 3> = {
264
- jwt: 3, oauth: 3, session: 3, rbac: 3, mfa: 3, general: 3,
265
- };
266
-
267
- const durationMap: Record<AuthType, string> = {
268
- jwt: '4-6 hours',
269
- oauth: '6-10 hours',
270
- session: '3-5 hours',
271
- rbac: '4-6 hours',
272
- mfa: '6-8 hours',
273
- general: '2-4 hours',
274
- };
275
-
276
- return {
277
- agent: 'auth',
278
- task,
279
- tier: tierMap[authType],
280
- approach: APPROACH_MAP[authType],
281
- steps: STEPS_MAP[authType],
282
- checklist: checklistMap[authType],
283
- pitfalls: PITFALLS_MAP[authType],
284
- patterns: PATTERNS_MAP[authType],
285
- duration_estimate: context?.includes('complex') ? '8-12 hours' : durationMap[authType],
286
- };
287
- }
@@ -1,337 +0,0 @@
1
- import type { AgentPlan } from '../types.js';
2
- import type { FindingSeverity } from '../types.js';
3
-
4
- // ─── Public types ──────────────────────────────────────────────────────────
5
-
6
- export interface DependencyFlag {
7
- name: string;
8
- version: string;
9
- reason: string;
10
- severity: FindingSeverity;
11
- fix: string;
12
- }
13
-
14
- export interface DependencyAuditResult {
15
- total_deps: number;
16
- flagged: DependencyFlag[];
17
- recommendations: string[];
18
- score: number;
19
- }
20
-
21
- // ─── Plan ──────────────────────────────────────────────────────────────────
22
-
23
- export function plan(task: string, _context?: string): AgentPlan {
24
- return {
25
- agent: 'dependency-audit',
26
- task,
27
- tier: 1,
28
- approach:
29
- 'Audit all direct and transitive dependencies for known CVEs, deprecated packages, ' +
30
- 'and missing security-critical libraries. Produce a prioritised remediation list.',
31
- steps: [
32
- 'Parse package.json to enumerate dependencies and devDependencies',
33
- 'Check each package against the known-problematic package list',
34
- 'Run npm audit / yarn audit to surface known CVEs from the advisory database',
35
- 'Identify deprecated or unmaintained packages that introduce risk',
36
- 'Check for missing security-critical middleware (helmet, rate-limit)',
37
- 'Verify that lockfile (package-lock.json / yarn.lock) is committed and up to date',
38
- 'Check for packages that should not be in production dependencies (devDeps in deps)',
39
- 'Review transitive dependencies flagged by npm audit for prototype pollution',
40
- 'Produce remediation steps prioritised by severity',
41
- 'Set up automated dependency scanning in CI (Dependabot or Renovate)',
42
- ],
43
- checklist: [
44
- 'npm audit or yarn audit shows zero critical or high vulnerabilities',
45
- 'Lockfile committed to version control and not in .gitignore',
46
- 'All dependencies pinned to exact versions or narrow semver ranges',
47
- 'Dependabot or Renovate configured for automatic security PRs',
48
- 'node-serialize removed — known RCE vulnerability',
49
- 'lodash >= 4.17.21 (prototype pollution fix)',
50
- 'minimist >= 1.2.6 (prototype pollution fix)',
51
- 'tar >= 4.4.18 (path traversal fix)',
52
- 'ws >= 7.4.6 (DoS fix)',
53
- 'axios >= 0.21.2 (SSRF fix)',
54
- 'jsonwebtoken >= 9.0.0 (algorithm confusion fix)',
55
- 'helmet installed and applied to Express app',
56
- 'express-rate-limit installed and applied to auth and sensitive routes',
57
- 'No unused dependencies in package.json',
58
- 'devDependencies not included in production Docker image (--production install)',
59
- 'No packages sourced from git branches or unverified registries',
60
- 'npm config set audit-level high in CI to fail on high/critical',
61
- 'SBOM (Software Bill of Materials) generated for production releases',
62
- ],
63
- pitfalls: [
64
- 'Ignoring npm audit output by adding --ignore-scripts instead of fixing the issue',
65
- 'Using npm install without a lockfile — allows different versions across environments',
66
- 'Installing devDependencies in production — increases attack surface',
67
- 'Using packages from personal GitHub repos without verifying integrity',
68
- 'Overriding transitive dependency versions in overrides without testing',
69
- 'Not reviewing Dependabot PRs promptly — security patches accumulate',
70
- 'Trusting package.json version ranges (^) without auditing transitive tree',
71
- ],
72
- patterns: [
73
- 'Lockfile-first install: npm ci instead of npm install in CI',
74
- 'Production-only install: npm ci --omit=dev in Docker production stage',
75
- 'Automated dependency updates: Dependabot weekly security PRs',
76
- 'Audit gate: npm audit --audit-level=high fails CI on violations',
77
- 'SBOM generation: cyclonedx-npm for supply-chain transparency',
78
- ],
79
- duration_estimate: '1-2 hours for initial audit; ongoing via automated tooling',
80
- };
81
- }
82
-
83
- // ─── Known problematic packages database ──────────────────────────────────
84
-
85
- interface KnownIssue {
86
- reason: string;
87
- severity: FindingSeverity;
88
- fix: string;
89
- /** semver prefix that is safe; versions below this are flagged */
90
- safeAbove?: string;
91
- }
92
-
93
- const KNOWN_ISSUES: Record<string, KnownIssue> = {
94
- 'node-serialize': {
95
- reason: 'Contains a Remote Code Execution (RCE) vulnerability — deserialization of untrusted data executes arbitrary code.',
96
- severity: 'critical',
97
- fix: 'Remove node-serialize entirely. Use JSON.parse() for safe, schema-validated deserialisation.',
98
- },
99
- 'serialize-javascript': {
100
- reason: 'Older versions have an XSS vulnerability when serialised output is embedded in HTML.',
101
- severity: 'high',
102
- safeAbove: '3.1.0',
103
- fix: 'Upgrade to serialize-javascript >= 3.1.0 which escapes HTML-sensitive characters.',
104
- },
105
- lodash: {
106
- reason: 'Versions below 4.17.21 are vulnerable to prototype pollution (CVE-2020-8203).',
107
- severity: 'high',
108
- safeAbove: '4.17.21',
109
- fix: 'Upgrade lodash to >= 4.17.21. Consider replacing with individual lodash-es functions to reduce bundle size.',
110
- },
111
- minimist: {
112
- reason: 'Versions below 1.2.6 allow prototype pollution via constructor or __proto__ keys.',
113
- severity: 'high',
114
- safeAbove: '1.2.6',
115
- fix: 'Upgrade minimist to >= 1.2.6.',
116
- },
117
- tar: {
118
- reason: 'Older tar versions are vulnerable to path traversal (CVE-2021-37701, CVE-2021-37712).',
119
- severity: 'high',
120
- safeAbove: '4.4.18',
121
- fix: 'Upgrade tar to >= 4.4.18 (v4) or >= 6.1.9 (v6).',
122
- },
123
- ws: {
124
- reason: 'Versions below 7.4.6 are vulnerable to a Denial of Service via special HTTP headers (CVE-2021-32640).',
125
- severity: 'high',
126
- safeAbove: '7.4.6',
127
- fix: 'Upgrade ws to >= 7.4.6 (ws@7) or >= 8.0.0 (ws@8).',
128
- },
129
- axios: {
130
- reason: 'Versions below 0.21.2 are vulnerable to SSRF via crafted redirect (CVE-2020-28168).',
131
- severity: 'high',
132
- safeAbove: '0.21.2',
133
- fix: 'Upgrade axios to >= 0.21.2 or >= 1.0.0 for the current major.',
134
- },
135
- jsonwebtoken: {
136
- reason: 'Versions below 9.0.0 are vulnerable to algorithm confusion attacks (CVE-2022-23529).',
137
- severity: 'critical',
138
- safeAbove: '9.0.0',
139
- fix: 'Upgrade jsonwebtoken to >= 9.0.0 and explicitly pass { algorithms: ["HS256"] } to verify().',
140
- },
141
- request: {
142
- reason: 'The "request" package is deprecated (unmaintained since 2020) and will not receive security patches.',
143
- severity: 'medium',
144
- fix: 'Replace with native fetch() (Node 18+), axios >= 1.0.0, or got.',
145
- },
146
- mkdirp: {
147
- reason: 'mkdirp v0.x is outdated; the package has been rewritten and old versions may conflict with native fs.mkdirSync options.',
148
- severity: 'low',
149
- fix: 'Upgrade to mkdirp >= 1.0.4 or use fs.mkdirSync(path, { recursive: true }) available in Node 12+.',
150
- },
151
- rimraf: {
152
- reason: 'rimraf v2 is outdated; v3+ provides Promise-based API and better error handling.',
153
- severity: 'low',
154
- fix: 'Upgrade to rimraf >= 3.0.0 or use fs.rm(path, { recursive: true }) available in Node 14.14+.',
155
- },
156
- 'electron-builder': {
157
- reason: 'Older versions have code-signing bypass vulnerabilities.',
158
- severity: 'medium',
159
- safeAbove: '22.14.13',
160
- fix: 'Upgrade electron-builder to the latest version.',
161
- },
162
- 'xml2js': {
163
- reason: 'Versions below 0.5.0 are vulnerable to prototype pollution (CVE-2023-0842).',
164
- severity: 'high',
165
- safeAbove: '0.5.0',
166
- fix: 'Upgrade xml2js to >= 0.5.0.',
167
- },
168
- };
169
-
170
- // ─── Semver comparison helper ──────────────────────────────────────────────
171
-
172
- function parseSimpleVersion(v: string): number[] {
173
- // strips leading ^ ~ = v and returns [major, minor, patch]
174
- const clean = v.replace(/^[\^~=v]/, '').split('.');
175
- return clean.map(p => parseInt(p.replace(/\D.*/g, ''), 10) || 0);
176
- }
177
-
178
- function isBelow(installed: string, safeAbove: string): boolean {
179
- if (!installed || installed === '*' || installed === 'latest') return false;
180
- const a = parseSimpleVersion(installed);
181
- const b = parseSimpleVersion(safeAbove);
182
- for (let i = 0; i < 3; i++) {
183
- const ai = a[i] ?? 0;
184
- const bi = b[i] ?? 0;
185
- if (ai < bi) return true;
186
- if (ai > bi) return false;
187
- }
188
- return false; // equal means at the safe version
189
- }
190
-
191
- // ─── Missing security packages ─────────────────────────────────────────────
192
-
193
- function checkMissingSecurityPackages(
194
- allDeps: Record<string, string>,
195
- recommendations: string[],
196
- ): void {
197
- const hasExpress = 'express' in allDeps;
198
- const hasHelmet = 'helmet' in allDeps;
199
- const hasRateLimit =
200
- 'express-rate-limit' in allDeps || 'rate-limiter-flexible' in allDeps;
201
- const hasCors = 'cors' in allDeps;
202
- const hasHpp = 'hpp' in allDeps;
203
-
204
- if (hasExpress && !hasHelmet) {
205
- recommendations.push(
206
- 'Add helmet: sets security headers (CSP, HSTS, X-Frame-Options, etc.) — npm install helmet',
207
- );
208
- }
209
- if (hasExpress && !hasRateLimit) {
210
- recommendations.push(
211
- 'Add express-rate-limit: protect auth and API endpoints from brute-force — npm install express-rate-limit',
212
- );
213
- }
214
- if (hasExpress && hasCors && !hasHpp) {
215
- recommendations.push(
216
- 'Consider adding hpp to protect against HTTP Parameter Pollution attacks — npm install hpp',
217
- );
218
- }
219
- if (!('dotenv' in allDeps) && !('dotenv-safe' in allDeps)) {
220
- recommendations.push(
221
- 'Consider dotenv-safe to enforce required env variables at startup — npm install dotenv-safe',
222
- );
223
- }
224
- }
225
-
226
- // ─── Public API ────────────────────────────────────────────────────────────
227
-
228
- export function audit(packageJsonText: string): DependencyAuditResult {
229
- let parsed: Record<string, unknown>;
230
- try {
231
- parsed = JSON.parse(packageJsonText) as Record<string, unknown>;
232
- } catch {
233
- return {
234
- total_deps: 0,
235
- flagged: [],
236
- recommendations: ['Could not parse package.json — ensure it is valid JSON.'],
237
- score: 50,
238
- };
239
- }
240
-
241
- const deps = (parsed['dependencies'] ?? {}) as Record<string, string>;
242
- const devDeps = (parsed['devDependencies'] ?? {}) as Record<string, string>;
243
- const allDeps = { ...deps, ...devDeps };
244
- const total_deps = Object.keys(allDeps).length;
245
-
246
- const flagged: DependencyFlag[] = [];
247
- const recommendations: string[] = [
248
- 'Run npm audit --audit-level=high in CI and fail the build on violations.',
249
- 'Enable Dependabot or Renovate for automated security update PRs.',
250
- 'Use npm ci (not npm install) in CI to ensure lockfile integrity.',
251
- 'Separate devDependencies from dependencies; use --omit=dev in production.',
252
- 'Generate an SBOM with cyclonedx-npm for supply-chain transparency.',
253
- ];
254
-
255
- for (const [name, version] of Object.entries(allDeps)) {
256
- const issue = KNOWN_ISSUES[name];
257
- if (!issue) continue;
258
-
259
- if (issue.safeAbove) {
260
- // Only flag if the installed version appears to be below the safe threshold.
261
- // We do our best with semver string parsing; npm audit provides more accurate results.
262
- if (isBelow(version, issue.safeAbove)) {
263
- flagged.push({ name, version, reason: issue.reason, severity: issue.severity, fix: issue.fix });
264
- }
265
- } else {
266
- // Package is flagged regardless of version (deprecated / inherently unsafe)
267
- flagged.push({ name, version, reason: issue.reason, severity: issue.severity, fix: issue.fix });
268
- }
269
- }
270
-
271
- checkMissingSecurityPackages(allDeps, recommendations);
272
-
273
- // Scoring: start at 100, deduct per flagged item
274
- const critical = flagged.filter(f => f.severity === 'critical').length;
275
- const high = flagged.filter(f => f.severity === 'high').length;
276
- const medium = flagged.filter(f => f.severity === 'medium').length;
277
- const low = flagged.filter(f => f.severity === 'low').length;
278
-
279
- const raw = 100 - (critical * 25 + high * 10 + medium * 5 + low * 2);
280
- const score = Math.max(0, raw);
281
-
282
- return { total_deps, flagged, recommendations, score };
283
- }
284
-
285
- // ─── analyze() — AgentAnalysis wrapper for executor compatibility ──────────
286
- // The executor calls analyze(code, context) when task.code is provided.
287
- // For dependency-audit the "code" is expected to be the package.json text.
288
-
289
- export function analyze(code: string, context?: string): import('../types.js').AgentAnalysis {
290
- const result = audit(code);
291
- const subject = context ?? 'package.json';
292
-
293
- const findings: import('../types.js').AgentFinding[] = result.flagged.map(f => ({
294
- severity: f.severity,
295
- category: 'Dependency Security',
296
- description: `${f.name}@${f.version}: ${f.reason}`,
297
- fix: f.fix,
298
- cwe: 'CWE-1395',
299
- owasp: 'A06:2021',
300
- }));
301
-
302
- // Append recommendations as info-level findings
303
- for (const rec of result.recommendations) {
304
- findings.push({
305
- severity: 'info',
306
- category: 'Dependency Hygiene',
307
- description: rec,
308
- fix: rec,
309
- });
310
- }
311
-
312
- const critical_count = result.flagged.filter(f => f.severity === 'critical').length;
313
- const high_count = result.flagged.filter(f => f.severity === 'high').length;
314
- const medium_count = result.flagged.filter(f => f.severity === 'medium').length;
315
-
316
- const verdict: import('../types.js').AgentAnalysis['verdict'] =
317
- result.score >= 90 ? 'approved'
318
- : result.score >= 70 ? 'approved_with_warnings'
319
- : result.score >= 50 ? 'needs_revision'
320
- : 'rejected';
321
-
322
- const summary =
323
- result.flagged.length === 0
324
- ? `Dependency audit of ${subject} passed — ${result.total_deps} packages scanned, no known vulnerabilities. Score: ${result.score}/100.`
325
- : `Dependency audit of ${subject}: ${result.flagged.length} flagged package(s) out of ${result.total_deps} total. ${critical_count} critical, ${high_count} high, ${medium_count} medium. Score: ${result.score}/100 — ${verdict.replace(/_/g, ' ')}.`;
326
-
327
- return {
328
- agent: 'dependency-audit',
329
- subject,
330
- findings,
331
- score: result.score,
332
- verdict,
333
- summary,
334
- critical_count,
335
- high_count,
336
- };
337
- }