guardvibe 0.4.0 → 0.5.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 (54) hide show
  1. package/README.md +35 -14
  2. package/build/cli.js +1 -1
  3. package/build/data/framework-guides.d.ts.map +1 -1
  4. package/build/data/framework-guides.js +289 -0
  5. package/build/data/framework-guides.js.map +1 -1
  6. package/build/data/rules/cicd.d.ts +3 -0
  7. package/build/data/rules/cicd.d.ts.map +1 -0
  8. package/build/data/rules/cicd.js +47 -0
  9. package/build/data/rules/cicd.js.map +1 -0
  10. package/build/data/rules/core.d.ts.map +1 -1
  11. package/build/data/rules/core.js +26 -1
  12. package/build/data/rules/core.js.map +1 -1
  13. package/build/data/rules/dockerfile.d.ts +3 -0
  14. package/build/data/rules/dockerfile.d.ts.map +1 -0
  15. package/build/data/rules/dockerfile.js +58 -0
  16. package/build/data/rules/dockerfile.js.map +1 -0
  17. package/build/data/rules/go.d.ts.map +1 -1
  18. package/build/data/rules/go.js +6 -0
  19. package/build/data/rules/go.js.map +1 -1
  20. package/build/data/rules/index.d.ts.map +1 -1
  21. package/build/data/rules/index.js +4 -0
  22. package/build/data/rules/index.js.map +1 -1
  23. package/build/data/rules/java.d.ts.map +1 -1
  24. package/build/data/rules/java.js +6 -0
  25. package/build/data/rules/java.js.map +1 -1
  26. package/build/data/rules/php.d.ts.map +1 -1
  27. package/build/data/rules/php.js +5 -0
  28. package/build/data/rules/php.js.map +1 -1
  29. package/build/data/rules/ruby.d.ts.map +1 -1
  30. package/build/data/rules/ruby.js +5 -0
  31. package/build/data/rules/ruby.js.map +1 -1
  32. package/build/data/rules/types.d.ts +1 -0
  33. package/build/data/rules/types.d.ts.map +1 -1
  34. package/build/index.js +8 -2
  35. package/build/index.js.map +1 -1
  36. package/build/tools/check-code.d.ts +2 -2
  37. package/build/tools/check-code.d.ts.map +1 -1
  38. package/build/tools/check-code.js +10 -5
  39. package/build/tools/check-code.js.map +1 -1
  40. package/build/tools/check-project.d.ts.map +1 -1
  41. package/build/tools/check-project.js +10 -3
  42. package/build/tools/check-project.js.map +1 -1
  43. package/build/tools/scan-directory.d.ts.map +1 -1
  44. package/build/tools/scan-directory.js +13 -4
  45. package/build/tools/scan-directory.js.map +1 -1
  46. package/build/tools/scan-staged.d.ts +2 -0
  47. package/build/tools/scan-staged.d.ts.map +1 -0
  48. package/build/tools/scan-staged.js +119 -0
  49. package/build/tools/scan-staged.js.map +1 -0
  50. package/package.json +1 -1
  51. package/build/data/owasp-rules.d.ts +0 -12
  52. package/build/data/owasp-rules.d.ts.map +0 -1
  53. package/build/data/owasp-rules.js +0 -469
  54. package/build/data/owasp-rules.js.map +0 -1
package/README.md CHANGED
@@ -6,15 +6,19 @@ Stop shipping vulnerable code. GuardVibe checks your code against OWASP Top 10,
6
6
 
7
7
  ## Features
8
8
 
