@brunosps00/dev-workflow 0.4.7 → 0.6.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 (64) hide show
  1. package/README.md +33 -6
  2. package/lib/constants.js +6 -0
  3. package/lib/install-deps.js +39 -1
  4. package/package.json +1 -1
  5. package/scaffold/en/commands/dw-adr.md +117 -0
  6. package/scaffold/en/commands/dw-autopilot.md +7 -0
  7. package/scaffold/en/commands/dw-brainstorm.md +6 -0
  8. package/scaffold/en/commands/dw-bugfix.md +9 -0
  9. package/scaffold/en/commands/dw-code-review.md +28 -0
  10. package/scaffold/en/commands/dw-create-tasks.md +12 -0
  11. package/scaffold/en/commands/dw-create-techspec.md +8 -0
  12. package/scaffold/en/commands/dw-fix-qa.md +5 -0
  13. package/scaffold/en/commands/dw-generate-pr.md +11 -0
  14. package/scaffold/en/commands/dw-help.md +44 -3
  15. package/scaffold/en/commands/dw-quick.md +8 -1
  16. package/scaffold/en/commands/dw-refactoring-analysis.md +1 -0
  17. package/scaffold/en/commands/dw-resume.md +10 -3
  18. package/scaffold/en/commands/dw-revert-task.md +114 -0
  19. package/scaffold/en/commands/dw-review-implementation.md +17 -0
  20. package/scaffold/en/commands/dw-run-plan.md +19 -1
  21. package/scaffold/en/commands/dw-run-task.md +14 -1
  22. package/scaffold/en/commands/dw-security-check.md +271 -0
  23. package/scaffold/en/commands/dw-update.md +39 -0
  24. package/scaffold/en/templates/adr-template.md +56 -0
  25. package/scaffold/en/templates/prd-template.md +12 -0
  26. package/scaffold/en/templates/task-template.md +12 -0
  27. package/scaffold/en/templates/tasks-template.md +6 -0
  28. package/scaffold/en/templates/techspec-template.md +12 -0
  29. package/scaffold/pt-br/commands/dw-adr.md +117 -0
  30. package/scaffold/pt-br/commands/dw-autopilot.md +7 -0
  31. package/scaffold/pt-br/commands/dw-brainstorm.md +6 -0
  32. package/scaffold/pt-br/commands/dw-bugfix.md +9 -0
  33. package/scaffold/pt-br/commands/dw-code-review.md +28 -0
  34. package/scaffold/pt-br/commands/dw-create-tasks.md +12 -0
  35. package/scaffold/pt-br/commands/dw-create-techspec.md +8 -0
  36. package/scaffold/pt-br/commands/dw-fix-qa.md +5 -0
  37. package/scaffold/pt-br/commands/dw-generate-pr.md +11 -0
  38. package/scaffold/pt-br/commands/dw-help.md +44 -3
  39. package/scaffold/pt-br/commands/dw-quick.md +8 -1
  40. package/scaffold/pt-br/commands/dw-refactoring-analysis.md +1 -0
  41. package/scaffold/pt-br/commands/dw-resume.md +10 -3
  42. package/scaffold/pt-br/commands/dw-revert-task.md +114 -0
  43. package/scaffold/pt-br/commands/dw-review-implementation.md +17 -0
  44. package/scaffold/pt-br/commands/dw-run-plan.md +19 -1
  45. package/scaffold/pt-br/commands/dw-run-task.md +14 -1
  46. package/scaffold/pt-br/commands/dw-security-check.md +271 -0
  47. package/scaffold/pt-br/commands/dw-update.md +40 -0
  48. package/scaffold/pt-br/templates/adr-template.md +56 -0
  49. package/scaffold/pt-br/templates/prd-template.md +12 -0
  50. package/scaffold/pt-br/templates/task-template.md +12 -0
  51. package/scaffold/pt-br/templates/tasks-template.md +6 -0
  52. package/scaffold/pt-br/templates/techspec-template.md +12 -0
  53. package/scaffold/skills/dw-council/SKILL.md +189 -0
  54. package/scaffold/skills/dw-council/agents/architect-advisor.md +44 -0
  55. package/scaffold/skills/dw-council/agents/devils-advocate.md +45 -0
  56. package/scaffold/skills/dw-council/agents/pragmatic-engineer.md +47 -0
  57. package/scaffold/skills/dw-council/agents/product-mind.md +48 -0
  58. package/scaffold/skills/dw-council/agents/security-advocate.md +48 -0
  59. package/scaffold/skills/dw-memory/SKILL.md +178 -0
  60. package/scaffold/skills/dw-review-rigor/SKILL.md +145 -0
  61. package/scaffold/skills/dw-verify/SKILL.md +196 -0
  62. package/scaffold/skills/security-review/languages/csharp.md +507 -0
  63. package/scaffold/skills/security-review/languages/rust.md +584 -0
  64. package/scaffold/skills/security-review/languages/typescript.md +373 -0
