@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.
- package/README.md +33 -6
- package/lib/constants.js +6 -0
- package/lib/install-deps.js +39 -1
- package/package.json +1 -1
- package/scaffold/en/commands/dw-adr.md +117 -0
- package/scaffold/en/commands/dw-autopilot.md +7 -0
- package/scaffold/en/commands/dw-brainstorm.md +6 -0
- package/scaffold/en/commands/dw-bugfix.md +9 -0
- package/scaffold/en/commands/dw-code-review.md +28 -0
- package/scaffold/en/commands/dw-create-tasks.md +12 -0
- package/scaffold/en/commands/dw-create-techspec.md +8 -0
- package/scaffold/en/commands/dw-fix-qa.md +5 -0
- package/scaffold/en/commands/dw-generate-pr.md +11 -0
- package/scaffold/en/commands/dw-help.md +44 -3
- package/scaffold/en/commands/dw-quick.md +8 -1
- package/scaffold/en/commands/dw-refactoring-analysis.md +1 -0
- package/scaffold/en/commands/dw-resume.md +10 -3
- package/scaffold/en/commands/dw-revert-task.md +114 -0
- package/scaffold/en/commands/dw-review-implementation.md +17 -0
- package/scaffold/en/commands/dw-run-plan.md +19 -1
- package/scaffold/en/commands/dw-run-task.md +14 -1
- package/scaffold/en/commands/dw-security-check.md +271 -0
- package/scaffold/en/commands/dw-update.md +39 -0
- package/scaffold/en/templates/adr-template.md +56 -0
- package/scaffold/en/templates/prd-template.md +12 -0
- package/scaffold/en/templates/task-template.md +12 -0
- package/scaffold/en/templates/tasks-template.md +6 -0
- package/scaffold/en/templates/techspec-template.md +12 -0
- package/scaffold/pt-br/commands/dw-adr.md +117 -0
- package/scaffold/pt-br/commands/dw-autopilot.md +7 -0
- package/scaffold/pt-br/commands/dw-brainstorm.md +6 -0
- package/scaffold/pt-br/commands/dw-bugfix.md +9 -0
- package/scaffold/pt-br/commands/dw-code-review.md +28 -0
- package/scaffold/pt-br/commands/dw-create-tasks.md +12 -0
- package/scaffold/pt-br/commands/dw-create-techspec.md +8 -0
- package/scaffold/pt-br/commands/dw-fix-qa.md +5 -0
- package/scaffold/pt-br/commands/dw-generate-pr.md +11 -0
- package/scaffold/pt-br/commands/dw-help.md +44 -3
- package/scaffold/pt-br/commands/dw-quick.md +8 -1
- package/scaffold/pt-br/commands/dw-refactoring-analysis.md +1 -0
- package/scaffold/pt-br/commands/dw-resume.md +10 -3
- package/scaffold/pt-br/commands/dw-revert-task.md +114 -0
- package/scaffold/pt-br/commands/dw-review-implementation.md +17 -0
- package/scaffold/pt-br/commands/dw-run-plan.md +19 -1
- package/scaffold/pt-br/commands/dw-run-task.md +14 -1
- package/scaffold/pt-br/commands/dw-security-check.md +271 -0
- package/scaffold/pt-br/commands/dw-update.md +40 -0
- package/scaffold/pt-br/templates/adr-template.md +56 -0
- package/scaffold/pt-br/templates/prd-template.md +12 -0
- package/scaffold/pt-br/templates/task-template.md +12 -0
- package/scaffold/pt-br/templates/tasks-template.md +6 -0
- package/scaffold/pt-br/templates/techspec-template.md +12 -0
- package/scaffold/skills/dw-council/SKILL.md +189 -0
- package/scaffold/skills/dw-council/agents/architect-advisor.md +44 -0
- package/scaffold/skills/dw-council/agents/devils-advocate.md +45 -0
- package/scaffold/skills/dw-council/agents/pragmatic-engineer.md +47 -0
- package/scaffold/skills/dw-council/agents/product-mind.md +48 -0
- package/scaffold/skills/dw-council/agents/security-advocate.md +48 -0
- package/scaffold/skills/dw-memory/SKILL.md +178 -0
- package/scaffold/skills/dw-review-rigor/SKILL.md +145 -0
- package/scaffold/skills/dw-verify/SKILL.md +196 -0
- package/scaffold/skills/security-review/languages/csharp.md +507 -0
- package/scaffold/skills/security-review/languages/rust.md +584 -0
- 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
|