9
- - **Code Security Analysis** — Scans code for 45+ vulnerability patterns (SQL injection, XSS, hardcoded secrets, cloud API keys, CORS misconfig, and more)
10
- - **Directory Scanning** — Scan your entire project directory directly from the filesystem with security scoring (A-F grade)
11
- - **Secret Detection** — Pattern + entropy-based detection of leaked API keys, tokens, and credentials in code and config files
12
- - **Dependency CVE Check** — Parse lockfiles (package.json, requirements.txt, go.mod, Gemfile.lock, Cargo.lock) and batch-query Google's OSV database
13
- - **False Positive Suppression** — `// guardvibe-ignore VG001` comments to suppress known false positives
14
- - **Security Documentation** — Instant best-practice guides for Express, Next.js, FastAPI, React, and more
15
- - **8 Languages** — JavaScript, TypeScript, Python, Go, Java, PHP, Ruby, and more
16
- - **OWASP Top 10:2025** — All rules mapped to the latest OWASP standards
17
- - **Zero-Config Setup** — `npx guardvibe init claude` sets up everything automatically
9
+ - **Code Security Analysis** — 55+ vulnerability patterns with auto-fix code snippets
10
+ - **Directory Scanning** — Scan your entire project directly from the filesystem (A-F security score)
11
+ - **Pre-Commit Scanning** — Scan only git-staged files before committing
12
+ - **Secret Detection** — Pattern + entropy-based detection of leaked API keys, tokens, and credentials
13
+ - **Dockerfile Scanning** — Detect root containers, exposed secrets, unpinned images, COPY ordering
14
+ - **CI/CD Scanning** — GitHub Actions security: secrets in run steps, unpinned actions, permissions
15
+ - **Dependency CVE Check** — Parse lockfiles and batch-query Google's OSV database
16
+ - **Auto-Fix Code** — Every finding includes copy-paste-ready secure code
17
+ - **False Positive Suppression** — `// guardvibe-ignore VG001` comments
18
+ - **14 Security Guides** — Express, Next.js, FastAPI, Django, NestJS, Hono, Supabase, tRPC, React, and more
19
+ - **8 Languages + Dockerfile + YAML** — JS, TS, Python, Go, Java, PHP, Ruby, Dockerfile, GitHub Actions
20
+ - **OWASP Top 10:2025** — All rules mapped to latest standards
21
+ - **Zero-Config Setup** — `npx guardvibe init claude`
18
22
 
19
23
  ## Quick Start
20
24
 