@@ -0,0 +1,373 @@
1
+ # TypeScript-Specific Security Patterns
2
+
3
+ This file complements `javascript.md` (which already covers React/Vue/Express/Next/Angular/Node XSS, injection, DOM sinks, prototype pollution). Here we focus on **TypeScript-specific** vulnerability classes: type-system abuses, runtime vs compile-time gap, TS-native ORMs, TS-native validators, and framework-specific patterns unique to TS ecosystems.
4
+
5
+ > Used by `/dw-security-check` as the primary reference when TS is detected in scope.
6
+
7
+ ---
8
+
9
+ ## The Compile-Time / Runtime Gap
10
+
11
+ TypeScript types are **erased at runtime**. Treating type annotations as validation is the most common security mistake in TS codebases.
12
+
13
+ ### Always Flag
14
+
15
+ ```ts
16
+ // FLAG CRITICAL: Type assertion on attacker-controlled input
17
+ const input = req.body as UserCreateDTO;
18
+ await db.user.create({ data: input }); // no runtime check — injection of extra fields
19
+
20
+ // FLAG CRITICAL: Chained "as unknown as X" to bypass checker
21
+ const user = rawJson as unknown as AdminUser; // laundering types
22
+
23
+ // FLAG HIGH: Non-null assertion on external input
24
+ const token = req.headers.authorization!.split(' ')[1]; // crash on undefined; often bypassed intent
25
+
26
+ // FLAG HIGH: any / unknown without narrowing
27
+ function handle(data: any) { db.$queryRawUnsafe(`... ${data.id}`); }
28
+ ```
29
+
30
+ ### Safe Patterns
31
+
32
+ ```ts
33
+ // Runtime validation via zod / yup / io-ts / typebox / class-validator
34
+ import { z } from 'zod';
35
+ const UserCreate = z.object({
36
+ email: z.string().email(),
37
+ age: z.number().int().positive().max(150),
38
+ });
39
+ const input = UserCreate.parse(req.body); // throws on invalid
40
+
41
+ // NestJS / class-validator
42
+ import { IsEmail, IsInt, Max } from 'class-validator';
43
+ class UserCreateDTO {
44
+ @IsEmail() email!: string;
45
+ @IsInt() @Max(150) age!: number;
46
+ }
47
+ // combined with ValidationPipe globally applied
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Prisma (TypeScript ORM)
53
+
54
+ ### Safe by Default
55
+
56
+ ```ts
57
+ // SAFE: Parameterized — Prisma binds values
58
+ await db.user.findMany({ where: { email: userInput } });
59
+ await db.$queryRaw`SELECT * FROM users WHERE email = ${userInput}`;
60
+ ```
61
+
62
+ ### Flag These
63
+
64
+ ```ts
65
+ // FLAG CRITICAL: $queryRawUnsafe with interpolation
66
+ await db.$queryRawUnsafe(`SELECT * FROM users WHERE email = '${userEmail}'`);
67
+
68
+ // FLAG HIGH: $executeRawUnsafe mutating
69
+ await db.$executeRawUnsafe(`UPDATE users SET role = '${role}' WHERE id = ${id}`);
70
+
71
+ // FLAG MEDIUM: select/where spread from req.body
72
+ await db.user.findMany({ where: req.body as any }); // attacker controls filter
73
+ ```
74
+
75
+ ---
76
+
77
+ ## TypeORM
78
+
79
+ ### Flag These
80
+
81
+ ```ts
82
+ // FLAG CRITICAL: raw query() with interpolation
83
+ await manager.query(`SELECT * FROM users WHERE id = ${userId}`);
84
+
85
+ // FLAG HIGH: QueryBuilder with unsafe where()
86
+ qb.where(`user.name = '${userName}'`); // not parameterized
87
+
88
+ // SAFE equivalents
89
+ await manager.query('SELECT * FROM users WHERE id = $1', [userId]);
90
+ qb.where('user.name = :name', { name: userName });
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Drizzle ORM
96
+
97
+ ### Flag These
98
+
99
+ ```ts
100
+ // FLAG CRITICAL: sql template with unchecked interpolation via `sql.raw()`
101
+ import { sql } from 'drizzle-orm';
102
+ db.execute(sql.raw(`SELECT * FROM users WHERE id = ${userId}`)); // raw() bypasses binding
103
+
104
+ // SAFE: sql tagged template binds values
105
+ db.execute(sql`SELECT * FROM users WHERE id = ${userId}`); // parameterized
106
+ ```
107
+
108
+ ---
109
+
110
+ ## NestJS
111
+
112
+ ### Flag These
113
+
114
+ ```ts
115
+ // FLAG HIGH: DTO without ValidationPipe or decorators
116
+ @Post() create(@Body() body: UserCreateDTO) { /* body is unvalidated */ }
117
+
118
+ // FLAG HIGH: raw ParseIntPipe missing on path param used in DB
119
+ @Get(':id') get(@Param('id') id: string) {
120
+ return db.$queryRawUnsafe(`SELECT * FROM u WHERE id = ${id}`);
121
+ }
122
+
123
+ // FLAG CRITICAL: @Public() or missing @UseGuards on sensitive routes
124
+ @Public() @Post('admin/reset-password') reset() { /* ... */ }
125
+
126
+ // FLAG HIGH: passthrough validation with "whitelist: false"
127
+ app.useGlobalPipes(new ValidationPipe({ whitelist: false })); // mass assignment risk
128
+ ```
129
+
130
+ ### Safe Baseline
131
+
132
+ ```ts
133
+ app.useGlobalPipes(new ValidationPipe({
134
+ whitelist: true, // drops unknown properties
135
+ forbidNonWhitelisted: true,
136
+ transform: true,
137
+ transformOptions: { enableImplicitConversion: false },
138
+ }));
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Secrets & Environment Variables (TS-specific)
144
+
145
+ ### Bundler Leaks
146
+
147
+ | Bundler | Public prefix (leaks to client bundle) |
148
+ |---------|----------------------------------------|
149
+ | Next.js | `NEXT_PUBLIC_*` |
150
+ | Vite | `VITE_*` |
151
+ | CRA | `REACT_APP_*` |
152
+ | Remix | process.env used in loaders is server-only; `window.ENV` if exposed |
153
+ | Nuxt | `NUXT_PUBLIC_*` |
154
+
155
+ ```ts
156
+ // FLAG CRITICAL: Secret in public-prefixed env
157
+ NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_... // ships to browser bundle
158
+
159
+ // FLAG HIGH: process.env accessed in client component without server boundary
160
+ 'use client';
161
+ const key = process.env.API_SECRET; // undefined OR leaked depending on bundler
162
+ ```
163
+
164
+ ### Unvalidated env
165
+
166
+ ```ts
167
+ // FLAG HIGH: process.env.X assumed to exist
168
+ const port = parseInt(process.env.PORT); // NaN on missing
169
+
170
+ // SAFE: t3-env / zod-based env validation at boot
171
+ import { z } from 'zod';
172
+ const env = z.object({ PORT: z.coerce.number().int().positive() }).parse(process.env);
173
+ ```
174
+
175
+ ---
176
+
177
+ ## JWT Handling in TS
178
+
179
+ ### Flag These
180
+
181
+ ```ts
182
+ // FLAG CRITICAL: jsonwebtoken.verify without explicit algorithms array
183
+ jwt.verify(token, secret); // allows "alg: none" if attacker controls header
184
+
185
+ // FLAG HIGH: decoded without verify
186
+ const payload = jwt.decode(token); // no signature check; decoration-only
187
+
188
+ // FLAG HIGH: tokens in localStorage from auth flow
189
+ localStorage.setItem('accessToken', token); // accessible to any XSS
190
+ ```
191
+
192
+ ### Safe Patterns
193
+
194
+ ```ts
195
+ jwt.verify(token, secret, { algorithms: ['HS256'] });
196
+
197
+ // httpOnly + Secure + SameSite=strict cookie via Set-Cookie on the server
198
+ res.cookie('accessToken', token, {
199
+ httpOnly: true, secure: true, sameSite: 'strict', maxAge: 15 * 60_000,
200
+ });
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Deserialization & Dynamic Evaluation
206
+
207
+ ```ts
208
+ // FLAG CRITICAL
209
+ eval(userInput);
210
+ new Function('arg', userInput);
211
+ vm.runInThisContext(userInput); // Node vm module
212
+ vm.runInNewContext(userInput, sandbox); // sandbox escape risk
213
+
214
+ // FLAG HIGH: JSON.parse without schema, then spread into ORM
215
+ const data = JSON.parse(body);
216
+ await db.user.update({ where: { id }, data }); // mass assignment
217
+
218
+ // FLAG HIGH: YAML load unsafe (js-yaml)
219
+ import yaml from 'js-yaml';
220
+ const cfg = yaml.load(userYaml); // default can instantiate custom types in older versions
221
+ // SAFE: yaml.load with CORE_SCHEMA / FAILSAFE_SCHEMA, or use js-yaml-secure-safe alternative
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Supply Chain (TS/JS specific)
227
+
228
+ ### Flag These
229
+
230
+ - `postinstall` / `prepare` scripts that fetch from network (`package.json`)
231
+ - Unpinned major versions on sensitive deps (`"express": "*"`)
232
+ - Missing `overrides` / `resolutions` when a transitive dep has a known CVE
233
+ - Typosquatting — double-check names on unfamiliar deps (historical incidents: `colors`, `node-ipc`, `event-stream`, `ua-parser-js`, `flatmap-stream`)
234
+ - `npm install` without lockfile (CI should use `npm ci` / `pnpm install --frozen-lockfile`)
235
+
236
+ ### Safe Patterns
237
+
238
+ ```json
239
+ // package.json
240
+ {
241
+ "overrides": { "semver": "^7.5.2" }, // force-patch transitive CVE
242
+ "pnpm": { "overrides": { "semver": "^7.5.2" } },
243
+ "scripts": { "preinstall": "npx only-allow pnpm" }
244
+ }
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Node-Specific (TS)
250
+
251
+ ```ts
252
+ // FLAG CRITICAL: child_process with concatenation
253
+ import { exec } from 'node:child_process';
254
+ exec(`git log ${userBranch}`); // shell injection via $(...) or ;
255
+
256
+ // SAFE: execFile with array args
257
+ import { execFile } from 'node:child_process';
258
+ execFile('git', ['log', userBranch]); // no shell
259
+
260
+ // FLAG HIGH: fs.readFile with user-controlled path
261
+ await fs.readFile(path.join('/var/data', userFile));
262
+ // SAFE: resolve + contained check
263
+ const resolved = path.resolve('/var/data', userFile);
264
+ if (!resolved.startsWith('/var/data/')) throw new Error('traversal');
265
+
266
+ // FLAG CRITICAL: dynamic require/import with user input
267
+ const mod = await import(`./plugins/${userPlugin}.js`);
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Browser-Specific (TS)
273
+
274
+ ```ts
275
+ // FLAG HIGH: postMessage without origin check
276
+ window.addEventListener('message', (e) => {
277
+ doThing(e.data); // no e.origin check
278
+ });
279
+
280
+ // FLAG HIGH: WebSocket without origin / token validation
281
+ const ws = new WebSocket(userUrl);
282
+
283
+ // FLAG MEDIUM: localStorage/sessionStorage with tokens + XSS surface
284
+ localStorage.setItem('refreshToken', token);
285
+
286
+ // FLAG HIGH: Service worker that caches opaque responses of auth'd endpoints
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Next.js 13/14 App Router Specific
292
+
293
+ ```ts
294
+ // FLAG CRITICAL: server action without auth check
295
+ 'use server';
296
+ export async function deleteUser(id: string) {
297
+ await db.user.delete({ where: { id } }); // no session check
298
+ }
299
+
300
+ // FLAG HIGH: cookies() used to construct SQL
301
+ import { cookies } from 'next/headers';
302
+ const role = cookies().get('role')?.value;
303
+ await db.$queryRawUnsafe(`SELECT * FROM admin WHERE role='${role}'`);
304
+
305
+ // FLAG MEDIUM: middleware without CSP/HSTS headers
306
+ // SAFE: next.config.js headers() or middleware.ts setting strict CSP
307
+ ```
308
+
309
+ ---
310
+
311
+ ## Research Checklist (before flagging)
312
+
313
+ For a suspected TS finding, check:
314
+
315
+ 1. **Is the value actually attacker-controlled?** — trace from HTTP request / external API / file upload. Values from env or config are not attacker-controlled.
316
+ 2. **Is there a validator upstream?** — search for `z.parse`, `yup.validateSync`, `class-validator`, `ajv.validate`, `ValidationPipe`.
317
+ 3. **Is the ORM method actually unsafe?** — Prisma is safe by default; only `$queryRawUnsafe` / `$executeRawUnsafe` / `sql.raw()` are flags.
318
+ 4. **Is the env var actually exposed to the client?** — check bundler prefix and whether the file is `'use client'`.
319
+ 5. **Is the JWT verified or just decoded?** — distinguish `verify` vs `decode`.
320
+ 6. **Is there CSRF protection?** — Next.js server actions, NestJS `@UseGuards`, `csurf` middleware.
321
+
322
+ Only report findings that pass the "attacker-controlled + no upstream mitigation + exploitable sink" test.
323
+
324
+ ---
325
+
326
+ ## Grep Patterns (TS-specific)
327
+
328
+ ```bash
329
+ # Type assertion on req/body/headers
330
+ grep -rn "req\.\(body\|params\|query\|headers\).*as " --include="*.ts" --include="*.tsx"
331
+
332
+ # as unknown as chain
333
+ grep -rn "as unknown as" --include="*.ts" --include="*.tsx"
334
+
335
+ # Non-null assertion on req/external
336
+ grep -rn "req\.\(body\|params\|query\|headers\).*!" --include="*.ts"
337
+
338
+ # Prisma unsafe
339
+ grep -rn "\$queryRawUnsafe\|\$executeRawUnsafe" --include="*.ts"
340
+
341
+ # Drizzle sql.raw
342
+ grep -rn "sql\.raw(" --include="*.ts"
343
+
344
+ # TypeORM raw query
345
+ grep -rn "\.query(\`" --include="*.ts"
346
+
347
+ # jwt without algorithms
348
+ grep -rn "jwt\.verify(" --include="*.ts" | grep -v "algorithms"
349
+
350
+ # server actions without auth (Next.js 13+)
351
+ grep -rn "'use server'" --include="*.ts" --include="*.tsx"
352
+
353
+ # Bundler-exposed env prefixes with suspicious names (secret/key/token/password)
354
+ grep -rEn "(NEXT_PUBLIC_|VITE_|REACT_APP_|NUXT_PUBLIC_)\w*(SECRET|KEY|TOKEN|PASS|PRIV)" --include="*.env*"
355
+
356
+ # zod schema presence (for context, not flag)
357
+ grep -rn "z\.object\|\.parse(" --include="*.ts"
358
+ ```
359
+
360
+ ---
361
+
362
+ ## Cross-Reference
363
+
364
+ For XSS/injection/CSRF/SSRF/crypto patterns that are NOT TS-specific, see:
365
+ - `../references/xss.md`
366
+ - `../references/injection.md`
367
+ - `../references/csrf.md`
368
+ - `../references/ssrf.md`
369
+ - `../references/cryptography.md`
370
+ - `../references/authentication.md`
371
+ - `../references/authorization.md`
372
+ - `../references/supply-chain.md`
373
+ - `./javascript.md` — React/Vue/Express/Angular/Node generic JS patterns