@@ -85,6 +89,14 @@ Input: { topic: "express authentication" | "sql injection" | "nextjs csrf" | ...
85
89
  Output: Markdown guide with code examples
86
90
  ```
87
91
 
92
+ ### `scan_staged`
93
+ Scan git-staged files before committing. No input needed.
94
+
95
+ ```
96
+ Input: {} (automatic — reads git staged files)
97
+ Output: Pre-commit security report with A-F score
98
+ ```
99
+
88
100
  ### `scan_directory`
89
101
  Scan an entire project directory directly from the filesystem. No need to pass file contents.
90
102
 
@@ -131,8 +143,13 @@ Output: Vulnerability report with CVE IDs, severity, and fix versions
131
143
  | XSS | DOM sanitization, CSP, React escaping |
132
144
  | Authentication | bcrypt, JWT, OAuth, session security |
133
145
  | Environment Variables | .env management, Vercel, secret rotation |
146
+ | Django | CSRF, ORM, settings, ALLOWED_HOSTS, password hashing |
147
+ | NestJS | Guards, Helmet, ValidationPipe, rate limiting |
148
+ | Hono | Middleware auth, CORS, zod validation, secure headers |
149
+ | Supabase | Row Level Security, anon vs service key, auth |
150
+ | tRPC | Input validation, auth middleware, rate limiting |
134
151
 
135
- ## Security Rules (45+ patterns)
152
+ ## Security Rules (55+ patterns)
136
153
 
137
154
  ### Core Rules (All supported languages)
138
155
 
@@ -157,6 +174,8 @@ Output: Vulnerability report with CVE IDs, severity, and fix versions
157
174
  | VG120-VG125 | Java | SQL concat, Runtime.exec, JSP XSS, Spring auth, MessageDigest, @CrossOrigin |
158
175
  | VG130-VG134 | PHP | $_GET/$_POST SQL injection, shell_exec, echo XSS, md5/sha1, eval |
159
176
  | VG140-VG144 | Ruby | String interpolation SQL, backtick injection, html_safe XSS, route auth, Digest |
177
+ | VG200-VG204 | Dockerfile | Root container, COPY ordering, latest tag, secrets in ENV, ADD vs COPY |
178
+ | VG210-VG213 | GitHub Actions | Secrets in run steps, pull_request_target, unpinned actions, permissions |
160
179
 
161
180
  ## Suppressing False Positives
162
181
 
@@ -180,11 +199,13 @@ Supports `//`, `#`, and `<!-- -->` comment styles.
180
199
 
181
200
  GuardVibe runs as a local MCP server (stdio transport). When your AI assistant needs security guidance, it calls GuardVibe's tools:
182
201
 
183
- 1. **Writing code?** → `check_code` scans for vulnerability patterns
202
+ 1. **Writing code?** → `check_code` scans for vulnerability patterns with auto-fix
184
203
  2. **Reviewing a project?** → `scan_directory` scans your entire codebase
185
- 3. **Adding a package?** → `scan_dependencies` checks your lockfile for CVEs
186
- 4. **Worried about leaks?** → `scan_secrets` detects API keys and tokens
187
- 5. **Need guidance?** → `get_security_docs` returns best practices
204
+ 3. **About to commit?** → `scan_staged` checks only staged files
205
+ 4. **Adding a package?** → `scan_dependencies` checks your lockfile for CVEs
206
+ 5. **Worried about leaks?** → `scan_secrets` detects API keys and tokens
207
+ 6. **Building Docker?** → `check_code` with language `dockerfile` scans your Dockerfile
208
+ 7. **Need guidance?** → `get_security_docs` for 14 framework guides
188
209
 
189
210
  No API keys needed. No cloud dependency. Runs entirely on your machine.
190
211
 
package/build/cli.js CHANGED
@@ -57,7 +57,7 @@ function setupPlatform(name) {
57
57
  // Create new config
58
58
  writeJsonFile(platform.path, {
59
59
  mcpServers: {
60
- vibeguard: GUARDVIBE_MCP_CONFIG,
60
+ guardvibe: GUARDVIBE_MCP_CONFIG,
61
61
  },
62
62
  });
63
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"framework-guides.d.ts","sourceRoot":"","sources":["../../src/data/framework-guides.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD,eAAO,MAAM,eAAe,EAAE,aAAa,EAwf1C,CAAC"}
1
+ {"version":3,"file":"framework-guides.d.ts","sourceRoot":"","sources":["../../src/data/framework-guides.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD,eAAO,MAAM,eAAe,EAAE,aAAa,EA8xB1C,CAAC"}
@@ -496,5 +496,294 @@ When your AI generates code with hardcoded secrets:
496
496
  3. Add .env to .gitignore
497
497
  4. Tell your AI: "Use environment variables for secrets"`,
498
498
  },
499
+ {
500
+ topic: "django",
501
+ title: "Django Security Best Practices",
502
+ keywords: ["django", "python", "csrf", "orm", "settings", "allowed_hosts"],
503
+ content: `# Django Security Best Practices
504
+
505
+ ## Critical Settings
506
+ \`\`\`python
507
+ # settings.py
508
+ DEBUG = False # NEVER True in production
509
+ SECRET_KEY = os.environ['DJANGO_SECRET_KEY'] # Never hardcode
510
+ ALLOWED_HOSTS = ['myapp.com'] # Never use ['*']
511
+ SECURE_SSL_REDIRECT = True
512
+ SESSION_COOKIE_SECURE = True
513
+ CSRF_COOKIE_SECURE = True
514
+ SECURE_HSTS_SECONDS = 31536000
515
+ \`\`\`
516
+
517
+ ## CSRF Protection
518
+ Django includes CSRF middleware by default. Never disable it.
519
+ \`\`\`python
520
+ # Views that modify data need @csrf_protect or use CsrfViewMiddleware
521
+ from django.views.decorators.csrf import csrf_protect
522
+
523
+ @csrf_protect
524
+ def update_profile(request):
525
+ pass
526
+ \`\`\`
527
+
528
+ ## ORM Injection Prevention
529
+ Always use Django ORM — avoid raw SQL:
530
+ \`\`\`python
531
+ # Safe - ORM parameterizes automatically
532
+ User.objects.filter(name=user_input)
533
+
534
+ # Dangerous - raw SQL with interpolation
535
+ User.objects.raw(f"SELECT * FROM users WHERE name = '{user_input}'")
536
+
537
+ # If raw SQL needed, use params:
538
+ User.objects.raw("SELECT * FROM users WHERE name = %s", [user_input])
539
+ \`\`\`
540
+
541
+ ## Authentication
542
+ \`\`\`python
543
+ from django.contrib.auth.decorators import login_required
544
+
545
+ @login_required
546
+ def dashboard(request):
547
+ pass
548
+ \`\`\`
549
+
550
+ ## Password Hashing
551
+ Django uses PBKDF2 by default. Upgrade to Argon2:
552
+ \`\`\`python
553
+ # settings.py
554
+ PASSWORD_HASHERS = [
555
+ 'django.contrib.auth.hashers.Argon2PasswordHasher',
556
+ 'django.contrib.auth.hashers.PBKDF2PasswordHasher',
557
+ ]
558
+ \`\`\`
559
+ `,
560
+ },
561
+ {
562
+ topic: "nestjs",
563
+ title: "NestJS Security Best Practices",
564
+ keywords: ["nestjs", "nest", "guard", "pipe", "helmet", "validation"],
565
+ content: `# NestJS Security Best Practices
566
+
567
+ ## Helmet
568
+ \`\`\`typescript
569
+ import helmet from 'helmet';
570
+ app.use(helmet());
571
+ \`\`\`
572
+
573
+ ## CORS
574
+ \`\`\`typescript
575
+ app.enableCors({
576
+ origin: ['https://myapp.com'],
577
+ credentials: true,
578
+ });
579
+ \`\`\`
580
+
581
+ ## Validation Pipe (Global)
582
+ \`\`\`typescript
583
+ app.useGlobalPipes(new ValidationPipe({
584
+ whitelist: true, // Strip unknown properties
585
+ forbidNonWhitelisted: true,
586
+ transform: true,
587
+ }));
588
+ \`\`\`
589
+
590
+ ## Auth Guard
591
+ \`\`\`typescript
592
+ @Injectable()
593
+ export class AuthGuard implements CanActivate {
594
+ canActivate(context: ExecutionContext): boolean {
595
+ const request = context.switchToHttp().getRequest();
596
+ return validateToken(request.headers.authorization);
597
+ }
598
+ }
599
+
600
+ // Apply globally or per-route
601
+ @UseGuards(AuthGuard)
602
+ @Controller('api')
603
+ export class ApiController {}
604
+ \`\`\`
605
+
606
+ ## Rate Limiting
607
+ \`\`\`typescript
608
+ import { ThrottlerModule } from '@nestjs/throttler';
609
+ @Module({
610
+ imports: [ThrottlerModule.forRoot({ ttl: 60, limit: 10 })],
611
+ })
612
+ \`\`\`
613
+
614
+ ## Environment Variables
615
+ \`\`\`typescript
616
+ import { ConfigModule } from '@nestjs/config';
617
+ @Module({
618
+ imports: [ConfigModule.forRoot({ isGlobal: true })],
619
+ })
620
+ // Use: configService.get('DATABASE_URL')
621
+ \`\`\`
622
+ `,
623
+ },
624
+ {
625
+ topic: "hono",
626
+ title: "Hono Security Best Practices",
627
+ keywords: ["hono", "edge", "middleware", "cloudflare", "bun"],
628
+ content: `# Hono Security Best Practices
629
+
630
+ ## CORS
631
+ \`\`\`typescript
632
+ import { cors } from 'hono/cors';
633
+ app.use('*', cors({
634
+ origin: ['https://myapp.com'],
635
+ credentials: true,
636
+ }));
637
+ \`\`\`
638
+
639
+ ## Auth Middleware
640
+ \`\`\`typescript
641
+ import { bearerAuth } from 'hono/bearer-auth';
642
+ app.use('/api/*', bearerAuth({ token: process.env.API_TOKEN! }));
643
+
644
+ // Or custom JWT auth:
645
+ app.use('/api/*', async (c, next) => {
646
+ const token = c.req.header('Authorization')?.replace('Bearer ', '');
647
+ if (!token || !verifyJwt(token)) return c.json({ error: 'Unauthorized' }, 401);
648
+ await next();
649
+ });
650
+ \`\`\`
651
+
652
+ ## Input Validation
653
+ \`\`\`typescript
654
+ import { zValidator } from '@hono/zod-validator';
655
+ import { z } from 'zod';
656
+
657
+ app.post('/api/users', zValidator('json', z.object({
658
+ email: z.string().email(),
659
+ name: z.string().min(1).max(100),
660
+ })), async (c) => {
661
+ const data = c.req.valid('json');
662
+ });
663
+ \`\`\`
664
+
665
+ ## Rate Limiting
666
+ \`\`\`typescript
667
+ import { rateLimiter } from 'hono-rate-limiter';
668
+ app.use(rateLimiter({ windowMs: 15 * 60 * 1000, limit: 100 }));
669
+ \`\`\`
670
+
671
+ ## Secure Headers
672
+ \`\`\`typescript
673
+ import { secureHeaders } from 'hono/secure-headers';
674
+ app.use('*', secureHeaders());
675
+ \`\`\`
676
+ `,
677
+ },
678
+ {
679
+ topic: "supabase",
680
+ title: "Supabase Security Best Practices",
681
+ keywords: ["supabase", "rls", "row level security", "postgres", "auth"],
682
+ content: `# Supabase Security Best Practices
683
+
684
+ ## Row Level Security (RLS) — CRITICAL
685
+ Always enable RLS on every table:
686
+ \`\`\`sql
687
+ ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
688
+
689
+ -- Users can only read their own profile
690
+ CREATE POLICY "Users read own profile"
691
+ ON profiles FOR SELECT
692
+ USING (auth.uid() = user_id);
693
+
694
+ -- Users can only update their own profile
695
+ CREATE POLICY "Users update own profile"
696
+ ON profiles FOR UPDATE
697
+ USING (auth.uid() = user_id);
698
+ \`\`\`
699
+
700
+ ## Anon Key vs Service Key
701
+ \`\`\`typescript
702
+ // Client-side: use anon key (safe to expose, RLS enforced)
703
+ const supabase = createClient(url, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!);
704
+
705
+ // Server-side only: service key (bypasses RLS!)
706
+ const admin = createClient(url, process.env.SUPABASE_SERVICE_KEY!);
707
+ // NEVER expose service key to the client
708
+ \`\`\`
709
+
710
+ ## Auth
711
+ \`\`\`typescript
712
+ // Always check auth on server
713
+ const { data: { user } } = await supabase.auth.getUser();
714
+ if (!user) throw new Error('Unauthorized');
715
+ \`\`\`
716
+
717
+ ## API Security
718
+ \`\`\`typescript
719
+ // Validate input before database operations
720
+ const schema = z.object({ title: z.string().max(200) });
721
+ const input = schema.parse(body);
722
+ await supabase.from('posts').insert(input);
723
+ \`\`\`
724
+ `,
725
+ },
726
+ {
727
+ topic: "trpc",
728
+ title: "tRPC Security Best Practices",
729
+ keywords: ["trpc", "procedure", "middleware", "zod", "typesafe"],
730
+ content: `# tRPC Security Best Practices
731
+
732
+ ## Input Validation
733
+ Always validate with zod:
734
+ \`\`\`typescript
735
+ export const appRouter = router({
736
+ createUser: publicProcedure
737
+ .input(z.object({
738
+ email: z.string().email(),
739
+ name: z.string().min(1).max(100),
740
+ }))
741
+ .mutation(async ({ input }) => {
742
+ // input is validated and typed
743
+ }),
744
+ });
745
+ \`\`\`
746
+
747
+ ## Auth Middleware
748
+ \`\`\`typescript
749
+ const isAuthed = t.middleware(({ ctx, next }) => {
750
+ if (!ctx.session?.user) {
751
+ throw new TRPCError({ code: 'UNAUTHORIZED' });
752
+ }
753
+ return next({ ctx: { user: ctx.session.user } });
754
+ });
755
+
756
+ const protectedProcedure = t.procedure.use(isAuthed);
757
+
758
+ // Use for protected routes
759
+ export const appRouter = router({
760
+ getProfile: protectedProcedure.query(({ ctx }) => {
761
+ return db.user.findUnique({ where: { id: ctx.user.id } });
762
+ }),
763
+ });
764
+ \`\`\`
765
+
766
+ ## Rate Limiting
767
+ \`\`\`typescript
768
+ const rateLimiter = t.middleware(async ({ ctx, next }) => {
769
+ const ip = ctx.req.headers['x-forwarded-for'] || 'unknown';
770
+ const { success } = await ratelimit.limit(ip);
771
+ if (!success) throw new TRPCError({ code: 'TOO_MANY_REQUESTS' });
772
+ return next();
773
+ });
774
+ \`\`\`
775
+
776
+ ## Error Handling
777
+ Never expose internal errors:
778
+ \`\`\`typescript
779
+ // tRPC automatically masks internal errors in production
780
+ // Only TRPCError messages are sent to client
781
+ throw new TRPCError({
782
+ code: 'BAD_REQUEST',
783
+ message: 'Invalid input', // Safe user-facing message
784
+ });
785
+ \`\`\`
786
+ `,
787
+ },
499
788
  ];
500
789
  //# sourceMappingURL=framework-guides.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"framework-guides.js","sourceRoot":"","sources":["../../src/data/framework-guides.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"framework-guides.js","sourceRoot":"","sources":["../../src/data/framework-guides.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityRule } from "./types.js";
2
+ export declare const cicdRules: SecurityRule[];
3
+ //# sourceMappingURL=cicd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cicd.d.ts","sourceRoot":"","sources":["../../../src/data/rules/cicd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,SAAS,EAAE,YAAY,EA6CnC,CAAC"}
@@ -0,0 +1,47 @@
1
+ export const cicdRules = [
2
+ {
3
+ id: "VG210",
4
+ name: "Secrets interpolated in run step",
5
+ severity: "critical",
6
+ owasp: "A01:2025 Broken Access Control",
7
+ description: "GitHub Actions secrets interpolated directly in run steps can leak via process logs or error messages.",
8
+ pattern: /run:\s*.*\$\{\{\s*secrets\./gi,
9
+ languages: ["yaml"],
10
+ fix: "Pass secrets as environment variables instead of interpolating in run steps.",
11
+ fixCode: "# Pass secrets via env, not interpolation\nsteps:\n - run: echo \"deploying\"\n env:\n MY_SECRET: ${{ secrets.MY_SECRET }}",
12
+ },
13
+ {
14
+ id: "VG211",
15
+ name: "pull_request_target with checkout",
16
+ severity: "critical",
17
+ owasp: "A01:2025 Broken Access Control",
18
+ description: "Using pull_request_target with actions/checkout allows untrusted PR code to access secrets.",
19
+ pattern: /pull_request_target[\s\S]*?actions\/checkout/gi,
20
+ languages: ["yaml"],
21
+ fix: "Use pull_request trigger instead, or avoid checking out PR code with pull_request_target.",
22
+ fixCode: "# Use pull_request instead of pull_request_target\non:\n pull_request:\n branches: [main]",
23
+ },
24
+ {
25
+ id: "VG212",
26
+ name: "Unpinned action version",
27
+ severity: "medium",
28
+ owasp: "A03:2025 Software Supply Chain Failures",
29
+ description: "Using @main or @master for GitHub Actions allows untested code changes to affect your pipeline.",
30
+ pattern: /uses:\s*\S+@(?:main|master)\s/gi,
31
+ languages: ["yaml"],
32
+ fix: "Pin actions to a specific commit SHA or version tag.",
33
+ fixCode: "# Pin to specific version or SHA\nuses: actions/checkout@v4\n# Or pin to commit SHA:\n# uses: actions/checkout@abc123def456",
34
+ },
35
+ {
36
+ id: "VG213",
37
+ name: "Overly permissive permissions",
38
+ severity: "high",
39
+ owasp: "A01:2025 Broken Access Control",
40
+ description: "write-all permissions give the workflow full access to the repository. Use least-privilege permissions.",
41
+ pattern: /permissions:\s*write-all/gi,
42
+ languages: ["yaml"],
43
+ fix: "Specify minimum required permissions for each job.",
44
+ fixCode: "# Use least-privilege permissions\npermissions:\n contents: read\n pull-requests: write",
45
+ },
46
+ ];
47
+ //# sourceMappingURL=cicd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cicd.js","sourceRoot":"","sources":["../../../src/data/rules/cicd.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAmB;IACvC;QACE,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,kCAAkC;QACxC,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,gCAAgC;QACvC,WAAW,EAAE,wGAAwG;QACrH,OAAO,EAAE,+BAA+B;QACxC,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,GAAG,EAAE,8EAA8E;QACnF,OAAO,EAAE,qIAAqI;KAC/I;IACD;QACE,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,mCAAmC;QACzC,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,gCAAgC;QACvC,WAAW,EAAE,6FAA6F;QAC1G,OAAO,EAAE,gDAAgD;QACzD,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,GAAG,EAAE,2FAA2F;QAChG,OAAO,EAAE,+FAA+F;KACzG;IACD;QACE,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,yBAAyB;QAC/B,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,yCAAyC;QAChD,WAAW,EAAE,iGAAiG;QAC9G,OAAO,EAAE,iCAAiC;QAC1C,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,GAAG,EAAE,sDAAsD;QAC3D,OAAO,EAAE,6HAA6H;KACvI;IACD;QACE,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,+BAA+B;QACrC,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,gCAAgC;QACvC,WAAW,EAAE,yGAAyG;QACtH,OAAO,EAAE,4BAA4B;QACrC,SAAS,EAAE,CAAC,MAAM,CAAC;QACnB,GAAG,EAAE,oDAAoD;QACzD,OAAO,EAAE,2FAA2F;KACrG;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/data/rules/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,eAAO,MAAM,SAAS,EAAE,YAAY,EAmRnC,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/data/rules/core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,eAAO,MAAM,SAAS,EAAE,YAAY,EA4SnC,CAAC"}