thuban 0.4.10 → 0.4.11
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/LICENSE +21 -21
- package/README.md +437 -437
- package/dist/LICENSE +21 -0
- package/dist/README.md +437 -0
- package/dist/cli.js +2 -0
- package/dist/package.json +63 -0
- package/dist/packages/crucible/.golden/golden-master.json +414 -0
- package/dist/packages/crucible/report-generator.js +1 -0
- package/dist/packages/crucible/rules/code-scanner-core.json +303 -0
- package/dist/packages/crucible/rules/command-injection.json +411 -0
- package/dist/packages/crucible/rules/crypto-misuse.json +35 -0
- package/dist/packages/crucible/rules/deserialization.json +152 -0
- package/dist/packages/crucible/rules/env-injection.json +46 -0
- package/dist/packages/crucible/rules/eval-abuse.json +104 -0
- package/dist/packages/crucible/rules/file-upload.json +46 -0
- package/dist/packages/crucible/rules/hallucination.json +22 -0
- package/dist/packages/crucible/rules/hardcoded-secret.json +397 -0
- package/dist/packages/crucible/rules/hardcoded-url.json +13 -0
- package/dist/packages/crucible/rules/insecure-crypto.json +302 -0
- package/dist/packages/crucible/rules/integer-overflow.json +35 -0
- package/dist/packages/crucible/rules/log-injection.json +33 -0
- package/dist/packages/crucible/rules/mass-assignment.json +112 -0
- package/dist/packages/crucible/rules/open-redirect.json +196 -0
- package/dist/packages/crucible/rules/path-traversal.json +422 -0
- package/dist/packages/crucible/rules/prototype-pollution.json +22 -0
- package/dist/packages/crucible/rules/sql-injection.json +619 -0
- package/dist/packages/crucible/rules/ssrf.json +557 -0
- package/dist/packages/crucible/rules/timing-attack.json +55 -0
- package/dist/packages/crucible/rules/unsafe-block.json +24 -0
- package/dist/packages/crucible/rules/xss.json +663 -0
- package/dist/packages/crucible/rules/xxe.json +66 -0
- package/dist/packages/crucible/rules/yaml-deserialization.json +22 -0
- package/dist/packages/crucible/rules/yaml-injection.json +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-001.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-002.cs +24 -0
- package/dist/packages/crucible/seeds/csharp/seed-003.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-004.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-005.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-006.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-007.cs +34 -0
- package/dist/packages/crucible/seeds/csharp/seed-008.cs +23 -0
- package/dist/packages/crucible/seeds/csharp/seed-009.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-010.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-011.cs +32 -0
- package/dist/packages/crucible/seeds/csharp/seed-012.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-013.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-014.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-015.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-016.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-017.cs +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-018.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-019.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-020.cs +22 -0
- package/dist/packages/crucible/seeds/csharp/seed-021.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-022.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-023.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-024.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-025.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-026.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-027.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-028.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-029.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-030.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-031.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-032.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-033.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-034.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-035.cs +32 -0
- package/dist/packages/crucible/seeds/csharp/seed-036.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-037.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-038.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-039.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-040.cs +28 -0
- package/dist/packages/crucible/seeds/csharp/seed-041.cs +33 -0
- package/dist/packages/crucible/seeds/csharp/seed-042.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-043.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-044.cs +25 -0
- package/dist/packages/crucible/seeds/csharp/seed-045.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-046.cs +29 -0
- package/dist/packages/crucible/seeds/csharp/seed-047.cs +26 -0
- package/dist/packages/crucible/seeds/csharp/seed-048.cs +31 -0
- package/dist/packages/crucible/seeds/csharp/seed-049.cs +27 -0
- package/dist/packages/crucible/seeds/csharp/seed-050.cs +30 -0
- package/dist/packages/crucible/seeds/csharp/seed-051.cs +34 -0
- package/dist/packages/crucible/seeds/csharp/seed-052.cs +36 -0
- package/dist/packages/crucible/seeds/go/seed-001.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-002.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-003.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-004.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-005.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-006.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-007.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-008.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-009.go +30 -0
- package/dist/packages/crucible/seeds/go/seed-010.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-011.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-012.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-013.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-014.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-015.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-016.go +19 -0
- package/dist/packages/crucible/seeds/go/seed-017.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-018.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-019.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-020.go +31 -0
- package/dist/packages/crucible/seeds/go/seed-021.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-022.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-023.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-024.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-025.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-026.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-027.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-028.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-029.go +28 -0
- package/dist/packages/crucible/seeds/go/seed-030.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-031.go +28 -0
- package/dist/packages/crucible/seeds/go/seed-032.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-033.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-034.go +22 -0
- package/dist/packages/crucible/seeds/go/seed-035.go +32 -0
- package/dist/packages/crucible/seeds/go/seed-036.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-037.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-038.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-039.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-040.go +37 -0
- package/dist/packages/crucible/seeds/go/seed-041.go +23 -0
- package/dist/packages/crucible/seeds/go/seed-042.go +32 -0
- package/dist/packages/crucible/seeds/go/seed-043.go +35 -0
- package/dist/packages/crucible/seeds/go/seed-044.go +25 -0
- package/dist/packages/crucible/seeds/go/seed-045.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-046.go +34 -0
- package/dist/packages/crucible/seeds/go/seed-047.go +26 -0
- package/dist/packages/crucible/seeds/go/seed-048.go +29 -0
- package/dist/packages/crucible/seeds/go/seed-049.go +24 -0
- package/dist/packages/crucible/seeds/go/seed-050.go +27 -0
- package/dist/packages/crucible/seeds/go/seed-051.go +38 -0
- package/dist/packages/crucible/seeds/go/seed-052.go +27 -0
- package/dist/packages/crucible/seeds/java/seed-001.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-002.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-003.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-004.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-005.java +33 -0
- package/dist/packages/crucible/seeds/java/seed-006.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-007.java +21 -0
- package/dist/packages/crucible/seeds/java/seed-008.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-009.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-010.java +30 -0
- package/dist/packages/crucible/seeds/java/seed-011.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-012.java +20 -0
- package/dist/packages/crucible/seeds/java/seed-013.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-014.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-015.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-016.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-017.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-018.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-019.java +38 -0
- package/dist/packages/crucible/seeds/java/seed-020.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-021.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-022.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-023.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-024.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-025.java +27 -0
- package/dist/packages/crucible/seeds/java/seed-026.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-027.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-028.java +21 -0
- package/dist/packages/crucible/seeds/java/seed-029.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-030.java +27 -0
- package/dist/packages/crucible/seeds/java/seed-031.java +23 -0
- package/dist/packages/crucible/seeds/java/seed-032.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-033.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-034.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-035.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-036.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-037.java +30 -0
- package/dist/packages/crucible/seeds/java/seed-038.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-039.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-040.java +31 -0
- package/dist/packages/crucible/seeds/java/seed-041.java +20 -0
- package/dist/packages/crucible/seeds/java/seed-042.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-043.java +31 -0
- package/dist/packages/crucible/seeds/java/seed-044.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-045.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-046.java +22 -0
- package/dist/packages/crucible/seeds/java/seed-047.java +26 -0
- package/dist/packages/crucible/seeds/java/seed-048.java +24 -0
- package/dist/packages/crucible/seeds/java/seed-049.java +28 -0
- package/dist/packages/crucible/seeds/java/seed-050.java +29 -0
- package/dist/packages/crucible/seeds/java/seed-051.java +25 -0
- package/dist/packages/crucible/seeds/java/seed-052.java +32 -0
- package/dist/packages/crucible/seeds/js/seed-001.js +27 -0
- package/dist/packages/crucible/seeds/js/seed-002.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-003.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-004.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-005.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-006.js +28 -0
- package/dist/packages/crucible/seeds/js/seed-007.js +26 -0
- package/dist/packages/crucible/seeds/js/seed-008.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-009.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-010.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-011.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-012.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-013.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-014.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-015.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-016.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-017.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-018.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-019.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-020.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-021.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-022.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-023.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-024.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-025.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-026.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-027.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-028.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-029.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-030.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-031.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-032.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-033.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-034.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-035.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-036.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-037.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-038.js +31 -0
- package/dist/packages/crucible/seeds/js/seed-039.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-040.js +35 -0
- package/dist/packages/crucible/seeds/js/seed-041.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-042.js +32 -0
- package/dist/packages/crucible/seeds/js/seed-043.js +27 -0
- package/dist/packages/crucible/seeds/js/seed-044.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-045.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-046.js +33 -0
- package/dist/packages/crucible/seeds/js/seed-047.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-048.js +29 -0
- package/dist/packages/crucible/seeds/js/seed-049.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-050.js +34 -0
- package/dist/packages/crucible/seeds/js/seed-051.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-052.js +30 -0
- package/dist/packages/crucible/seeds/js/seed-053.js +26 -0
- package/dist/packages/crucible/seeds/js/seed-054.js +35 -0
- package/dist/packages/crucible/seeds/js/seed-055.js +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-001.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-002.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-003.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-004.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-005.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-006.kt +21 -0
- package/dist/packages/crucible/seeds/kotlin/seed-007.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-008.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-009.kt +21 -0
- package/dist/packages/crucible/seeds/kotlin/seed-010.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-011.kt +22 -0
- package/dist/packages/crucible/seeds/kotlin/seed-012.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-013.kt +30 -0
- package/dist/packages/crucible/seeds/kotlin/seed-014.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-015.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-016.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-017.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-018.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-019.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-020.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-021.kt +34 -0
- package/dist/packages/crucible/seeds/kotlin/seed-022.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-023.kt +20 -0
- package/dist/packages/crucible/seeds/kotlin/seed-024.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-025.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-026.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-027.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-028.kt +24 -0
- package/dist/packages/crucible/seeds/kotlin/seed-029.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-030.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-031.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-032.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-033.kt +30 -0
- package/dist/packages/crucible/seeds/kotlin/seed-034.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-035.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-036.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-037.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-038.kt +25 -0
- package/dist/packages/crucible/seeds/kotlin/seed-039.kt +29 -0
- package/dist/packages/crucible/seeds/kotlin/seed-040.kt +28 -0
- package/dist/packages/crucible/seeds/kotlin/seed-041.kt +31 -0
- package/dist/packages/crucible/seeds/kotlin/seed-042.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-043.kt +26 -0
- package/dist/packages/crucible/seeds/kotlin/seed-044.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-045.kt +27 -0
- package/dist/packages/crucible/seeds/kotlin/seed-046.kt +33 -0
- package/dist/packages/crucible/seeds/kotlin/seed-047.kt +32 -0
- package/dist/packages/crucible/seeds/kotlin/seed-048.kt +20 -0
- package/dist/packages/crucible/seeds/kotlin/seed-049.kt +23 -0
- package/dist/packages/crucible/seeds/kotlin/seed-050.kt +19 -0
- package/dist/packages/crucible/seeds/php/seed-001.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-002.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-003.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-004.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-005.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-006.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-007.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-008.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-009.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-010.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-011.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-012.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-013.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-014.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-015.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-016.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-017.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-018.php +17 -0
- package/dist/packages/crucible/seeds/php/seed-019.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-020.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-021.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-022.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-023.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-024.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-025.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-026.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-027.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-028.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-029.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-030.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-031.php +23 -0
- package/dist/packages/crucible/seeds/php/seed-032.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-033.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-034.php +24 -0
- package/dist/packages/crucible/seeds/php/seed-035.php +22 -0
- package/dist/packages/crucible/seeds/php/seed-036.php +17 -0
- package/dist/packages/crucible/seeds/php/seed-037.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-038.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-039.php +15 -0
- package/dist/packages/crucible/seeds/php/seed-040.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-041.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-042.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-043.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-044.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-045.php +25 -0
- package/dist/packages/crucible/seeds/php/seed-046.php +20 -0
- package/dist/packages/crucible/seeds/php/seed-047.php +21 -0
- package/dist/packages/crucible/seeds/php/seed-048.php +19 -0
- package/dist/packages/crucible/seeds/php/seed-049.php +18 -0
- package/dist/packages/crucible/seeds/php/seed-050.php +20 -0
- package/dist/packages/crucible/seeds/python/seed-001.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-002.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-003.py +31 -0
- package/dist/packages/crucible/seeds/python/seed-004.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-005.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-006.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-007.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-008.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-009.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-010.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-011.py +30 -0
- package/dist/packages/crucible/seeds/python/seed-012.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-013.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-014.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-015.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-016.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-017.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-018.py +30 -0
- package/dist/packages/crucible/seeds/python/seed-019.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-020.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-021.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-022 2.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-022.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-023 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-023.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-024 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-024.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-025 2.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-025.py +40 -0
- package/dist/packages/crucible/seeds/python/seed-026 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-026.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-027.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-028 2.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-028.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-029.py +42 -0
- package/dist/packages/crucible/seeds/python/seed-030 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-030.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-031 2.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-031.py +34 -0
- package/dist/packages/crucible/seeds/python/seed-032.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-033.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-034.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-035.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-036 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-036.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-037 2.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-037.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-038 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-038.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-039 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-039.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-040.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-041 2.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-041.py +37 -0
- package/dist/packages/crucible/seeds/python/seed-042 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-042.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-043 2.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-043.py +32 -0
- package/dist/packages/crucible/seeds/python/seed-044 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-044.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-045 2.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-045.py +36 -0
- package/dist/packages/crucible/seeds/python/seed-046 2.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-046.py +33 -0
- package/dist/packages/crucible/seeds/python/seed-047 2.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-047.py +44 -0
- package/dist/packages/crucible/seeds/python/seed-048 2.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-048.py +35 -0
- package/dist/packages/crucible/seeds/python/seed-049 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-049.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050 2.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-050.py +39 -0
- package/dist/packages/crucible/seeds/python/seed-051 2.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-051.py +38 -0
- package/dist/packages/crucible/seeds/python/seed-052 2.py +41 -0
- package/dist/packages/crucible/seeds/python/seed-052.py +41 -0
- package/dist/packages/crucible/seeds/ruby/seed-001 2.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-001.rb +15 -0
- package/dist/packages/crucible/seeds/ruby/seed-002 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-002.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-003 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-003.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-004 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-004.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-005 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-005.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-006 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-006.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-007 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-007.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-008 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-008.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-009 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-009.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-010 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-010.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-011 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-011.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-012 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-012.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-013 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-013.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-014 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-014.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-015 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-015.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-016 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-016.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-017 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-017.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-018 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-018.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-019 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-019.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-020 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-020.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-021 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-021.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-022 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-022.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-023 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-023.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-024 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-024.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-025.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-026 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-026.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-027 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-027.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-028 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-028.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-029 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-029.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-030 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-030.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-031 2.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-031.rb +17 -0
- package/dist/packages/crucible/seeds/ruby/seed-032 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-032.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-033 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-033.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-034 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-034.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035 2.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-035.rb +19 -0
- package/dist/packages/crucible/seeds/ruby/seed-036 2.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-036.rb +18 -0
- package/dist/packages/crucible/seeds/ruby/seed-037 2.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-037.rb +21 -0
- package/dist/packages/crucible/seeds/ruby/seed-038 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-038.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-039.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-040 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-040.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-041 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-041.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-042 2.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-042.rb +25 -0
- package/dist/packages/crucible/seeds/ruby/seed-043 2.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-043.rb +23 -0
- package/dist/packages/crucible/seeds/ruby/seed-044 2.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-044.rb +16 -0
- package/dist/packages/crucible/seeds/ruby/seed-045 2.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-045.rb +22 -0
- package/dist/packages/crucible/seeds/ruby/seed-046 2.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-046.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-047 2.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-047.rb +26 -0
- package/dist/packages/crucible/seeds/ruby/seed-048 2.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-048.rb +24 -0
- package/dist/packages/crucible/seeds/ruby/seed-049 2.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-049.rb +20 -0
- package/dist/packages/crucible/seeds/ruby/seed-050 2.rb +27 -0
- package/dist/packages/crucible/seeds/ruby/seed-050.rb +27 -0
- package/dist/packages/crucible/seeds/rust/seed-001 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-001.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-002 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-002.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-003 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-003.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-004 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-004.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-005.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-006 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-006.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-007 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-007.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-008 2.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-008.rs +19 -0
- package/dist/packages/crucible/seeds/rust/seed-009 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-009.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-010.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-011 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-011.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-012 2.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-012.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-013 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-013.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-014 2.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-014.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-015 2.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-015.rs +33 -0
- package/dist/packages/crucible/seeds/rust/seed-016 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-016.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-017 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-017.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-018 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-018.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-019 2.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-019.rs +36 -0
- package/dist/packages/crucible/seeds/rust/seed-020 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-020.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-021 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-021.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-022 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-022.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-023 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-023.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-024 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-024.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-025 2.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-025.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-026 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-026.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-027 2.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-027.rs +24 -0
- package/dist/packages/crucible/seeds/rust/seed-028 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-028.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-029.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-030 2.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-030.rs +30 -0
- package/dist/packages/crucible/seeds/rust/seed-031 2.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-031.rs +22 -0
- package/dist/packages/crucible/seeds/rust/seed-032 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-032.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-033.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-034 2.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-034.rs +20 -0
- package/dist/packages/crucible/seeds/rust/seed-035 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-035.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-036 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-036.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-037 2.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-037.rs +31 -0
- package/dist/packages/crucible/seeds/rust/seed-038 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-038.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-039 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-039.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-040 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-040.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-041 2.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-041.rs +32 -0
- package/dist/packages/crucible/seeds/rust/seed-042 2.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-042.rs +27 -0
- package/dist/packages/crucible/seeds/rust/seed-043 2.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-043.rs +29 -0
- package/dist/packages/crucible/seeds/rust/seed-044 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-044.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-045 2.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-045.rs +28 -0
- package/dist/packages/crucible/seeds/rust/seed-046 2.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-046.rs +25 -0
- package/dist/packages/crucible/seeds/rust/seed-047 2.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-047.rs +34 -0
- package/dist/packages/crucible/seeds/rust/seed-048 2.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-048.rs +21 -0
- package/dist/packages/crucible/seeds/rust/seed-049 2.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-049.rs +26 -0
- package/dist/packages/crucible/seeds/rust/seed-050 2.rs +23 -0
- package/dist/packages/crucible/seeds/rust/seed-050.rs +23 -0
- package/dist/packages/crucible/seeds/ts/seed-001 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-001.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-002 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-002.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-003 2.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-003.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-004 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-004.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-005 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-005.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-006 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-006.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-007 2.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-007.ts +28 -0
- package/dist/packages/crucible/seeds/ts/seed-008 2.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-008.ts +40 -0
- package/dist/packages/crucible/seeds/ts/seed-009 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-009.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-010 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-010.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-011 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-011.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-012 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-012.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-013 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-013.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-014 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-014.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-015 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-015.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-016 2.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-016.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-017 2.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-017.ts +44 -0
- package/dist/packages/crucible/seeds/ts/seed-018 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-018.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-019 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-019.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-020 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-020.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-021.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-022 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-022.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-023 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-023.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-024 2.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-024.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-025 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-025.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-026 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-026.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-027 2.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-027.ts +30 -0
- package/dist/packages/crucible/seeds/ts/seed-028 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-028.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-029 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-029.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-030 2.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-030.ts +37 -0
- package/dist/packages/crucible/seeds/ts/seed-031 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-031.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-032 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-032.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-033.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-034 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-034.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-035 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-035.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-036 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-036.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-037 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-037.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-038 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-038.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-039 2.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-039.ts +35 -0
- package/dist/packages/crucible/seeds/ts/seed-040 2.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-040.ts +31 -0
- package/dist/packages/crucible/seeds/ts/seed-041 2.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-041.ts +29 -0
- package/dist/packages/crucible/seeds/ts/seed-042 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-042.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-043 2.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-043.ts +32 -0
- package/dist/packages/crucible/seeds/ts/seed-044 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-044.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-045 2.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-045.ts +39 -0
- package/dist/packages/crucible/seeds/ts/seed-046 2.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-046.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-047 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-047.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048 2.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-048.ts +33 -0
- package/dist/packages/crucible/seeds/ts/seed-049 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-049.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-050 2.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-050.ts +41 -0
- package/dist/packages/crucible/seeds/ts/seed-051 2.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-051.ts +34 -0
- package/dist/packages/crucible/seeds/ts/seed-052 2.ts +36 -0
- package/dist/packages/crucible/seeds/ts/seed-052.ts +36 -0
- package/dist/packages/scanner/alert-manager.js +1 -0
- package/dist/packages/scanner/architecture-map.js +1 -0
- package/dist/packages/scanner/ast-analyzer.js +1 -0
- package/dist/packages/scanner/benchmarks.js +1 -0
- package/dist/packages/scanner/cfg-analyzer.js +1 -0
- package/dist/packages/scanner/code-scanner.js +1 -0
- package/dist/packages/scanner/compliance-mapper.js +1 -0
- package/dist/packages/scanner/file-collector.js +1 -0
- package/dist/packages/scanner/file-watcher.js +1 -0
- package/dist/packages/scanner/ghost-code-detector.js +1 -0
- package/dist/packages/scanner/git-velocity.js +1 -0
- package/dist/packages/scanner/hallucination-detector.js +1 -0
- package/dist/packages/scanner/health-checker.js +1 -0
- package/dist/packages/scanner/investor-report.js +1 -0
- package/dist/packages/scanner/json-file-util.js +1 -0
- package/dist/packages/scanner/monitor-store.js +1 -0
- package/dist/packages/scanner/python_ast_helper.py +426 -0
- package/dist/packages/scanner/risk-valuation.js +1 -0
- package/dist/packages/scanner/scan-history.js +1 -0
- package/dist/packages/scanner/secret-scanner.js +1 -0
- package/dist/packages/scanner/sentinel-core.js +1 -0
- package/dist/packages/scanner/supply-chain.js +1 -0
- package/dist/packages/scanner/support-bot.js +1 -0
- package/dist/packages/scanner/support-knowledge.js +1 -0
- package/dist/packages/scanner/taint-tracker.js +1 -0
- package/package.json +15 -13
- package/cli.js +0 -2
- package/packages/crucible/.golden/golden-master.json +0 -414
- package/packages/crucible/README.md +0 -93
- package/packages/crucible/report-generator.js +0 -1
- package/packages/crucible/rules/code-scanner-core.json +0 -281
- package/packages/crucible/rules/command-injection.json +0 -411
- package/packages/crucible/rules/crypto-misuse.json +0 -35
- package/packages/crucible/rules/deserialization.json +0 -152
- package/packages/crucible/rules/env-injection.json +0 -46
- package/packages/crucible/rules/eval-abuse.json +0 -104
- package/packages/crucible/rules/file-upload.json +0 -46
- package/packages/crucible/rules/hallucination.json +0 -22
- package/packages/crucible/rules/hardcoded-secret.json +0 -397
- package/packages/crucible/rules/hardcoded-url.json +0 -13
- package/packages/crucible/rules/insecure-crypto.json +0 -302
- package/packages/crucible/rules/integer-overflow.json +0 -35
- package/packages/crucible/rules/log-injection.json +0 -33
- package/packages/crucible/rules/mass-assignment.json +0 -112
- package/packages/crucible/rules/open-redirect.json +0 -196
- package/packages/crucible/rules/path-traversal.json +0 -422
- package/packages/crucible/rules/prototype-pollution.json +0 -22
- package/packages/crucible/rules/sql-injection.json +0 -619
- package/packages/crucible/rules/ssrf.json +0 -557
- package/packages/crucible/rules/timing-attack.json +0 -55
- package/packages/crucible/rules/unsafe-block.json +0 -24
- package/packages/crucible/rules/xss.json +0 -663
- package/packages/crucible/rules/xxe.json +0 -66
- package/packages/crucible/rules/yaml-deserialization.json +0 -22
- package/packages/crucible/rules/yaml-injection.json +0 -22
- package/packages/crucible/seeds/csharp/seed-001.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-002.cs +0 -24
- package/packages/crucible/seeds/csharp/seed-003.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-004.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-005.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-006.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-007.cs +0 -34
- package/packages/crucible/seeds/csharp/seed-008.cs +0 -23
- package/packages/crucible/seeds/csharp/seed-009.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-010.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-011.cs +0 -32
- package/packages/crucible/seeds/csharp/seed-012.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-013.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-014.cs +0 -26
- package/packages/crucible/seeds/csharp/seed-015.cs +0 -33
- package/packages/crucible/seeds/csharp/seed-016.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-017.cs +0 -22
- package/packages/crucible/seeds/csharp/seed-018.cs +0 -26
- package/packages/crucible/seeds/csharp/seed-019.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-020.cs +0 -22
- package/packages/crucible/seeds/csharp/seed-021.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-022.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-023.cs +0 -33
- package/packages/crucible/seeds/csharp/seed-024.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-025.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-026.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-027.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-028.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-029.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-030.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-031.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-032.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-033.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-034.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-035.cs +0 -32
- package/packages/crucible/seeds/csharp/seed-036.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-037.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-038.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-039.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-040.cs +0 -28
- package/packages/crucible/seeds/csharp/seed-041.cs +0 -33
- package/packages/crucible/seeds/csharp/seed-042.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-043.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-044.cs +0 -25
- package/packages/crucible/seeds/csharp/seed-045.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-046.cs +0 -29
- package/packages/crucible/seeds/csharp/seed-047.cs +0 -26
- package/packages/crucible/seeds/csharp/seed-048.cs +0 -31
- package/packages/crucible/seeds/csharp/seed-049.cs +0 -27
- package/packages/crucible/seeds/csharp/seed-050.cs +0 -30
- package/packages/crucible/seeds/csharp/seed-051.cs +0 -34
- package/packages/crucible/seeds/csharp/seed-052.cs +0 -36
- package/packages/crucible/seeds/go/seed-001.go +0 -29
- package/packages/crucible/seeds/go/seed-002.go +0 -27
- package/packages/crucible/seeds/go/seed-003.go +0 -31
- package/packages/crucible/seeds/go/seed-004.go +0 -27
- package/packages/crucible/seeds/go/seed-005.go +0 -27
- package/packages/crucible/seeds/go/seed-006.go +0 -29
- package/packages/crucible/seeds/go/seed-007.go +0 -24
- package/packages/crucible/seeds/go/seed-008.go +0 -25
- package/packages/crucible/seeds/go/seed-009.go +0 -30
- package/packages/crucible/seeds/go/seed-010.go +0 -35
- package/packages/crucible/seeds/go/seed-011.go +0 -24
- package/packages/crucible/seeds/go/seed-012.go +0 -24
- package/packages/crucible/seeds/go/seed-013.go +0 -31
- package/packages/crucible/seeds/go/seed-014.go +0 -35
- package/packages/crucible/seeds/go/seed-015.go +0 -25
- package/packages/crucible/seeds/go/seed-016.go +0 -19
- package/packages/crucible/seeds/go/seed-017.go +0 -23
- package/packages/crucible/seeds/go/seed-018.go +0 -23
- package/packages/crucible/seeds/go/seed-019.go +0 -22
- package/packages/crucible/seeds/go/seed-020.go +0 -31
- package/packages/crucible/seeds/go/seed-021.go +0 -22
- package/packages/crucible/seeds/go/seed-022.go +0 -29
- package/packages/crucible/seeds/go/seed-023.go +0 -26
- package/packages/crucible/seeds/go/seed-024.go +0 -27
- package/packages/crucible/seeds/go/seed-025.go +0 -23
- package/packages/crucible/seeds/go/seed-026.go +0 -29
- package/packages/crucible/seeds/go/seed-027.go +0 -26
- package/packages/crucible/seeds/go/seed-028.go +0 -23
- package/packages/crucible/seeds/go/seed-029.go +0 -28
- package/packages/crucible/seeds/go/seed-030.go +0 -27
- package/packages/crucible/seeds/go/seed-031.go +0 -28
- package/packages/crucible/seeds/go/seed-032.go +0 -27
- package/packages/crucible/seeds/go/seed-033.go +0 -29
- package/packages/crucible/seeds/go/seed-034.go +0 -22
- package/packages/crucible/seeds/go/seed-035.go +0 -32
- package/packages/crucible/seeds/go/seed-036.go +0 -27
- package/packages/crucible/seeds/go/seed-037.go +0 -27
- package/packages/crucible/seeds/go/seed-038.go +0 -27
- package/packages/crucible/seeds/go/seed-039.go +0 -26
- package/packages/crucible/seeds/go/seed-040.go +0 -37
- package/packages/crucible/seeds/go/seed-041.go +0 -23
- package/packages/crucible/seeds/go/seed-042.go +0 -32
- package/packages/crucible/seeds/go/seed-043.go +0 -35
- package/packages/crucible/seeds/go/seed-044.go +0 -25
- package/packages/crucible/seeds/go/seed-045.go +0 -26
- package/packages/crucible/seeds/go/seed-046.go +0 -34
- package/packages/crucible/seeds/go/seed-047.go +0 -26
- package/packages/crucible/seeds/go/seed-048.go +0 -29
- package/packages/crucible/seeds/go/seed-049.go +0 -24
- package/packages/crucible/seeds/go/seed-050.go +0 -27
- package/packages/crucible/seeds/go/seed-051.go +0 -38
- package/packages/crucible/seeds/go/seed-052.go +0 -27
- package/packages/crucible/seeds/java/seed-001.java +0 -23
- package/packages/crucible/seeds/java/seed-002.java +0 -22
- package/packages/crucible/seeds/java/seed-003.java +0 -28
- package/packages/crucible/seeds/java/seed-004.java +0 -26
- package/packages/crucible/seeds/java/seed-005.java +0 -33
- package/packages/crucible/seeds/java/seed-006.java +0 -22
- package/packages/crucible/seeds/java/seed-007.java +0 -21
- package/packages/crucible/seeds/java/seed-008.java +0 -29
- package/packages/crucible/seeds/java/seed-009.java +0 -24
- package/packages/crucible/seeds/java/seed-010.java +0 -30
- package/packages/crucible/seeds/java/seed-011.java +0 -25
- package/packages/crucible/seeds/java/seed-012.java +0 -20
- package/packages/crucible/seeds/java/seed-013.java +0 -26
- package/packages/crucible/seeds/java/seed-014.java +0 -23
- package/packages/crucible/seeds/java/seed-015.java +0 -25
- package/packages/crucible/seeds/java/seed-016.java +0 -22
- package/packages/crucible/seeds/java/seed-017.java +0 -24
- package/packages/crucible/seeds/java/seed-018.java +0 -24
- package/packages/crucible/seeds/java/seed-019.java +0 -38
- package/packages/crucible/seeds/java/seed-020.java +0 -24
- package/packages/crucible/seeds/java/seed-021.java +0 -22
- package/packages/crucible/seeds/java/seed-022.java +0 -22
- package/packages/crucible/seeds/java/seed-023.java +0 -22
- package/packages/crucible/seeds/java/seed-024.java +0 -25
- package/packages/crucible/seeds/java/seed-025.java +0 -27
- package/packages/crucible/seeds/java/seed-026.java +0 -25
- package/packages/crucible/seeds/java/seed-027.java +0 -22
- package/packages/crucible/seeds/java/seed-028.java +0 -21
- package/packages/crucible/seeds/java/seed-029.java +0 -28
- package/packages/crucible/seeds/java/seed-030.java +0 -27
- package/packages/crucible/seeds/java/seed-031.java +0 -23
- package/packages/crucible/seeds/java/seed-032.java +0 -22
- package/packages/crucible/seeds/java/seed-033.java +0 -24
- package/packages/crucible/seeds/java/seed-034.java +0 -24
- package/packages/crucible/seeds/java/seed-035.java +0 -29
- package/packages/crucible/seeds/java/seed-036.java +0 -25
- package/packages/crucible/seeds/java/seed-037.java +0 -30
- package/packages/crucible/seeds/java/seed-038.java +0 -29
- package/packages/crucible/seeds/java/seed-039.java +0 -26
- package/packages/crucible/seeds/java/seed-040.java +0 -31
- package/packages/crucible/seeds/java/seed-041.java +0 -20
- package/packages/crucible/seeds/java/seed-042.java +0 -26
- package/packages/crucible/seeds/java/seed-043.java +0 -31
- package/packages/crucible/seeds/java/seed-044.java +0 -22
- package/packages/crucible/seeds/java/seed-045.java +0 -25
- package/packages/crucible/seeds/java/seed-046.java +0 -22
- package/packages/crucible/seeds/java/seed-047.java +0 -26
- package/packages/crucible/seeds/java/seed-048.java +0 -24
- package/packages/crucible/seeds/java/seed-049.java +0 -28
- package/packages/crucible/seeds/java/seed-050.java +0 -29
- package/packages/crucible/seeds/java/seed-051.java +0 -25
- package/packages/crucible/seeds/java/seed-052.java +0 -32
- package/packages/crucible/seeds/js/seed-001.js +0 -27
- package/packages/crucible/seeds/js/seed-002.js +0 -28
- package/packages/crucible/seeds/js/seed-003.js +0 -30
- package/packages/crucible/seeds/js/seed-004.js +0 -28
- package/packages/crucible/seeds/js/seed-005.js +0 -31
- package/packages/crucible/seeds/js/seed-006.js +0 -28
- package/packages/crucible/seeds/js/seed-007.js +0 -26
- package/packages/crucible/seeds/js/seed-008.js +0 -30
- package/packages/crucible/seeds/js/seed-009.js +0 -30
- package/packages/crucible/seeds/js/seed-010.js +0 -29
- package/packages/crucible/seeds/js/seed-011.js +0 -34
- package/packages/crucible/seeds/js/seed-012.js +0 -32
- package/packages/crucible/seeds/js/seed-013.js +0 -29
- package/packages/crucible/seeds/js/seed-014.js +0 -29
- package/packages/crucible/seeds/js/seed-015.js +0 -31
- package/packages/crucible/seeds/js/seed-016.js +0 -31
- package/packages/crucible/seeds/js/seed-017.js +0 -30
- package/packages/crucible/seeds/js/seed-018.js +0 -29
- package/packages/crucible/seeds/js/seed-019.js +0 -32
- package/packages/crucible/seeds/js/seed-020.js +0 -29
- package/packages/crucible/seeds/js/seed-021.js +0 -31
- package/packages/crucible/seeds/js/seed-022.js +0 -31
- package/packages/crucible/seeds/js/seed-023.js +0 -29
- package/packages/crucible/seeds/js/seed-024.js +0 -29
- package/packages/crucible/seeds/js/seed-025.js +0 -34
- package/packages/crucible/seeds/js/seed-026.js +0 -31
- package/packages/crucible/seeds/js/seed-027.js +0 -31
- package/packages/crucible/seeds/js/seed-028.js +0 -33
- package/packages/crucible/seeds/js/seed-029.js +0 -33
- package/packages/crucible/seeds/js/seed-030.js +0 -30
- package/packages/crucible/seeds/js/seed-031.js +0 -31
- package/packages/crucible/seeds/js/seed-032.js +0 -34
- package/packages/crucible/seeds/js/seed-033.js +0 -33
- package/packages/crucible/seeds/js/seed-034.js +0 -33
- package/packages/crucible/seeds/js/seed-035.js +0 -30
- package/packages/crucible/seeds/js/seed-036.js +0 -30
- package/packages/crucible/seeds/js/seed-037.js +0 -29
- package/packages/crucible/seeds/js/seed-038.js +0 -31
- package/packages/crucible/seeds/js/seed-039.js +0 -34
- package/packages/crucible/seeds/js/seed-040.js +0 -35
- package/packages/crucible/seeds/js/seed-041.js +0 -32
- package/packages/crucible/seeds/js/seed-042.js +0 -32
- package/packages/crucible/seeds/js/seed-043.js +0 -27
- package/packages/crucible/seeds/js/seed-044.js +0 -29
- package/packages/crucible/seeds/js/seed-045.js +0 -33
- package/packages/crucible/seeds/js/seed-046.js +0 -33
- package/packages/crucible/seeds/js/seed-047.js +0 -29
- package/packages/crucible/seeds/js/seed-048.js +0 -29
- package/packages/crucible/seeds/js/seed-049.js +0 -34
- package/packages/crucible/seeds/js/seed-050.js +0 -34
- package/packages/crucible/seeds/js/seed-051.js +0 -30
- package/packages/crucible/seeds/js/seed-052.js +0 -30
- package/packages/crucible/seeds/js/seed-053.js +0 -26
- package/packages/crucible/seeds/js/seed-054.js +0 -35
- package/packages/crucible/seeds/js/seed-055.js +0 -33
- package/packages/crucible/seeds/kotlin/seed-001.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-002.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-003.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-004.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-005.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-006.kt +0 -21
- package/packages/crucible/seeds/kotlin/seed-007.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-008.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-009.kt +0 -21
- package/packages/crucible/seeds/kotlin/seed-010.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-011.kt +0 -22
- package/packages/crucible/seeds/kotlin/seed-012.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-013.kt +0 -30
- package/packages/crucible/seeds/kotlin/seed-014.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-015.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-016.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-017.kt +0 -33
- package/packages/crucible/seeds/kotlin/seed-018.kt +0 -31
- package/packages/crucible/seeds/kotlin/seed-019.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-020.kt +0 -31
- package/packages/crucible/seeds/kotlin/seed-021.kt +0 -34
- package/packages/crucible/seeds/kotlin/seed-022.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-023.kt +0 -20
- package/packages/crucible/seeds/kotlin/seed-024.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-025.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-026.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-027.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-028.kt +0 -24
- package/packages/crucible/seeds/kotlin/seed-029.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-030.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-031.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-032.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-033.kt +0 -30
- package/packages/crucible/seeds/kotlin/seed-034.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-035.kt +0 -33
- package/packages/crucible/seeds/kotlin/seed-036.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-037.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-038.kt +0 -25
- package/packages/crucible/seeds/kotlin/seed-039.kt +0 -29
- package/packages/crucible/seeds/kotlin/seed-040.kt +0 -28
- package/packages/crucible/seeds/kotlin/seed-041.kt +0 -31
- package/packages/crucible/seeds/kotlin/seed-042.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-043.kt +0 -26
- package/packages/crucible/seeds/kotlin/seed-044.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-045.kt +0 -27
- package/packages/crucible/seeds/kotlin/seed-046.kt +0 -33
- package/packages/crucible/seeds/kotlin/seed-047.kt +0 -32
- package/packages/crucible/seeds/kotlin/seed-048.kt +0 -20
- package/packages/crucible/seeds/kotlin/seed-049.kt +0 -23
- package/packages/crucible/seeds/kotlin/seed-050.kt +0 -19
- package/packages/crucible/seeds/php/seed-001.php +0 -23
- package/packages/crucible/seeds/php/seed-002.php +0 -18
- package/packages/crucible/seeds/php/seed-003.php +0 -25
- package/packages/crucible/seeds/php/seed-004.php +0 -21
- package/packages/crucible/seeds/php/seed-005.php +0 -21
- package/packages/crucible/seeds/php/seed-006.php +0 -21
- package/packages/crucible/seeds/php/seed-007.php +0 -18
- package/packages/crucible/seeds/php/seed-008.php +0 -19
- package/packages/crucible/seeds/php/seed-009.php +0 -24
- package/packages/crucible/seeds/php/seed-010.php +0 -24
- package/packages/crucible/seeds/php/seed-011.php +0 -18
- package/packages/crucible/seeds/php/seed-012.php +0 -24
- package/packages/crucible/seeds/php/seed-013.php +0 -23
- package/packages/crucible/seeds/php/seed-014.php +0 -20
- package/packages/crucible/seeds/php/seed-015.php +0 -18
- package/packages/crucible/seeds/php/seed-016.php +0 -18
- package/packages/crucible/seeds/php/seed-017.php +0 -18
- package/packages/crucible/seeds/php/seed-018.php +0 -17
- package/packages/crucible/seeds/php/seed-019.php +0 -24
- package/packages/crucible/seeds/php/seed-020.php +0 -19
- package/packages/crucible/seeds/php/seed-021.php +0 -22
- package/packages/crucible/seeds/php/seed-022.php +0 -15
- package/packages/crucible/seeds/php/seed-023.php +0 -24
- package/packages/crucible/seeds/php/seed-024.php +0 -22
- package/packages/crucible/seeds/php/seed-025.php +0 -20
- package/packages/crucible/seeds/php/seed-026.php +0 -22
- package/packages/crucible/seeds/php/seed-027.php +0 -15
- package/packages/crucible/seeds/php/seed-028.php +0 -15
- package/packages/crucible/seeds/php/seed-029.php +0 -21
- package/packages/crucible/seeds/php/seed-030.php +0 -21
- package/packages/crucible/seeds/php/seed-031.php +0 -23
- package/packages/crucible/seeds/php/seed-032.php +0 -18
- package/packages/crucible/seeds/php/seed-033.php +0 -18
- package/packages/crucible/seeds/php/seed-034.php +0 -24
- package/packages/crucible/seeds/php/seed-035.php +0 -22
- package/packages/crucible/seeds/php/seed-036.php +0 -17
- package/packages/crucible/seeds/php/seed-037.php +0 -19
- package/packages/crucible/seeds/php/seed-038.php +0 -20
- package/packages/crucible/seeds/php/seed-039.php +0 -15
- package/packages/crucible/seeds/php/seed-040.php +0 -21
- package/packages/crucible/seeds/php/seed-041.php +0 -20
- package/packages/crucible/seeds/php/seed-042.php +0 -21
- package/packages/crucible/seeds/php/seed-043.php +0 -21
- package/packages/crucible/seeds/php/seed-044.php +0 -25
- package/packages/crucible/seeds/php/seed-045.php +0 -25
- package/packages/crucible/seeds/php/seed-046.php +0 -20
- package/packages/crucible/seeds/php/seed-047.php +0 -21
- package/packages/crucible/seeds/php/seed-048.php +0 -19
- package/packages/crucible/seeds/php/seed-049.php +0 -18
- package/packages/crucible/seeds/php/seed-050.php +0 -20
- package/packages/crucible/seeds/python/seed-001.py +0 -33
- package/packages/crucible/seeds/python/seed-002.py +0 -39
- package/packages/crucible/seeds/python/seed-003.py +0 -31
- package/packages/crucible/seeds/python/seed-004.py +0 -33
- package/packages/crucible/seeds/python/seed-005.py +0 -33
- package/packages/crucible/seeds/python/seed-006.py +0 -34
- package/packages/crucible/seeds/python/seed-007.py +0 -33
- package/packages/crucible/seeds/python/seed-008.py +0 -38
- package/packages/crucible/seeds/python/seed-009.py +0 -38
- package/packages/crucible/seeds/python/seed-010.py +0 -42
- package/packages/crucible/seeds/python/seed-011.py +0 -30
- package/packages/crucible/seeds/python/seed-012.py +0 -35
- package/packages/crucible/seeds/python/seed-013.py +0 -33
- package/packages/crucible/seeds/python/seed-014.py +0 -40
- package/packages/crucible/seeds/python/seed-015.py +0 -33
- package/packages/crucible/seeds/python/seed-016.py +0 -34
- package/packages/crucible/seeds/python/seed-017.py +0 -34
- package/packages/crucible/seeds/python/seed-018.py +0 -30
- package/packages/crucible/seeds/python/seed-019.py +0 -33
- package/packages/crucible/seeds/python/seed-020.py +0 -37
- package/packages/crucible/seeds/python/seed-021 2.py +0 -37
- package/packages/crucible/seeds/python/seed-021.py +0 -37
- package/packages/crucible/seeds/python/seed-022 2.py +0 -34
- package/packages/crucible/seeds/python/seed-022.py +0 -34
- package/packages/crucible/seeds/python/seed-023 2.py +0 -37
- package/packages/crucible/seeds/python/seed-023.py +0 -37
- package/packages/crucible/seeds/python/seed-024 2.py +0 -38
- package/packages/crucible/seeds/python/seed-024.py +0 -38
- package/packages/crucible/seeds/python/seed-025 2.py +0 -40
- package/packages/crucible/seeds/python/seed-025.py +0 -40
- package/packages/crucible/seeds/python/seed-026 2.py +0 -35
- package/packages/crucible/seeds/python/seed-026.py +0 -35
- package/packages/crucible/seeds/python/seed-027 2.py +0 -35
- package/packages/crucible/seeds/python/seed-027.py +0 -35
- package/packages/crucible/seeds/python/seed-028 2.py +0 -42
- package/packages/crucible/seeds/python/seed-028.py +0 -42
- package/packages/crucible/seeds/python/seed-029.py +0 -42
- package/packages/crucible/seeds/python/seed-030 2.py +0 -37
- package/packages/crucible/seeds/python/seed-030.py +0 -37
- package/packages/crucible/seeds/python/seed-031 2.py +0 -34
- package/packages/crucible/seeds/python/seed-031.py +0 -34
- package/packages/crucible/seeds/python/seed-032.py +0 -33
- package/packages/crucible/seeds/python/seed-033.py +0 -32
- package/packages/crucible/seeds/python/seed-034.py +0 -38
- package/packages/crucible/seeds/python/seed-035.py +0 -35
- package/packages/crucible/seeds/python/seed-036 2.py +0 -33
- package/packages/crucible/seeds/python/seed-036.py +0 -33
- package/packages/crucible/seeds/python/seed-037 2.py +0 -41
- package/packages/crucible/seeds/python/seed-037.py +0 -41
- package/packages/crucible/seeds/python/seed-038 2.py +0 -33
- package/packages/crucible/seeds/python/seed-038.py +0 -33
- package/packages/crucible/seeds/python/seed-039 2.py +0 -39
- package/packages/crucible/seeds/python/seed-039.py +0 -39
- package/packages/crucible/seeds/python/seed-040 2.py +0 -39
- package/packages/crucible/seeds/python/seed-040.py +0 -39
- package/packages/crucible/seeds/python/seed-041 2.py +0 -37
- package/packages/crucible/seeds/python/seed-041.py +0 -37
- package/packages/crucible/seeds/python/seed-042 2.py +0 -38
- package/packages/crucible/seeds/python/seed-042.py +0 -38
- package/packages/crucible/seeds/python/seed-043 2.py +0 -32
- package/packages/crucible/seeds/python/seed-043.py +0 -32
- package/packages/crucible/seeds/python/seed-044 2.py +0 -38
- package/packages/crucible/seeds/python/seed-044.py +0 -38
- package/packages/crucible/seeds/python/seed-045 2.py +0 -36
- package/packages/crucible/seeds/python/seed-045.py +0 -36
- package/packages/crucible/seeds/python/seed-046 2.py +0 -33
- package/packages/crucible/seeds/python/seed-046.py +0 -33
- package/packages/crucible/seeds/python/seed-047 2.py +0 -44
- package/packages/crucible/seeds/python/seed-047.py +0 -44
- package/packages/crucible/seeds/python/seed-048 2.py +0 -35
- package/packages/crucible/seeds/python/seed-048.py +0 -35
- package/packages/crucible/seeds/python/seed-049 2.py +0 -39
- package/packages/crucible/seeds/python/seed-049.py +0 -39
- package/packages/crucible/seeds/python/seed-050 2.py +0 -39
- package/packages/crucible/seeds/python/seed-050.py +0 -39
- package/packages/crucible/seeds/python/seed-051 2.py +0 -38
- package/packages/crucible/seeds/python/seed-051.py +0 -38
- package/packages/crucible/seeds/python/seed-052 2.py +0 -41
- package/packages/crucible/seeds/python/seed-052.py +0 -41
- package/packages/crucible/seeds/ruby/seed-001 2.rb +0 -15
- package/packages/crucible/seeds/ruby/seed-001.rb +0 -15
- package/packages/crucible/seeds/ruby/seed-002 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-002.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-003 2.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-003.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-004 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-004.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-005 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-005.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-006 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-006.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-007 2.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-007.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-008 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-008.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-009 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-009.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-010 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-010.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-011 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-011.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-012 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-012.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-013 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-013.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-014 2.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-014.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-015 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-015.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-016 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-016.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-017 2.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-017.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-018 2.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-018.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-019 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-019.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-020 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-020.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-021 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-021.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-022 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-022.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-023 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-023.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-024 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-024.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-025 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-025.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-026 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-026.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-027 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-027.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-028 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-028.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-029 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-029.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-030 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-030.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-031 2.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-031.rb +0 -17
- package/packages/crucible/seeds/ruby/seed-032 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-032.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-033 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-033.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-034 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-034.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-035 2.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-035.rb +0 -19
- package/packages/crucible/seeds/ruby/seed-036 2.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-036.rb +0 -18
- package/packages/crucible/seeds/ruby/seed-037 2.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-037.rb +0 -21
- package/packages/crucible/seeds/ruby/seed-038 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-038.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-039 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-039.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-040 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-040.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-041 2.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-041.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-042 2.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-042.rb +0 -25
- package/packages/crucible/seeds/ruby/seed-043 2.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-043.rb +0 -23
- package/packages/crucible/seeds/ruby/seed-044 2.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-044.rb +0 -16
- package/packages/crucible/seeds/ruby/seed-045 2.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-045.rb +0 -22
- package/packages/crucible/seeds/ruby/seed-046 2.rb +0 -27
- package/packages/crucible/seeds/ruby/seed-046.rb +0 -27
- package/packages/crucible/seeds/ruby/seed-047 2.rb +0 -26
- package/packages/crucible/seeds/ruby/seed-047.rb +0 -26
- package/packages/crucible/seeds/ruby/seed-048 2.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-048.rb +0 -24
- package/packages/crucible/seeds/ruby/seed-049 2.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-049.rb +0 -20
- package/packages/crucible/seeds/ruby/seed-050 2.rb +0 -27
- package/packages/crucible/seeds/ruby/seed-050.rb +0 -27
- package/packages/crucible/seeds/rust/seed-001 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-001.rs +0 -25
- package/packages/crucible/seeds/rust/seed-002 2.rs +0 -20
- package/packages/crucible/seeds/rust/seed-002.rs +0 -20
- package/packages/crucible/seeds/rust/seed-003 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-003.rs +0 -23
- package/packages/crucible/seeds/rust/seed-004 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-004.rs +0 -21
- package/packages/crucible/seeds/rust/seed-005 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-005.rs +0 -21
- package/packages/crucible/seeds/rust/seed-006 2.rs +0 -24
- package/packages/crucible/seeds/rust/seed-006.rs +0 -24
- package/packages/crucible/seeds/rust/seed-007 2.rs +0 -20
- package/packages/crucible/seeds/rust/seed-007.rs +0 -20
- package/packages/crucible/seeds/rust/seed-008 2.rs +0 -19
- package/packages/crucible/seeds/rust/seed-008.rs +0 -19
- package/packages/crucible/seeds/rust/seed-009 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-009.rs +0 -28
- package/packages/crucible/seeds/rust/seed-010 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-010.rs +0 -28
- package/packages/crucible/seeds/rust/seed-011 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-011.rs +0 -25
- package/packages/crucible/seeds/rust/seed-012 2.rs +0 -31
- package/packages/crucible/seeds/rust/seed-012.rs +0 -31
- package/packages/crucible/seeds/rust/seed-013 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-013.rs +0 -27
- package/packages/crucible/seeds/rust/seed-014 2.rs +0 -30
- package/packages/crucible/seeds/rust/seed-014.rs +0 -30
- package/packages/crucible/seeds/rust/seed-015 2.rs +0 -33
- package/packages/crucible/seeds/rust/seed-015.rs +0 -33
- package/packages/crucible/seeds/rust/seed-016 2.rs +0 -22
- package/packages/crucible/seeds/rust/seed-016.rs +0 -22
- package/packages/crucible/seeds/rust/seed-017 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-017.rs +0 -28
- package/packages/crucible/seeds/rust/seed-018 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-018.rs +0 -21
- package/packages/crucible/seeds/rust/seed-019 2.rs +0 -36
- package/packages/crucible/seeds/rust/seed-019.rs +0 -36
- package/packages/crucible/seeds/rust/seed-020 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-020.rs +0 -27
- package/packages/crucible/seeds/rust/seed-021 2.rs +0 -26
- package/packages/crucible/seeds/rust/seed-021.rs +0 -26
- package/packages/crucible/seeds/rust/seed-022 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-022.rs +0 -23
- package/packages/crucible/seeds/rust/seed-023 2.rs +0 -22
- package/packages/crucible/seeds/rust/seed-023.rs +0 -22
- package/packages/crucible/seeds/rust/seed-024 2.rs +0 -24
- package/packages/crucible/seeds/rust/seed-024.rs +0 -24
- package/packages/crucible/seeds/rust/seed-025 2.rs +0 -29
- package/packages/crucible/seeds/rust/seed-025.rs +0 -29
- package/packages/crucible/seeds/rust/seed-026 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-026.rs +0 -23
- package/packages/crucible/seeds/rust/seed-027 2.rs +0 -24
- package/packages/crucible/seeds/rust/seed-027.rs +0 -24
- package/packages/crucible/seeds/rust/seed-028 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-028.rs +0 -25
- package/packages/crucible/seeds/rust/seed-029 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-029.rs +0 -25
- package/packages/crucible/seeds/rust/seed-030 2.rs +0 -30
- package/packages/crucible/seeds/rust/seed-030.rs +0 -30
- package/packages/crucible/seeds/rust/seed-031 2.rs +0 -22
- package/packages/crucible/seeds/rust/seed-031.rs +0 -22
- package/packages/crucible/seeds/rust/seed-032 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-032.rs +0 -25
- package/packages/crucible/seeds/rust/seed-033 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-033.rs +0 -25
- package/packages/crucible/seeds/rust/seed-034 2.rs +0 -20
- package/packages/crucible/seeds/rust/seed-034.rs +0 -20
- package/packages/crucible/seeds/rust/seed-035 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-035.rs +0 -28
- package/packages/crucible/seeds/rust/seed-036 2.rs +0 -26
- package/packages/crucible/seeds/rust/seed-036.rs +0 -26
- package/packages/crucible/seeds/rust/seed-037 2.rs +0 -31
- package/packages/crucible/seeds/rust/seed-037.rs +0 -31
- package/packages/crucible/seeds/rust/seed-038 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-038.rs +0 -25
- package/packages/crucible/seeds/rust/seed-039 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-039.rs +0 -28
- package/packages/crucible/seeds/rust/seed-040 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-040.rs +0 -27
- package/packages/crucible/seeds/rust/seed-041 2.rs +0 -32
- package/packages/crucible/seeds/rust/seed-041.rs +0 -32
- package/packages/crucible/seeds/rust/seed-042 2.rs +0 -27
- package/packages/crucible/seeds/rust/seed-042.rs +0 -27
- package/packages/crucible/seeds/rust/seed-043 2.rs +0 -29
- package/packages/crucible/seeds/rust/seed-043.rs +0 -29
- package/packages/crucible/seeds/rust/seed-044 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-044.rs +0 -25
- package/packages/crucible/seeds/rust/seed-045 2.rs +0 -28
- package/packages/crucible/seeds/rust/seed-045.rs +0 -28
- package/packages/crucible/seeds/rust/seed-046 2.rs +0 -25
- package/packages/crucible/seeds/rust/seed-046.rs +0 -25
- package/packages/crucible/seeds/rust/seed-047 2.rs +0 -34
- package/packages/crucible/seeds/rust/seed-047.rs +0 -34
- package/packages/crucible/seeds/rust/seed-048 2.rs +0 -21
- package/packages/crucible/seeds/rust/seed-048.rs +0 -21
- package/packages/crucible/seeds/rust/seed-049 2.rs +0 -26
- package/packages/crucible/seeds/rust/seed-049.rs +0 -26
- package/packages/crucible/seeds/rust/seed-050 2.rs +0 -23
- package/packages/crucible/seeds/rust/seed-050.rs +0 -23
- package/packages/crucible/seeds/ts/seed-001 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-001.ts +0 -32
- package/packages/crucible/seeds/ts/seed-002 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-002.ts +0 -34
- package/packages/crucible/seeds/ts/seed-003 2.ts +0 -28
- package/packages/crucible/seeds/ts/seed-003.ts +0 -28
- package/packages/crucible/seeds/ts/seed-004 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-004.ts +0 -34
- package/packages/crucible/seeds/ts/seed-005 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-005.ts +0 -32
- package/packages/crucible/seeds/ts/seed-006 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-006.ts +0 -31
- package/packages/crucible/seeds/ts/seed-007 2.ts +0 -28
- package/packages/crucible/seeds/ts/seed-007.ts +0 -28
- package/packages/crucible/seeds/ts/seed-008 2.ts +0 -40
- package/packages/crucible/seeds/ts/seed-008.ts +0 -40
- package/packages/crucible/seeds/ts/seed-009 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-009.ts +0 -31
- package/packages/crucible/seeds/ts/seed-010 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-010.ts +0 -33
- package/packages/crucible/seeds/ts/seed-011 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-011.ts +0 -29
- package/packages/crucible/seeds/ts/seed-012 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-012.ts +0 -34
- package/packages/crucible/seeds/ts/seed-013 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-013.ts +0 -31
- package/packages/crucible/seeds/ts/seed-014 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-014.ts +0 -36
- package/packages/crucible/seeds/ts/seed-015 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-015.ts +0 -31
- package/packages/crucible/seeds/ts/seed-016 2.ts +0 -37
- package/packages/crucible/seeds/ts/seed-016.ts +0 -37
- package/packages/crucible/seeds/ts/seed-017 2.ts +0 -44
- package/packages/crucible/seeds/ts/seed-017.ts +0 -44
- package/packages/crucible/seeds/ts/seed-018 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-018.ts +0 -33
- package/packages/crucible/seeds/ts/seed-019 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-019.ts +0 -32
- package/packages/crucible/seeds/ts/seed-020 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-020.ts +0 -33
- package/packages/crucible/seeds/ts/seed-021 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-021.ts +0 -33
- package/packages/crucible/seeds/ts/seed-022 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-022.ts +0 -34
- package/packages/crucible/seeds/ts/seed-023 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-023.ts +0 -33
- package/packages/crucible/seeds/ts/seed-024 2.ts +0 -35
- package/packages/crucible/seeds/ts/seed-024.ts +0 -35
- package/packages/crucible/seeds/ts/seed-025 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-025.ts +0 -29
- package/packages/crucible/seeds/ts/seed-026 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-026.ts +0 -36
- package/packages/crucible/seeds/ts/seed-027 2.ts +0 -30
- package/packages/crucible/seeds/ts/seed-027.ts +0 -30
- package/packages/crucible/seeds/ts/seed-028 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-028.ts +0 -32
- package/packages/crucible/seeds/ts/seed-029 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-029.ts +0 -34
- package/packages/crucible/seeds/ts/seed-030 2.ts +0 -37
- package/packages/crucible/seeds/ts/seed-030.ts +0 -37
- package/packages/crucible/seeds/ts/seed-031 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-031.ts +0 -31
- package/packages/crucible/seeds/ts/seed-032 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-032.ts +0 -32
- package/packages/crucible/seeds/ts/seed-033 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-033.ts +0 -32
- package/packages/crucible/seeds/ts/seed-034 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-034.ts +0 -34
- package/packages/crucible/seeds/ts/seed-035 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-035.ts +0 -29
- package/packages/crucible/seeds/ts/seed-036 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-036.ts +0 -34
- package/packages/crucible/seeds/ts/seed-037 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-037.ts +0 -33
- package/packages/crucible/seeds/ts/seed-038 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-038.ts +0 -29
- package/packages/crucible/seeds/ts/seed-039 2.ts +0 -35
- package/packages/crucible/seeds/ts/seed-039.ts +0 -35
- package/packages/crucible/seeds/ts/seed-040 2.ts +0 -31
- package/packages/crucible/seeds/ts/seed-040.ts +0 -31
- package/packages/crucible/seeds/ts/seed-041 2.ts +0 -29
- package/packages/crucible/seeds/ts/seed-041.ts +0 -29
- package/packages/crucible/seeds/ts/seed-042 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-042.ts +0 -33
- package/packages/crucible/seeds/ts/seed-043 2.ts +0 -32
- package/packages/crucible/seeds/ts/seed-043.ts +0 -32
- package/packages/crucible/seeds/ts/seed-044 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-044.ts +0 -36
- package/packages/crucible/seeds/ts/seed-045 2.ts +0 -39
- package/packages/crucible/seeds/ts/seed-045.ts +0 -39
- package/packages/crucible/seeds/ts/seed-046 2.ts +0 -41
- package/packages/crucible/seeds/ts/seed-046.ts +0 -41
- package/packages/crucible/seeds/ts/seed-047 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-047.ts +0 -33
- package/packages/crucible/seeds/ts/seed-048 2.ts +0 -33
- package/packages/crucible/seeds/ts/seed-048.ts +0 -33
- package/packages/crucible/seeds/ts/seed-049 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-049.ts +0 -34
- package/packages/crucible/seeds/ts/seed-050 2.ts +0 -41
- package/packages/crucible/seeds/ts/seed-050.ts +0 -41
- package/packages/crucible/seeds/ts/seed-051 2.ts +0 -34
- package/packages/crucible/seeds/ts/seed-051.ts +0 -34
- package/packages/crucible/seeds/ts/seed-052 2.ts +0 -36
- package/packages/crucible/seeds/ts/seed-052.ts +0 -36
- package/packages/scanner/alert-manager.js +0 -1
- package/packages/scanner/ast-analyzer.js +0 -1
- package/packages/scanner/cfg-analyzer.js +0 -1
- package/packages/scanner/code-scanner.js +0 -1
- package/packages/scanner/file-collector.js +0 -1
- package/packages/scanner/file-watcher.js +0 -1
- package/packages/scanner/ghost-code-detector.js +0 -1
- package/packages/scanner/hallucination-detector.js +0 -1
- package/packages/scanner/health-checker.js +0 -1
- package/packages/scanner/investor-report.js +0 -1
- package/packages/scanner/master-health-checker.js +0 -1
- package/packages/scanner/monitor-store.js +0 -1
- package/packages/scanner/python_ast_helper.py +0 -426
- package/packages/scanner/secret-scanner.js +0 -1
- package/packages/scanner/sentinel-core.js +0 -1
- package/packages/scanner/support-bot.js +0 -1
- package/packages/scanner/support-knowledge.js +0 -1
- package/packages/scanner/taint-tracker.js +0 -1
- /package/{packages → dist/packages}/crucible/badge-generator.js +0 -0
- /package/{packages → dist/packages}/crucible/banner.js +0 -0
- /package/{packages → dist/packages}/crucible/ci-integration.js +0 -0
- /package/{packages → dist/packages}/crucible/golden-master.js +0 -0
- /package/{packages → dist/packages}/crucible/index.js +0 -0
- /package/{packages → dist/packages}/crucible/kenny-mode.js +0 -0
- /package/{packages → dist/packages}/crucible/leaderboard.js +0 -0
- /package/{packages → dist/packages}/crucible/mutation-engine.js +0 -0
- /package/{packages → dist/packages}/crucible/pattern-learner.js +0 -0
- /package/{packages → dist/packages}/crucible/rule-loader.js +0 -0
- /package/{packages → dist/packages}/crucible/seeding-engine.js +0 -0
- /package/{packages → dist/packages}/crucible/self-attack.js +0 -0
- /package/{packages → dist/packages}/scanner/ai-confidence-scorer.js +0 -0
- /package/{packages → dist/packages}/scanner/baseline-manager.js +0 -0
- /package/{packages → dist/packages}/scanner/codebase-passport.js +0 -0
- /package/{packages → dist/packages}/scanner/copy-paste-detector.js +0 -0
- /package/{packages → dist/packages}/scanner/dependency-graph.js +0 -0
- /package/{packages → dist/packages}/scanner/drift-detector.js +0 -0
- /package/{packages → dist/packages}/scanner/executive-report.js +0 -0
- /package/{packages → dist/packages}/scanner/export-verifier.js +0 -0
- /package/{packages → dist/packages}/scanner/feedback-client.js +0 -0
- /package/{packages → dist/packages}/scanner/go-ast-analyzer.js +0 -0
- /package/{packages → dist/packages}/scanner/html-report.js +0 -0
- /package/{packages → dist/packages}/scanner/index.js +0 -0
- /package/{packages → dist/packages}/scanner/license-manager.js +0 -0
- /package/{packages → dist/packages}/scanner/monitor-notifier.js +0 -0
- /package/{packages → dist/packages}/scanner/monitor-service.js +0 -0
- /package/{packages → dist/packages}/scanner/pre-commit-gate.js +0 -0
- /package/{packages → dist/packages}/scanner/python-ast-analyzer.js +0 -0
- /package/{packages → dist/packages}/scanner/read-file.js +0 -0
- /package/{packages → dist/packages}/scanner/scan-diff.js +0 -0
- /package/{packages → dist/packages}/scanner/scan-runner.js +0 -0
- /package/{packages → dist/packages}/scanner/sentinel-knowledge.js +0 -0
- /package/{packages → dist/packages}/scanner/slack-notifier.js +0 -0
- /package/{packages → dist/packages}/scanner/tech-debt-analyzer.js +0 -0
- /package/{packages → dist/packages}/scanner/tech-debt-cost.js +0 -0
- /package/{packages → dist/packages}/scanner/widget-generator.js +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: ssrf
|
|
3
|
+
// severity: high
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: SSRF via axios with user-controlled webhook URL and redirect following
|
|
6
|
+
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
import { Request, Response, Router } from 'express';
|
|
9
|
+
|
|
10
|
+
const router = Router();
|
|
11
|
+
|
|
12
|
+
interface WebhookConfig {
|
|
13
|
+
url: string;
|
|
14
|
+
secret?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
router.post('/webhooks/test', async (req: Request, res: Response) => {
|
|
18
|
+
const { url, secret } = req.body as WebhookConfig;
|
|
19
|
+
// url user-controlled — attacker probes internal network
|
|
20
|
+
const response = await axios.post(url, { test: true, timestamp: Date.now() }, {
|
|
21
|
+
headers: { 'X-Webhook-Secret': secret ?? '' },
|
|
22
|
+
maxRedirects: 5, // follows redirects — can pivot to internal services
|
|
23
|
+
timeout: 10000,
|
|
24
|
+
});
|
|
25
|
+
res.json({ status: response.status, data: response.data });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
router.get('/import', async (req: Request, res: Response) => {
|
|
29
|
+
const dataUrl = req.query.source as string;
|
|
30
|
+
const { data } = await axios.get(dataUrl, { responseType: 'arraybuffer' });
|
|
31
|
+
res.set('Content-Type', 'application/octet-stream').send(data);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export default router;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: ssrf
|
|
3
|
+
// severity: high
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: SSRF via got library with user-controlled URL in oEmbed/link-preview feature
|
|
6
|
+
|
|
7
|
+
import got from 'got';
|
|
8
|
+
import { Request, Response, Router } from 'express';
|
|
9
|
+
|
|
10
|
+
const router = Router();
|
|
11
|
+
|
|
12
|
+
interface LinkPreviewResult {
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
image?: string;
|
|
16
|
+
url: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
router.get('/link-preview', async (req: Request, res: Response) => {
|
|
20
|
+
const url = req.query.url as string;
|
|
21
|
+
|
|
22
|
+
// url is user-controlled — attacker can reach internal services
|
|
23
|
+
const response = await got(url, {
|
|
24
|
+
followRedirect: true,
|
|
25
|
+
timeout: { request: 8000 },
|
|
26
|
+
throwHttpErrors: false,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const titleMatch = response.body.match(/<title>(.*?)<\/title>/i);
|
|
30
|
+
const descMatch = response.body.match(/<meta name="description" content="(.*?)"/i);
|
|
31
|
+
|
|
32
|
+
const result: LinkPreviewResult = {
|
|
33
|
+
title: titleMatch?.[1] ?? '',
|
|
34
|
+
description: descMatch?.[1] ?? '',
|
|
35
|
+
url,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
res.json(result);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export default router;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: ssrf
|
|
3
|
+
// severity: high
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: SSRF via got library with user-controlled URL in oEmbed/link-preview feature
|
|
6
|
+
|
|
7
|
+
import got from 'got';
|
|
8
|
+
import { Request, Response, Router } from 'express';
|
|
9
|
+
|
|
10
|
+
const router = Router();
|
|
11
|
+
|
|
12
|
+
interface LinkPreviewResult {
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
image?: string;
|
|
16
|
+
url: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
router.get('/link-preview', async (req: Request, res: Response) => {
|
|
20
|
+
const url = req.query.url as string;
|
|
21
|
+
|
|
22
|
+
// url is user-controlled — attacker can reach internal services
|
|
23
|
+
const response = await got(url, {
|
|
24
|
+
followRedirect: true,
|
|
25
|
+
timeout: { request: 8000 },
|
|
26
|
+
throwHttpErrors: false,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const titleMatch = response.body.match(/<title>(.*?)<\/title>/i);
|
|
30
|
+
const descMatch = response.body.match(/<meta name="description" content="(.*?)"/i);
|
|
31
|
+
|
|
32
|
+
const result: LinkPreviewResult = {
|
|
33
|
+
title: titleMatch?.[1] ?? '',
|
|
34
|
+
description: descMatch?.[1] ?? '',
|
|
35
|
+
url,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
res.json(result);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export default router;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: deserialization
|
|
3
|
+
// severity: critical
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: unsafe deserialization via class-transformer plainToClass with user-controlled type
|
|
6
|
+
|
|
7
|
+
import { plainToClass } from 'class-transformer';
|
|
8
|
+
import { IsString, IsNumber } from 'class-validator';
|
|
9
|
+
import { Request, Response, Router } from 'express';
|
|
10
|
+
|
|
11
|
+
class UserDto {
|
|
12
|
+
@IsString() username!: string;
|
|
13
|
+
@IsString() email!: string;
|
|
14
|
+
@IsNumber() role!: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class AdminDto extends UserDto {
|
|
18
|
+
@IsString() adminToken!: string;
|
|
19
|
+
canDeleteUsers: boolean = true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const router = Router();
|
|
23
|
+
|
|
24
|
+
router.post('/users/import', (req: Request, res: Response) => {
|
|
25
|
+
const { type, data } = req.body;
|
|
26
|
+
|
|
27
|
+
// User controls which class to deserialize into — can escalate to AdminDto
|
|
28
|
+
const DtoClass = type === 'admin' ? AdminDto : UserDto;
|
|
29
|
+
const instance = plainToClass(DtoClass, data);
|
|
30
|
+
// No validation step — properties set without checking constraints
|
|
31
|
+
res.json({ created: instance });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export default router;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: deserialization
|
|
3
|
+
// severity: critical
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: unsafe deserialization via class-transformer plainToClass with user-controlled type
|
|
6
|
+
|
|
7
|
+
import { plainToClass } from 'class-transformer';
|
|
8
|
+
import { IsString, IsNumber } from 'class-validator';
|
|
9
|
+
import { Request, Response, Router } from 'express';
|
|
10
|
+
|
|
11
|
+
class UserDto {
|
|
12
|
+
@IsString() username!: string;
|
|
13
|
+
@IsString() email!: string;
|
|
14
|
+
@IsNumber() role!: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class AdminDto extends UserDto {
|
|
18
|
+
@IsString() adminToken!: string;
|
|
19
|
+
canDeleteUsers: boolean = true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const router = Router();
|
|
23
|
+
|
|
24
|
+
router.post('/users/import', (req: Request, res: Response) => {
|
|
25
|
+
const { type, data } = req.body;
|
|
26
|
+
|
|
27
|
+
// User controls which class to deserialize into — can escalate to AdminDto
|
|
28
|
+
const DtoClass = type === 'admin' ? AdminDto : UserDto;
|
|
29
|
+
const instance = plainToClass(DtoClass, data);
|
|
30
|
+
// No validation step — properties set without checking constraints
|
|
31
|
+
res.json({ created: instance });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export default router;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: deserialization
|
|
3
|
+
// severity: high
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: unsafe deserialization via JSON.parse used to dynamically dispatch method calls
|
|
6
|
+
|
|
7
|
+
import { Request, Response, Router } from 'express';
|
|
8
|
+
|
|
9
|
+
interface TaskDescriptor {
|
|
10
|
+
module: string;
|
|
11
|
+
method: string;
|
|
12
|
+
args: unknown[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const allowedModules: Record<string, Record<string, (...args: unknown[]) => unknown>> = {
|
|
16
|
+
reports: require('./reports'),
|
|
17
|
+
notifications: require('./notifications'),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
router.post('/task/run', (req: Request, res: Response) => {
|
|
21
|
+
// task is JSON-parsed from user body without schema validation
|
|
22
|
+
const task = JSON.parse(req.body.taskJson as string) as TaskDescriptor;
|
|
23
|
+
|
|
24
|
+
const mod = allowedModules[task.module];
|
|
25
|
+
if (!mod) return res.status(400).json({ error: 'Unknown module' });
|
|
26
|
+
|
|
27
|
+
const fn = mod[task.method];
|
|
28
|
+
if (typeof fn !== 'function') return res.status(400).json({ error: 'Unknown method' });
|
|
29
|
+
|
|
30
|
+
// task.args passed directly — no sanitization or type validation
|
|
31
|
+
const result = fn(...task.args);
|
|
32
|
+
res.json({ result });
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const router2 = Router();
|
|
36
|
+
export default router2;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// [CRUCIBLE-SEED]
|
|
2
|
+
// category: deserialization
|
|
3
|
+
// severity: high
|
|
4
|
+
// language: typescript
|
|
5
|
+
// expected: unsafe deserialization via JSON.parse used to dynamically dispatch method calls
|
|
6
|
+
|
|
7
|
+
import { Request, Response, Router } from 'express';
|
|
8
|
+
|
|
9
|
+
interface TaskDescriptor {
|
|
10
|
+
module: string;
|
|
11
|
+
method: string;
|
|
12
|
+
args: unknown[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const allowedModules: Record<string, Record<string, (...args: unknown[]) => unknown>> = {
|
|
16
|
+
reports: require('./reports'),
|
|
17
|
+
notifications: require('./notifications'),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
router.post('/task/run', (req: Request, res: Response) => {
|
|
21
|
+
// task is JSON-parsed from user body without schema validation
|
|
22
|
+
const task = JSON.parse(req.body.taskJson as string) as TaskDescriptor;
|
|
23
|
+
|
|
24
|
+
const mod = allowedModules[task.module];
|
|
25
|
+
if (!mod) return res.status(400).json({ error: 'Unknown module' });
|
|
26
|
+
|
|
27
|
+
const fn = mod[task.method];
|
|
28
|
+
if (typeof fn !== 'function') return res.status(400).json({ error: 'Unknown method' });
|
|
29
|
+
|
|
30
|
+
// task.args passed directly — no sanitization or type validation
|
|
31
|
+
const result = fn(...task.args);
|
|
32
|
+
res.json({ result });
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const router2 = Router();
|
|
36
|
+
export default router2;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const fs=require("fs"),path=require("path"),EventEmitter=require("events");class AlertManager extends EventEmitter{constructor(e={}){super(),this.config={rootPath:e.rootPath||process.cwd(),alertsDir:e.alertsDir||path.join(e.rootPath||process.cwd(),"sentinel","alerts"),reportsDir:e.reportsDir||path.join(e.rootPath||process.cwd(),"sentinel","reports"),consoleOutput:!1!==e.consoleOutput,fileOutput:!1!==e.fileOutput,maxAlertsPerFile:e.maxAlertsPerFile||1e3,slackWebhook:e.slackWebhook||null,emailConfig:e.emailConfig||null,...e},this._ensureDirectories(),this.recentAlerts=new Map,this.alertDedupeWindowMs=e.alertDedupeWindowMs||6e4}async sendAlert(e){const t=this._normalizeAlert(e);if(this._isDuplicate(t))return{sent:!1,reason:"duplicate"};this._recordAlert(t);const o={console:!1,file:!1,slack:!1,email:!1};return this.config.consoleOutput&&(o.console=this._outputToConsole(t)),this.config.fileOutput&&(o.file=await this._outputToFile(t)),this.config.slackWebhook&&["critical","error"].includes(t.level)&&(o.slack=await this._outputToSlack(t)),this.emit("alertSent",{alert:t,results:o}),{sent:!0,alert:t,results:o}}async sendDigest(e){if(console.log("\n"+"=".repeat(60)),console.log("[SENTINEL] DAILY DIGEST - "+e.date),console.log("=".repeat(60)),console.log("\nSummary:"),console.log(` Issues Found: ${e.summary.issuesFound}`),console.log(` Critical: ${e.summary.criticalIssues}`),console.log(` Warnings: ${e.summary.warningIssues}`),console.log(` Files Watched: ${e.summary.filesWatched}`),console.log(` Last Scan: ${e.summary.lastScan||"N/A"}`),e.topIssues&&e.topIssues.length>0){console.log("\nTop Issues:");for(const t of e.topIssues.slice(0,5))console.log(` [${t.severity.toUpperCase()}] ${t.message}`),t.file&&console.log(` File: ${path.relative(this.config.rootPath,t.file)}`)}if(e.recommendations&&e.recommendations.length>0){console.log("\nRecommendations:");for(const t of e.recommendations)console.log(` [${t.priority.toUpperCase()}] ${t.message}`)}if(console.log("\n"+"=".repeat(60)+"\n"),this.config.fileOutput){const t=path.join(this.config.reportsDir,`digest-${e.date}.json`);fs.writeFileSync(t,JSON.stringify(e,null,2))}return this.emit("digestSent",e),{sent:!0}}async sendWeeklyReport(e){if(console.log("\n"+"=".repeat(70)),console.log("[SENTINEL] WEEKLY REPORT - Week of "+e.weekOf),console.log("=".repeat(70)),console.log("\nMetrics:"),console.log(` Total Scans: ${e.summary.totalScans}`),console.log(` Issues Detected: ${e.summary.issuesDetected}`),console.log(` Issues Resolved: ${e.summary.issuesResolved}`),console.log(` Avg Scan Time: ${e.summary.averageScanTime}ms`),console.log("\nCode Quality:"),console.log(` Score: ${e.codeQuality.score}/100 (${e.codeQuality.grade})`),console.log(` Complexity: ${e.codeQuality.factors.complexity}`),console.log(` Maintainability: ${e.codeQuality.factors.maintainability}`),console.log(` Test Coverage: ${e.codeQuality.factors.testCoverage}%`),console.log("\nTechnical Debt:"),console.log(` Estimated Hours: ${e.technicalDebt.estimatedHours}`),console.log(` Refactoring: ${e.technicalDebt.categories.refactoring}h`),console.log(` Documentation: ${e.technicalDebt.categories.documentation}h`),console.log(` Testing: ${e.technicalDebt.categories.testing}h`),e.recommendations&&e.recommendations.length>0){console.log("\nRecommendations:");for(const t of e.recommendations)console.log(` [${t.priority.toUpperCase()}] ${t.message}`)}if(console.log("\n"+"=".repeat(70)+"\n"),this.config.fileOutput){const t=path.join(this.config.reportsDir,`weekly-report-${e.weekOf}.json`);fs.writeFileSync(t,JSON.stringify(e,null,2))}return this.emit("weeklyReportSent",e),{sent:!0}}_ensureDirectories(){try{fs.existsSync(this.config.alertsDir)||fs.mkdirSync(this.config.alertsDir,{recursive:!0}),fs.existsSync(this.config.reportsDir)||fs.mkdirSync(this.config.reportsDir,{recursive:!0})}catch(e){console.warn("[ALERT-MANAGER] Could not create directories")}}_normalizeAlert(e){return{id:e.id||this._generateAlertId(),timestamp:e.timestamp||(new Date).toISOString(),level:e.level||"info",category:e.category||"general",title:e.title||"Alert",message:e.message||"",file:e.file||null,line:e.line||null,details:e.details||{}}}_generateAlertId(){return`alert-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}_isDuplicate(e){const t=`${e.level}:${e.message}:${e.file}`,o=this.recentAlerts.get(t);return!!(o&&Date.now()-o<this.alertDedupeWindowMs)}_recordAlert(e){const t=`${e.level}:${e.message}:${e.file}`;this.recentAlerts.set(t,Date.now());const o=Date.now()-this.alertDedupeWindowMs;for(const[e,t]of this.recentAlerts)t<o&&this.recentAlerts.delete(e)}_outputToConsole(e){const t={critical:"[31m",error:"[31m",warning:"[33m",info:"[36m"}[e.level]||"";if(console.log(`${t}[SENTINEL:${e.level.toUpperCase()}][0m ${e.title}`),console.log(` ${e.message}`),e.file){const t=path.relative(this.config.rootPath,e.file);console.log(` File: ${t}${e.line?":"+e.line:""}`)}return!0}async _outputToFile(e){try{const t=(new Date).toISOString().split("T")[0],o=path.join(this.config.alertsDir,`alerts-${t}.json`);let s={date:t,alerts:[]};if(fs.existsSync(o))try{s=JSON.parse(fs.readFileSync(o,"utf8"))}catch(e){}return s.alerts.push(e),s.alerts.length>this.config.maxAlertsPerFile&&(s.alerts=s.alerts.slice(-this.config.maxAlertsPerFile)),fs.writeFileSync(o,JSON.stringify(s,null,2)),!0}catch(e){return console.error("[ALERT-MANAGER] File output failed"),!1}}async _outputToSlack(e){if(!this.config.slackWebhook)return!1;try{return console.log(`[ALERT-MANAGER] Would send to Slack: ${e.title}`),!0}catch(e){return console.error("[ALERT-MANAGER] Slack output failed"),!1}}}module.exports=AlertManager;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const fs=require("fs"),path=require("path"),DEFAULT_IGNORE=new Set(["node_modules",".git","dist","build",".next",".vite","coverage",".thuban",".crucible",".golden"]),ENTRY_NAME_HINTS=["index.","main.","app.","server.","cli.","bin/"],IMPORT_REGEXES=[/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,/import\s+.*?from\s+['"]([^'"]+)['"]/g,/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g],DECISION_KEYWORDS=/\b(if|else|for|while|switch|case|catch|&&|\|\||\?)\b/g,FUNCTION_REGEX=/(?:^|\n)\s*(?:export\s+)?(?:async\s+)?function\s+\w+|=>\s*\{|(?:^|\n)\s*func\s+(?:\([^)]*\)\s+)?\w+\s*\(|(?:^|\n)\s*(?:pub\s+)?(?:async\s+)?fn\s+\w+|(?:^|\n)\s*def\s+(?:self\.)?\w+|(?:^|\n)\s*(?:public|private|protected|internal)?\s*(?:fun|suspend\s+fun)\s+\w+/gm;function moduleNameFor(e){const t=e.split(path.sep).filter(Boolean);return t.length<=1?"(root)":("packages"===t[0]||"apps"===t[0]||"libs"===t[0])&&t.length>2?`${t[0]}/${t[1]}`:t[0]}function isEntryPoint(e,t){const n=e.toLowerCase();return!!ENTRY_NAME_HINTS.some(e=>n.includes(e))||!!t.startsWith("#!/usr/bin/env")||!(!t.includes("createServer")&&!t.includes(".listen("))}function estimateComplexity(e){const t=e.match(DECISION_KEYWORDS)||[],n=e.match(FUNCTION_REGEX)||[];return 0===n.length?0:t.length/n.length}function extractModuleImports(e,t,n){const s=new Set;for(const o of IMPORT_REGEXES){let i;for(o.lastIndex=0;null!==(i=o.exec(e));){const e=i[1];if(!e||!e.startsWith(".")&&!path.isAbsolute(e))continue;const o=path.resolve(t,e),r=path.relative(n,o);r.startsWith("..")||s.add(r)}}return s}function healthRatingFor(e,t){let n=0;n+=Math.min(4*e,60),n+=Math.min(3*Math.max(t-5,0),30);const s=Math.max(0,100-n);return s>=85?{rating:"Excellent",color:"#00ff88",score:s}:s>=65?{rating:"Good",color:"#88ff00",score:s}:s>=45?{rating:"Fair",color:"#ffd93d",color2:"#ffd93d",score:s}:s>=25?{rating:"Poor",color:"#ff8844",score:s}:{rating:"Critical",color:"#ff4444",score:s}}async function generateArchitectureMap(e={}){const{files:t=[],rootPath:n=process.cwd(),scanResults:s={},hallResults:o={}}=e,i=new Map,r=[],c=new Map;for(const e of t){let t;try{const n=fs.statSync(e);if(!n.isFile()||n.size>1048576)continue;t=fs.readFileSync(e,"utf-8").replace(/\r\n/g,"\n")}catch{continue}const s=path.relative(n,e);if(s.split(path.sep).some(e=>DEFAULT_IGNORE.has(e)))continue;const o=moduleNameFor(s);c.set(s,o),i.has(o)||i.set(o,{name:o,fileCount:0,loc:0,complexitySum:0,complexityCount:0,findingsCount:0,dependsOn:new Set});const a=i.get(o),l=t.split("\n").length;a.fileCount++,a.loc+=l;const u=estimateComplexity(t);u>0&&(a.complexitySum+=u,a.complexityCount++),isEntryPoint(s,t)&&r.push({file:s,module:o});const f=extractModuleImports(t,path.dirname(e),n);for(const e of f){const t=moduleNameFor(e);t!==o&&a.dependsOn.add(t)}}const a=e=>{if(!e)return;let t;try{t=path.isAbsolute(e)?path.relative(n,e):e}catch{return}const s=c.get(t)||moduleNameFor(t),o=i.get(s);o&&o.findingsCount++},l=/security|inject|xss|secret|auth|taint|vuln/i,u=new Set;for(const e of s.issues||[]){a(e.file);const t=`${e.category||""} ${e.message||""} ${e.name||""}`;if(l.test(t)){const t=path.isAbsolute(e.file||"")?path.relative(n,e.file):e.file||"",s=c.get(t)||moduleNameFor(t||"");u.add(s)}}for(const e of o.phantomAPIs||[]){a(e.file);const t=path.isAbsolute(e.file||"")?path.relative(n,e.file):e.file||"";u.add(c.get(t)||moduleNameFor(t||""))}for(const e of o.deprecatedAPIs||[])a(e.file);const f=[];for(const[e,t]of i){const n=t.complexityCount>0?t.complexitySum/t.complexityCount:0,s=healthRatingFor(t.loc>0?t.findingsCount/t.loc*1e3:0,n);f.push({name:e,fileCount:t.fileCount,loc:t.loc,avgComplexity:Math.round(10*n)/10,findingsCount:t.findingsCount,healthRating:s.rating,healthColor:s.color,healthScore:Math.round(s.score),dependsOn:Array.from(t.dependsOn).sort(),hasSecurityFindings:u.has(e)})}return f.sort((e,t)=>t.loc-e.loc),{modules:f,graph:renderAsciiGraph(f,r,u),entryPoints:r.slice(0,15),securityModules:Array.from(u)}}function renderAsciiGraph(e,t,n){const s=[];if(s.push("ENTRY POINTS"),0===t.length)s.push(" (none detected)");else{for(const e of t.slice(0,8))s.push(` ▸ ${e.file} [${e.module}]`);t.length>8&&s.push(` ... and ${t.length-8} more`)}s.push(""),s.push("MODULE DEPENDENCY GRAPH (data flow: left depends on right)"),s.push("");const o=Math.max(...e.map(e=>e.name.length),10);for(const t of e){const e=n.has(t.name)?" ⚠":"",i=t.name.padEnd(o," ");0===t.dependsOn.length?s.push(` ${i} (leaf module — no internal deps)${e}`):s.push(` ${i} ──▶ ${t.dependsOn.join(", ")}${e}`)}return s.push(""),s.push("⚠ = module contains security-relevant findings"),s.join("\n")}module.exports={generateArchitectureMap:generateArchitectureMap};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const parser=require("@babel/parser"),path=require("path"),pythonAstAnalyzer=require("./python-ast-analyzer"),goAstAnalyzer=require("./go-ast-analyzer"),BABEL_PLUGINS=["estree","typescript","jsx","classProperties","decorators-legacy"];function walk(e,t){if(e&&"object"==typeof e&&"string"==typeof e.type){t(e);for(const n in e){if("loc"===n||"range"===n||"start"===n||"end"===n)continue;const s=e[n];if(Array.isArray(s))for(const e of s)e&&"object"==typeof e&&"string"==typeof e.type&&walk(e,t);else s&&"object"==typeof s&&"string"==typeof s.type&&walk(s,t)}}}function lineOf(e){return e&&e.loc?e.loc.start.line:0}function snippet(e,t){return!t||t<1||t>e.length?"":e[t-1].trim().substring(0,100)}function buildIssue(e,t,n,s){return{file:e,line:t,category:s.category,type:s.type,severity:s.severity,id:s.id,name:s.name,message:s.message,code:snippet(n,t),source:s.source}}function mkIssue(e,t,n,s){return buildIssue(e,t,n,{...s,category:"security",source:"ast"})}const CMD_FUNCS=new Set(["exec","execSync","spawn","spawnSync","fork"]),SQL_METHODS=new Set(["query","execute","raw","where"]);function isNonLiteralDynamic(e){let t=!1;return walk(e,e=>{"Identifier"!==e.type&&"CallExpression"!==e.type&&"MemberExpression"!==e.type||(t=!0)}),t}function isDynamicStringBuild(e){return!!e&&("TemplateLiteral"===e.type?(e.expressions||[]).length>0:"BinaryExpression"===e.type&&"+"===e.operator&&isNonLiteralDynamic(e))}function collectEvalAliases(e){const t=new Set;let n=!0,s=0;for(;n&&s<5;)n=!1,s++,walk(e,e=>{if("VariableDeclarator"===e.type&&e.init&&"Identifier"===e.init.type&&"Identifier"===e.id.type){const s=e.init.name;"eval"!==s&&!t.has(s)||t.has(e.id.name)||(t.add(e.id.name),n=!0)}if("AssignmentExpression"===e.type&&"="===e.operator&&"Identifier"===e.left.type&&"Identifier"===e.right.type){const s=e.right.name;"eval"!==s&&!t.has(s)||t.has(e.left.name)||(t.add(e.left.name),n=!0)}});return t}function findProtoGuard(e){let t=!1;return walk(e,e=>{"Literal"===e.type&&"string"==typeof e.value&&["__proto__","constructor","prototype"].includes(e.value)&&(t=!0)}),t}function analyzeJSAst(e,t){const n=[],s=t.split("\n");let r;try{r=parser.parse(t,{sourceType:"unambiguous",plugins:BABEL_PLUGINS,allowReturnOutsideFunction:!0,allowImportExportEverywhere:!0,allowAwaitOutsideFunction:!0,allowSuperOutsideMethod:!0,allowUndeclaredExports:!0,errorRecovery:!1}).program}catch(e){return n}const i=collectEvalAliases(r);return walk(r,t=>{if("CallExpression"===t.type&&"Identifier"===t.callee.type){const r=t.callee.name;if("eval"===r||i.has(r)){const i="eval"!==r;n.push(mkIssue(e,lineOf(t),s,{type:"eval_abuse",severity:"error",id:"AST001",name:i?"Aliased eval() Usage (AST)":"eval() Usage (AST)",message:i?`eval() called indirectly through alias "${r}" - AST-detected`:"eval() is dangerous and should be avoided (AST-confirmed)"}))}}if("CallExpression"===t.type&&"MemberExpression"===t.callee.type&&"Identifier"===t.callee.property.type&&SQL_METHODS.has(t.callee.property.name)){const r=t.arguments[0];r&&isDynamicStringBuild(r)&&n.push(mkIssue(e,lineOf(t),s,{type:"sql_injection",severity:"error",id:"AST002",name:"SQL Injection Risk (AST)",message:`Dynamic string passed to .${t.callee.property.name}() - use parameterized queries`}))}if("AssignmentExpression"!==t.type||"MemberExpression"!==t.left.type||"Identifier"!==t.left.property.type||"innerHTML"!==t.left.property.name&&"outerHTML"!==t.left.property.name||"Literal"!==t.right.type&&n.push(mkIssue(e,lineOf(t),s,{type:"xss",severity:"warning",id:"AST003",name:`${t.left.property.name} Assignment (AST)`,message:`Non-literal value assigned to ${t.left.property.name} - possible XSS`})),"CallExpression"===t.type&&"MemberExpression"===t.callee.type&&"Identifier"===t.callee.object.type&&"document"===t.callee.object.name&&"Identifier"===t.callee.property.type&&"write"===t.callee.property.name){const r=t.arguments[0];r&&"Literal"!==r.type&&n.push(mkIssue(e,lineOf(t),s,{type:"xss",severity:"warning",id:"AST003",name:"document.write() Assignment (AST)",message:"Non-literal value passed to document.write() - possible XSS"}))}if("CallExpression"===t.type){let r=null;if("Identifier"===t.callee.type?r=t.callee.name:"MemberExpression"===t.callee.type&&"Identifier"===t.callee.property.type&&(r=t.callee.property.name),r&&CMD_FUNCS.has(r)){const i=t.arguments[0];i&&isDynamicStringBuild(i)&&n.push(mkIssue(e,lineOf(t),s,{type:"command_injection",severity:"error",id:"AST004",name:`${r}() Command Injection (AST)`,message:`Dynamic string passed to ${r}() - command injection risk`}))}}if("ForInStatement"===t.type||"ForOfStatement"===t.type){let r=null;if(("ForInStatement"===t.type||"CallExpression"===t.right.type&&"MemberExpression"===t.right.callee.type&&"Identifier"===t.right.callee.object.type&&"Object"===t.right.callee.object.name&&"Identifier"===t.right.callee.property.type&&"keys"===t.right.callee.property.name)&&("VariableDeclaration"===t.left.type?r=t.left.declarations[0].id.name:"Identifier"===t.left.type&&(r=t.left.name)),r&&!findProtoGuard(t.body)){let i=!1;walk(t.body,e=>{"AssignmentExpression"===e.type&&"MemberExpression"===e.left.type&&e.left.computed&&"Identifier"===e.left.property.type&&e.left.property.name===r&&(i=!0)}),i&&n.push(mkIssue(e,lineOf(t),s,{type:"prototype_pollution",severity:"error",id:"AST005",name:"Unguarded Object Merge (AST)",message:`Loop assigns to obj[${r}] without checking for __proto__/constructor/prototype - prototype pollution risk`}))}}}),n}function joinLogicalStatements(e){const t=e.split("\n"),n=[];let s="",r=0,i=0;for(let e=0;e<t.length;e++){const a=t[e];s||(r=e+1),s+=(s?"\n":"")+a;for(const e of a)"("===e||"["===e||"{"===e?i++:")"!==e&&"]"!==e&&"}"!==e||(i=Math.max(0,i-1));const o=/\\\s*$/.test(a);0!==i||o||(n.push({text:s,startLine:r}),s="")}return s&&n.push({text:s,startLine:r}),n}function extractBalanced(e,t){let n=0;for(let s=t;s<e.length;s++)if("("===e[s])n++;else if(")"===e[s]&&(n--,0===n))return e.slice(t+1,s);return e.slice(t+1)}function splitTopLevelArgs(e){const t=[];let n=0,s="",r=null;for(let i=0;i<e.length;i++){const a=e[i];r?(s+=a,a===r&&"\\"!==e[i-1]&&(r=null)):'"'!==a&&"'"!==a?("([{".includes(a)&&n++,")]}".includes(a)&&n--,","!==a||0!==n?s+=a:(t.push(s.trim()),s="")):(r=a,s+=a)}return s.trim()&&t.push(s.trim()),t}function isDynamicPyString(e){if(!e)return!1;const t=e.trim();return!(!/^[rR]?[fF]['"]/.test(t)||!t.includes("{"))||!!/['"]\s*%\s*\(?[\w.]/.test(t)||!!/['"]\s*\+\s*\w|\w\s*\+\s*['"]/.test(t)}function analyzePythonHeuristic(e,t){const n=[],s=t.split("\n"),r=joinLogicalStatements(t),i=new Set;for(const e of r){const t=e.text.match(/^\s*([A-Za-z_]\w*)\s*=\s*(eval|exec)\s*$/m);t&&i.add(t[1])}for(const t of r){const r=t.text,a=t.startLine;for(const t of i)new RegExp("\\b"+t+"\\s*\\(").test(r)&&n.push(mkIssue(e,a,s,{type:"eval_abuse",severity:"error",id:"AST011",name:"Aliased eval/exec Usage (AST)",message:`eval/exec called indirectly through alias "${t}" - AST-detected`}));const o=r.search(/\bos\.system\s*\(/);if(-1!==o){const t=r.indexOf("(",o);isDynamicPyString(extractBalanced(r,t))&&n.push(mkIssue(e,a,s,{type:"command_injection",severity:"error",id:"AST012",name:"os.system() Command Injection (AST)",message:"Dynamic string passed to os.system() - command injection risk"}))}const l=r.match(/\bsubprocess\.(call|run|Popen|check_output)\s*\(/);if(l){const t=r.indexOf("(",l.index),i=extractBalanced(r,t);if(/shell\s*=\s*True/.test(i)){const t=splitTopLevelArgs(i)[0]||"";isDynamicPyString(t)&&!t.trim().startsWith("[")&&n.push(mkIssue(e,a,s,{type:"command_injection",severity:"error",id:"AST013",name:"subprocess shell=True Command Injection (AST)",message:`Dynamic string passed to subprocess.${l[1]}() with shell=True`}))}}const c=r.match(/\b(?:cursor|db|conn|connection)\.execute\s*\(/);if(c){const t=r.indexOf("(",c.index);isDynamicPyString(splitTopLevelArgs(extractBalanced(r,t))[0]||"")&&n.push(mkIssue(e,a,s,{type:"sql_injection",severity:"error",id:"AST014",name:"SQL Injection Risk (AST)",message:"Dynamic string passed to .execute() - use parameterized queries"}))}}return n}const JS_EXTS=new Set([".js",".jsx",".ts",".tsx",".mjs",".cjs"]),PY_EXTS=new Set([".py",".pyw"]),GO_EXTS=new Set([".go"]),MAX_AST_FILE_SIZE=2e4;function analyzePython(e,t){const n=analyzePythonHeuristic(e,t);let s=[];try{s=pythonAstAnalyzer.analyze(e,t)}catch(e){s=[]}return n.concat(s)}function analyze(e,t){if(t.length>2e4)return[];const n=path.extname(e).toLowerCase();try{if(JS_EXTS.has(n))return analyzeJSAst(e,t);if(PY_EXTS.has(n))return analyzePython(e,t);if(GO_EXTS.has(n))return analyzeGo(e,t)}catch(e){return[]}return[]}function analyzeGo(e,t){try{return goAstAnalyzer.analyze(e,t)}catch(e){return[]}}module.exports={analyze:analyze,analyzeJSAst:analyzeJSAst,analyzePythonHeuristic:analyzePythonHeuristic,analyzePython:analyzePython,analyzeGo:analyzeGo,_internal:{walk:walk,isDynamicStringBuild:isDynamicStringBuild,collectEvalAliases:collectEvalAliases,joinLogicalStatements:joinLogicalStatements,extractBalanced:extractBalanced,splitTopLevelArgs:splitTopLevelArgs,isDynamicPyString:isDynamicPyString,lineOf:lineOf,snippet:snippet,buildIssue:buildIssue}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const LOC_BUCKETS=[{key:"xs",label:"< 5K LOC",max:5e3},{key:"small",label:"5K–25K LOC",max:25e3},{key:"medium",label:"25K–100K LOC",max:1e5},{key:"large",label:"100K–500K LOC",max:5e5},{key:"xl",label:"> 500K LOC",max:1/0}];function bucketFor(e){return LOC_BUCKETS.find(t=>e<=t.max)||LOC_BUCKETS[LOC_BUCKETS.length-1]}const BASE_METRICS_BY_LANG={javascript:{trustScore:{avg:68,top10:88},criticalFindingsPer1k:{avg:1.8,top10:.2},hallucinationsPer1k:{avg:.6,top10:.05},testCoverageRatio:{avg:.32,top10:.75},avgComplexity:{avg:6.5,top10:3.2},dependencyCVEs:{avg:4.2,top10:.3},ghostCodePercent:{avg:7.5,top10:1.5},cloneRatio:{avg:.09,top10:.02}},typescript:{trustScore:{avg:74,top10:91},criticalFindingsPer1k:{avg:1.2,top10:.1},hallucinationsPer1k:{avg:.4,top10:.03},testCoverageRatio:{avg:.42,top10:.82},avgComplexity:{avg:5.8,top10:2.9},dependencyCVEs:{avg:3.1,top10:.2},ghostCodePercent:{avg:5.8,top10:1},cloneRatio:{avg:.07,top10:.015}},python:{trustScore:{avg:71,top10:90},criticalFindingsPer1k:{avg:1.5,top10:.15},hallucinationsPer1k:{avg:.5,top10:.04},testCoverageRatio:{avg:.48,top10:.85},avgComplexity:{avg:5.2,top10:2.7},dependencyCVEs:{avg:3.6,top10:.25},ghostCodePercent:{avg:6.2,top10:1.2},cloneRatio:{avg:.06,top10:.01}},go:{trustScore:{avg:79,top10:94},criticalFindingsPer1k:{avg:.7,top10:.05},hallucinationsPer1k:{avg:.2,top10:.01},testCoverageRatio:{avg:.55,top10:.88},avgComplexity:{avg:4.5,top10:2.3},dependencyCVEs:{avg:1.8,top10:.1},ghostCodePercent:{avg:3.5,top10:.5},cloneRatio:{avg:.04,top10:.005}},ruby:{trustScore:{avg:70,top10:89},criticalFindingsPer1k:{avg:1.4,top10:.15},hallucinationsPer1k:{avg:.45,top10:.04},testCoverageRatio:{avg:.5,top10:.85},avgComplexity:{avg:5.5,top10:2.8},dependencyCVEs:{avg:3.4,top10:.2},ghostCodePercent:{avg:6,top10:1.1},cloneRatio:{avg:.07,top10:.015}},php:{trustScore:{avg:62,top10:85},criticalFindingsPer1k:{avg:2.4,top10:.3},hallucinationsPer1k:{avg:.7,top10:.06},testCoverageRatio:{avg:.25,top10:.65},avgComplexity:{avg:7.2,top10:3.6},dependencyCVEs:{avg:5.5,top10:.4},ghostCodePercent:{avg:9,top10:2},cloneRatio:{avg:.11,top10:.025}},java:{trustScore:{avg:76,top10:92},criticalFindingsPer1k:{avg:1,top10:.1},hallucinationsPer1k:{avg:.3,top10:.02},testCoverageRatio:{avg:.5,top10:.85},avgComplexity:{avg:5,top10:2.6},dependencyCVEs:{avg:2.5,top10:.15},ghostCodePercent:{avg:4.8,top10:.8},cloneRatio:{avg:.06,top10:.01}},default:{trustScore:{avg:70,top10:89},criticalFindingsPer1k:{avg:1.5,top10:.2},hallucinationsPer1k:{avg:.5,top10:.05},testCoverageRatio:{avg:.4,top10:.8},avgComplexity:{avg:5.8,top10:3},dependencyCVEs:{avg:3.5,top10:.25},ghostCodePercent:{avg:6.5,top10:1.2},cloneRatio:{avg:.07,top10:.015}}},SIZE_ADJUSTMENT={xs:{findings:.8,coverage:1.1,complexity:.9},small:{findings:1,coverage:1,complexity:1},medium:{findings:1.15,coverage:.92,complexity:1.05},large:{findings:1.3,coverage:.85,complexity:1.1},xl:{findings:1.45,coverage:.78,complexity:1.15}},EXT_TO_LANG={".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".ts":"typescript",".tsx":"typescript",".py":"python",".go":"go",".rb":"ruby",".php":"php",".java":"java"};function detectPrimaryLanguage(e={}){let t=null,a=-1;for(const[o,n]of Object.entries(e))n>a&&(a=n,t=o);return EXT_TO_LANG[t]||"default"}function percentileRank(e,t,a,o){if(t===a)return 50;let n;return n=o?e<=t?e/t*50:50+(e-t)/(a-t)*40:e>=t?t/Math.max(e,1e-4)*50:50+(t-e)/Math.max(t-a,1e-4)*40,Math.max(1,Math.min(99,Math.round(n)))}function generateBenchmarks(e={}){const t=e.lineCount||1,a=detectPrimaryLanguage(e.languageLineCounts||{}),o=bucketFor(t),n=BASE_METRICS_BY_LANG[a]||BASE_METRICS_BY_LANG.default,i=SIZE_ADJUSTMENT[o.key],g=Math.max(t/1e3,.1),r=(e.criticalFindings||0)/g,p=(e.hallucinations||0)/g,c=[{key:"trustScore",label:"Trust Score",unit:"/100",higherIsBetter:!0,value:e.trustScore||0,avg:Math.round(n.trustScore.avg),top10:Math.round(n.trustScore.top10)},{key:"criticalFindings",label:"Critical Findings per 1K LOC",unit:"",higherIsBetter:!1,value:Math.round(100*r)/100,avg:Math.round(n.criticalFindingsPer1k.avg*i.findings*100)/100,top10:n.criticalFindingsPer1k.top10},{key:"hallucinations",label:"Hallucinated APIs per 1K LOC",unit:"",higherIsBetter:!1,value:Math.round(100*p)/100,avg:Math.round(n.hallucinationsPer1k.avg*i.findings*100)/100,top10:n.hallucinationsPer1k.top10},{key:"testCoverageRatio",label:"Test Coverage Ratio (proxy)",unit:"%",higherIsBetter:!0,value:Math.round(100*(e.testCoverageRatio||0)),avg:Math.round(n.testCoverageRatio.avg*i.coverage*100),top10:Math.round(100*n.testCoverageRatio.top10)},{key:"avgComplexity",label:"Avg Cyclomatic Complexity",unit:"",higherIsBetter:!1,value:Math.round(10*(e.avgComplexity||0))/10,avg:Math.round(n.avgComplexity.avg*i.complexity*10)/10,top10:n.avgComplexity.top10},{key:"dependencyCVEs",label:"Dependency CVEs",unit:"",higherIsBetter:!1,value:e.dependencyCVEs||0,avg:Math.round(n.dependencyCVEs.avg*i.findings*10)/10,top10:n.dependencyCVEs.top10},{key:"ghostCodePercent",label:"Ghost / Dead Code %",unit:"%",higherIsBetter:!1,value:Math.round(10*(e.ghostCodePercent||0))/10,avg:Math.round(n.ghostCodePercent.avg*i.findings*10)/10,top10:n.ghostCodePercent.top10},{key:"cloneRatio",label:"Code Clone Ratio",unit:"%",higherIsBetter:!1,value:Math.round(1e3*(e.cloneRatio||0))/10,avg:Math.round(n.cloneRatio.avg*i.findings*1e3)/10,top10:Math.round(1e3*n.cloneRatio.top10)/10}].map(e=>({...e,percentile:percentileRank(e.value,e.avg,e.top10,e.higherIsBetter)}));return{language:a,bucket:{key:o.key,label:o.label},metrics:c}}module.exports={generateBenchmarks:generateBenchmarks,detectPrimaryLanguage:detectPrimaryLanguage,bucketFor:bucketFor,LOC_BUCKETS:LOC_BUCKETS};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const parser=require("@babel/parser"),path=require("path"),{walk:walk,buildIssue:buildIssue}=require("./ast-analyzer")._internal,BABEL_PLUGINS=["estree","typescript","jsx","classProperties","decorators-legacy"],MAX_CFG_FILE_SIZE=2e4;function lineOf(e){return e&&e.loc?e.loc.start.line:0}function snippet(e,t){return!t||t<1||t>e.length?"":e[t-1].trim().substring(0,100)}function mkIssue(e,t,n,a){return buildIssue(e,t,n,{...a,category:"quality",source:"cfg"})}function isFunctionNode(e){return"FunctionDeclaration"===e.type||"FunctionExpression"===e.type||"ArrowFunctionExpression"===e.type}const LOOP_TYPES=new Set(["WhileStatement","ForStatement","DoWhileStatement","ForInStatement","ForOfStatement"]);function staticTruthiness(e){if(!e)return null;if("Literal"===e.type)return null!==e.value&&("boolean"==typeof e.value?e.value:"number"==typeof e.value?0!==e.value&&!Number.isNaN(e.value):"string"==typeof e.value?e.value.length>0:null);if("UnaryExpression"===e.type&&"!"===e.operator){const t=staticTruthiness(e.argument);return null===t?null:!t}return null}function loopHasExit(e){let t=!1;return function e(n,a){if(t||!n||"object"!=typeof n||"string"!=typeof n.type)return;if(isFunctionNode(n))return;if("ReturnStatement"===n.type||"ThrowStatement"===n.type)return void(t=!0);if("BreakStatement"===n.type||"ContinueStatement"===n.type)return void((n.label||0===a)&&(t=!0));const r=LOOP_TYPES.has(n.type)||"SwitchStatement"===n.type?a+1:a;for(const t in n){if("loc"===t||"range"===t||"start"===t||"end"===t)continue;const a=n[t];if(Array.isArray(a))for(const t of a)t&&"object"==typeof t&&"string"==typeof t.type&&e(t,r);else a&&"object"==typeof a&&"string"==typeof a.type&&e(a,r)}}(e,0),t}function isStaticallyInfinite(e){return"ForStatement"===e.type?!e.test:("WhileStatement"===e.type||"DoWhileStatement"===e.type)&&!0===staticTruthiness(e.test)}function blockTerminates(e){let t=!1;for(const n of e){if(t)break;terminates(n)&&(t=!0)}return t}function terminates(e){switch(e.type){case"ReturnStatement":case"ThrowStatement":case"BreakStatement":case"ContinueStatement":return!0;case"BlockStatement":return blockTerminates(e.body);case"IfStatement":return!!e.alternate&&terminates(e.consequent)&&terminates(e.alternate);case"TryStatement":return!(!e.finalizer||!blockTerminates(e.finalizer.body))||!!e.handler&&blockTerminates(e.block.body)&&blockTerminates(e.handler.body.body);case"WhileStatement":case"ForStatement":case"DoWhileStatement":return isStaticallyInfinite(e)&&!loopHasExit(e.body);case"LabeledStatement":return terminates(e.body);default:return!1}}function isNoiseStatement(e){return"FunctionDeclaration"===e.type||"EmptyStatement"===e.type}function scanBlockBody(e,t,n,a){let r=!1;for(const i of e){if(r){isNoiseStatement(i)||a.push(mkIssue(t,lineOf(i),n,{type:"unreachable_code",severity:"warning",id:"CFG001",name:"Unreachable Code (CFG)",message:"This code can never execute - it follows a return/throw/break/continue (or an if/else where both branches always exit)"}));break}scanStatement(i,t,n,a),terminates(i)&&(r=!0)}}function scanStatement(e,t,n,a){switch(e.type){case"BlockStatement":scanBlockBody(e.body,t,n,a);break;case"IfStatement":scanStatement(e.consequent,t,n,a),e.alternate&&scanStatement(e.alternate,t,n,a);break;case"WhileStatement":case"DoWhileStatement":case"ForStatement":case"ForInStatement":case"ForOfStatement":case"LabeledStatement":scanStatement(e.body,t,n,a);break;case"SwitchStatement":for(const r of e.cases)scanBlockBody(r.consequent,t,n,a);break;case"TryStatement":scanBlockBody(e.block.body,t,n,a),e.handler&&scanBlockBody(e.handler.body.body,t,n,a),e.finalizer&&scanBlockBody(e.finalizer.body,t,n,a)}}function analyzeReachability(e,t,n,a){scanBlockBody(e.body,t,n,a),walk(e,e=>{isFunctionNode(e)&&e.body&&"BlockStatement"===e.body.type&&scanBlockBody(e.body.body,t,n,a)})}function analyzeLoopsAndBranches(e,t,n,a){walk(e,e=>{if(!LOOP_TYPES.has(e.type)||"WhileStatement"!==e.type&&"ForStatement"!==e.type&&"DoWhileStatement"!==e.type||isStaticallyInfinite(e)&&!loopHasExit(e.body)&&a.push(mkIssue(t,lineOf(e),n,{type:"infinite_loop",severity:"warning",id:"CFG002",name:"Infinite Loop With No Exit (CFG)",message:"Loop condition is always true and no break/return/throw was found anywhere inside it - this will hang"})),"IfStatement"===e.type){const r=staticTruthiness(e.test);null!==r&&a.push(mkIssue(t,lineOf(e),n,{type:"dead_branch",severity:"warning",id:"CFG003",name:"Dead Branch (CFG)",message:r?"Condition is always truthy - the else branch (if any) can never execute":e.alternate?"Condition is always falsy - the if branch can never execute, only else runs":"Condition is always falsy - this if branch can never execute"}))}if("ConditionalExpression"===e.type){const r=staticTruthiness(e.test);null!==r&&a.push(mkIssue(t,lineOf(e),n,{type:"dead_branch",severity:"warning",id:"CFG003",name:"Dead Branch (CFG)",message:r?"Ternary condition is always truthy - the alternate expression can never be reached":"Ternary condition is always falsy - the consequent expression can never be reached"}))}"WhileStatement"!==e.type&&"ForStatement"!==e.type||!e.test||!1===staticTruthiness(e.test)&&a.push(mkIssue(t,lineOf(e),n,{type:"dead_loop",severity:"warning",id:"CFG004",name:"Dead Loop (CFG)",message:"Loop condition is always false - the loop body will never execute, not even once"}))})}const FS_SYNC_THROWING=new Set(["readFileSync","writeFileSync","appendFileSync","readdirSync","statSync","lstatSync","unlinkSync","mkdirSync","rmdirSync","rmSync","renameSync","copyFileSync","accessSync","chmodSync","chownSync","symlinkSync","readlinkSync","realpathSync","openSync","closeSync","readSync","writeSync","truncateSync","utimesSync","mkdtempSync"]);function isKnownThrowingCall(e){if("CallExpression"!==e.type||"MemberExpression"!==e.callee.type)return null;const{object:t,property:n}=e.callee;return"Identifier"!==n.type?null:"Identifier"===t.type&&"JSON"===t.name&&"parse"===n.name?"JSON.parse":"Identifier"===t.type&&"fs"===t.name&&FS_SYNC_THROWING.has(n.name)?`fs.${n.name}`:null}function analyzeExceptionGaps(e,t,n,a){!function e(r,i){if(!r||"object"!=typeof r||"string"!=typeof r.type)return;if("TryStatement"===r.type)return e(r.block,!!r.handler),r.handler&&e(r.handler.body,i),void(r.finalizer&&e(r.finalizer,i));if(isFunctionNode(r))return void e(r.body,!1);const o=isKnownThrowingCall(r);o&&!i&&a.push(mkIssue(t,lineOf(r),n,{type:"exception_handling_gap",severity:"warning",id:"CFG005",name:"Missing Error Handling (CFG)",message:`${o}() can throw and is not wrapped in a try/catch`}));for(const t in r){if("loc"===t||"range"===t||"start"===t||"end"===t)continue;const n=r[t];if(Array.isArray(n))for(const t of n)t&&"object"==typeof t&&"string"==typeof t.type&&e(t,i);else n&&"object"==typeof n&&"string"==typeof n.type&&e(n,i)}}(e,!1)}const JS_EXTS=new Set([".js",".jsx",".ts",".tsx",".mjs",".cjs"]);function analyzeJSCfg(e,t){const n=[],a=t.split("\n");let r;try{r=parser.parse(t,{sourceType:"unambiguous",plugins:BABEL_PLUGINS,allowReturnOutsideFunction:!0,allowImportExportEverywhere:!0,allowAwaitOutsideFunction:!0,allowSuperOutsideMethod:!0,allowUndeclaredExports:!0,errorRecovery:!1}).program}catch(e){return n}return analyzeReachability(r,e,a,n),analyzeLoopsAndBranches(r,e,a,n),analyzeExceptionGaps(r,e,a,n),n}function analyze(e,t){if(t.length>2e4)return[];const n=path.extname(e).toLowerCase();try{if(JS_EXTS.has(n))return analyzeJSCfg(e,t)}catch(e){return[]}return[]}module.exports={analyze:analyze,analyzeJSCfg:analyzeJSCfg,_internal:{staticTruthiness:staticTruthiness,loopHasExit:loopHasExit,terminates:terminates,blockTerminates:blockTerminates,isKnownThrowingCall:isKnownThrowingCall}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const fs=require("fs"),path=require("path"),EventEmitter=require("events"),astAnalyzer=require("./ast-analyzer"),taintTracker=require("./taint-tracker"),cfgAnalyzer=require("./cfg-analyzer"),{getCodeScannerPatterns:getCodeScannerPatterns}=require("../crucible/rule-loader.js");class CodeScanner extends EventEmitter{constructor(e={}){super();const t=new Set(["rootPath","ignorePatterns","maxFileSize","totalScanTimeout","perFileTimeout","complexityThreshold","nestingThreshold"]),s={};for(const i of Object.keys(e))t.has(i)&&(s[i]=e[i]);this.config={rootPath:s.rootPath||process.cwd(),ignorePatterns:s.ignorePatterns||["node_modules/**",".git/**","dist/**",".orion/snapshots/**"],maxFileSize:s.maxFileSize||5242880,totalScanTimeout:s.totalScanTimeout||3e5,perFileTimeout:s.perFileTimeout||1e4,complexityThreshold:s.complexityThreshold||15,nestingThreshold:s.nestingThreshold||4},this._scanStartTime=null,this.safePatterns=[/keyEnv\s*[:=]/i,/envVar\s*[:=]/i,/process\.env\[/,/process\.env\./,/model\s*[:=]\s*['"][^'"]+['"]/i,/version\s*[:=]\s*['"][^'"]+['"]/i,/claude-|gpt-|gemini-|llama-|mistral-|deepseek-|grok-|sonar-/i,/endpoint\s*[:=]/i,/https?:\/\//,/_API_KEY['"]/,/API_KEY['"]\s*\)/,/errors?\.\w+\s*=/i,/Error\s*[:=]/i,/required|invalid|must be|cannot be/i],this.testFilePatterns=[/\.test\.(js|ts|jsx|tsx)$/,/\.spec\.(js|ts|jsx|tsx)$/,/__tests__\//,/\.mock\.(js|ts)$/,/test-.*\.js$/],this.securityPatterns=getCodeScannerPatterns(),this.qualityPatterns=[{id:"QUAL001",name:"Console.log in Production",pattern:/console\.(log|debug|info)\(/,severity:"info",message:"console.log found - consider using proper logging",skipInTests:!0,skipInDirs:["test","scripts","tools","dev"],skipInCliEntrypoints:!0},{id:"QUAL002",name:"TODO Comment",pattern:/\/\/\s*TODO|\/\*\s*TODO|\*\s*TODO|#\s*TODO/i,severity:"info",message:"TODO comment found - track in issue system"},{id:"QUAL003",name:"FIXME Comment",pattern:/\/\/\s*FIXME|\/\*\s*FIXME|\*\s*FIXME|#\s*FIXME/i,severity:"warning",message:"FIXME comment found - needs attention"},{id:"QUAL004",name:"Empty Catch Block",pattern:/catch\s*\([^)]*\)\s*\{\s*\}/,severity:"warning",message:"Empty catch block swallows errors"},{id:"QUAL005",name:"Magic Number",pattern:/(?<![0-9a-zA-Z_])(?!(?:1000|2000|3000|3001|4000|5000|8000|8080|9000|80|443|24|60|1024|2048|4096)\b)\d{5,}(?![0-9])/,severity:"info",message:"Magic number detected - consider using named constant",skipInTests:!0},{id:"QUAL006",name:"Callback Hell",pattern:/\)\s*=>\s*\{[^}]*\)\s*=>\s*\{[^}]*\)\s*=>\s*\{/,severity:"warning",message:"Deeply nested callbacks - consider async/await"}],this.performancePatterns=[{id:"PERF001",name:"Sync FS in Async",pattern:/fs\.(readFileSync|writeFileSync|readdirSync|statSync)/,severity:"info",message:"Synchronous file operation - may block event loop if used in a server request path"},{id:"PERF002",name:"Missing Await",pattern:/async\s+function[^{]*\{[^}]*(?<!await\s)new\s+Promise/,severity:"warning",message:"Promise created in async function without await"},{id:"PERF003",name:"Loop Database Query",pattern:/for\s*\([^)]*\)\s*\{[^}]*(query|find|select|update)/i,severity:"error",message:"Possible N+1 query pattern - consider batch operation"},{id:"PERF004",name:"Large Array in Memory",pattern:/new\s+Array\s*\(\s*\d{6,}\s*\)/,severity:"warning",message:"Large array allocation - consider streaming"}],this.aiPatterns=[{id:"AI001",name:"Potentially Hallucinated Import",pattern:/require\(['"](?!\.)[^'"]+['"]\)/,severity:"info",message:"External dependency - verify it exists in package.json",check:(e,t,s)=>this._checkDependencyExists(e,s)},{id:"AI002",name:"Unused Import",pattern:/const\s+(\w+)\s*=\s*require\(['"][^'"]+['"]\)/,severity:"info",message:"Import may be unused - verify usage",check:(e,t)=>this._checkImportUsage(e,t)},{id:"AI003",name:"Over-Engineered Pattern",pattern:/class\s+\w+Factory\s*\{|AbstractFactory|Singleton\.getInstance/,severity:"info",message:"Complex pattern detected - ensure justified by requirements"}]}async scanAll(){console.log("[CODE-SCANNER] Starting full codebase scan...");const e=Date.now();this._scanStartTime=e;const t={filesScanned:0,filesSkipped:0,issues:[],summary:{},duration:0};try{const s=await this._discoverFiles(this.config.rootPath);console.log(`[CODE-SCANNER] Found ${s.length} files to scan`),this._exportTaintMap=this._buildExportTaintMap(s);for(const i of s){if(Date.now()-e>this.config.totalScanTimeout){console.warn(`[CODE-SCANNER] Total scan timeout (${Math.round(this.config.totalScanTimeout/1e3)}s) reached — stopping scan`),t.issues.push({file:"scan",category:"info",severity:"warning",id:"TIMEOUT001",message:`Scan stopped after ${Math.round(this.config.totalScanTimeout/1e3)}s timeout — ${s.length-t.filesScanned} files not scanned`});break}const n=Date.now(),r=await this.scanFile(i),a=Date.now()-n;a>this.config.perFileTimeout&&console.warn(`[CODE-SCANNER] File ${i} took ${a}ms (>${this.config.perFileTimeout}ms) — results included but flagged`),t.filesScanned++,t.issues.push(...r)}return this._exportTaintMap=null,t.duration=Date.now()-e,t.summary=this._summarizeIssues(t.issues),console.log(`[CODE-SCANNER] Scan complete: ${t.filesScanned} files, ${t.issues.length} issues`),t}catch(e){return console.error("[CODE-SCANNER] Scan failed"),t.error="Scan failed",t}}async scanFiles(e){const t=Date.now();this._scanStartTime=t;const s={filesScanned:0,filesSkipped:0,issues:[],summary:{}};this._exportTaintMap=this._buildExportTaintMap(e);for(const i of e){if(Date.now()-t>this.config.totalScanTimeout){console.warn(`[CODE-SCANNER] Total scan timeout (${Math.round(this.config.totalScanTimeout/1e3)}s) reached — stopping scan`),s.issues.push({file:"scan",category:"info",severity:"warning",id:"TIMEOUT001",message:`Scan stopped after ${Math.round(this.config.totalScanTimeout/1e3)}s timeout — ${e.length-s.filesScanned} files not scanned`});break}const n=Date.now(),r=await this.scanFile(i),a=Date.now()-n;a>this.config.perFileTimeout&&(console.warn(`[CODE-SCANNER] WARNING: ${i} took ${a}ms (>${this.config.perFileTimeout}ms) — skipping slow file`),s.filesSkipped++,s.issues.push({file:i,category:"performance",severity:"warning",id:"TIMEOUT002",message:`File scan took ${a}ms — exceeded ${this.config.perFileTimeout}ms per-file limit`})),s.filesScanned++,s.issues.push(...r)}return this._exportTaintMap=null,s.summary=this._summarizeIssues(s.issues),s}async scanFile(e){const t=[];try{const s=fs.statSync(e);if(s.isSymbolicLink&&s.isSymbolicLink())return[];if(0===s.size)return[];if(s.size>this.config.maxFileSize)return[{file:e,category:"quality",severity:"info",id:"FILE001",message:`File too large (${(s.size/1048576).toFixed(1)}MB > ${(this.config.maxFileSize/1048576).toFixed(0)}MB limit) - skipped`}];let i;try{i=fs.readFileSync(e)}catch(e){return[]}const n=Math.min(i.length,512);for(let e=0;e<n;e++)if(0===i[e])return[];const r=i.toString("utf8").replace(/\r\n/g,"\n"),a=r.split("\n"),o=path.extname(e).toLowerCase();[".js",".ts",".jsx",".tsx",".mjs",".cjs",".vue",".svelte",".astro",".py",".pyw",".pyi",".pyx",".go",".rs",".java",".jsp",".kt",".kts",".cs",".cshtml",".razor",".vb",".fs",".fsx",".fsi",".php",".phtml",".blade.php",".rb",".erb",".rake",".gemspec",".swift",".m",".mm",".c",".h",".cpp",".cc",".cxx",".hpp",".hxx",".hh",".ino",".scala",".sc",".dart",".lua",".pl",".pm",".t",".r",".R",".Rmd",".groovy",".gvy",".gradle",".ex",".exs",".heex",".erl",".hrl",".hs",".lhs",".clj",".cljs",".cljc",".edn",".ml",".mli",".re",".rei",".nim",".nims",".zig",".cr",".jl",".d",".adb",".ads",".f90",".f95",".f03",".f08",".f",".for",".cob",".cbl",".cpy",".pas",".pp",".dpr",".cls",".trigger",".abap",".ps1",".psm1",".psd1",".sh",".bash",".zsh",".fish",".bat",".cmd",".sol",".move",".vy",".sql",".psql",".plsql",".graphql",".gql",".proto",".thrift",".html",".htm",".xhtml",".ejs",".hbs",".handlebars",".mustache",".pug",".jade",".haml",".slim",".twig",".njk",".liquid",".jinja",".jinja2",".css",".scss",".sass",".less",".styl",".xml",".xsl",".xslt",".xsd",".wsdl",".svg",".plist",".csproj",".sln",".props",".json",".jsonc",".json5",".yaml",".yml",".toml",".ini",".cfg",".conf",".env",".properties",".tf",".hcl",".dockerfile",".bicep",".pp",".md",".mdx",".rst",".adoc",".tex",".ipynb",".cmake",".as",".coffee",".ls",".elm",".purs",".v",".vv",".mojo",".tcl",".scm",".ss",".rkt",".lisp",".lsp",".cl",".pro",".P",".st",".vhd",".vhdl",".sv",".svh"].includes(o)&&(t.push(...this._runPatternScan(e,r,a,this.securityPatterns,"security")),t.push(...this._runPatternScan(e,r,a,this.qualityPatterns,"quality")),t.push(...this._runPatternScan(e,r,a,this.performancePatterns,"performance")),t.push(...this._runPatternScan(e,r,a,this.aiPatterns,"ai")),t.push(...this._analyzeComplexity(e,r,a)),t.push(...this._analyzeNesting(e,r,a)),t.push(...this._runAstScan(e,r,t)),t.push(...this._runTaintScan(e,r,t)),t.push(...this._runCfgScan(e,r,t))),".json"===o&&t.push(...this._scanJson(e,r));const c=this._applyThubanIgnore(a,t);for(const e of c)this.emit("issueFound",e);return c}catch(t){return[{file:e,category:"error",severity:"error",id:"SCAN001",message:"Failed to scan file: "+("ENOENT"===t.code?"File not found":"EACCES"===t.code?"Permission denied":"EISDIR"===t.code?"Path is a directory":"Scan error")}]}}_applyThubanIgnore(e,t){if(!t.length)return t;const s=new Map;for(let t=0;t<e.length;t++){const i=e[t].match(/thuban-ignore(?:\s+([A-Za-z0-9_,\s]+))?/);if(!i)continue;const n=i[1],r=[t+1,t+2];for(const e of r){if(!n||!n.trim()){s.set(e,!0);continue}const t=n.split(",").map(e=>e.trim()).filter(Boolean),i=s.get(e);if(!0===i)continue;const r=i instanceof Set?i:new Set;for(const e of t)r.add(e);s.set(e,r)}}return 0===s.size?t:t.filter(e=>{if(null==e.line)return!0;const t=s.get(e.line);return!t||!0!==t&&!t.has(e.id)})}getRules(){return{security:this.securityPatterns.map(e=>({id:e.id,name:e.name,severity:e.severity})),quality:this.qualityPatterns.map(e=>({id:e.id,name:e.name,severity:e.severity})),performance:this.performancePatterns.map(e=>({id:e.id,name:e.name,severity:e.severity})),ai:this.aiPatterns.map(e=>({id:e.id,name:e.name,severity:e.severity}))}}async _discoverFiles(e,t=[],s=0){if(s>100)return t;try{const i=fs.readdirSync(e,{withFileTypes:!0});for(const n of i){const i=path.join(e,n.name),r=path.relative(this.config.rootPath,i);if(!this._shouldIgnore(r))if(n.isDirectory())await this._discoverFiles(i,t,s+1);else if(n.isFile()){const e=path.extname(n.name).toLowerCase();[".js",".ts",".jsx",".tsx",".mjs",".cjs",".vue",".svelte",".astro",".json",".jsonc",".json5",".py",".pyw",".pyi",".pyx",".go",".rs",".java",".jsp",".kt",".kts",".cs",".cshtml",".razor",".vb",".fs",".fsx",".fsi",".php",".phtml",".rb",".erb",".rake",".gemspec",".swift",".m",".mm",".c",".h",".cpp",".cc",".cxx",".hpp",".hxx",".hh",".ino",".scala",".sc",".dart",".lua",".pl",".pm",".t",".r",".R",".Rmd",".groovy",".gvy",".gradle",".ex",".exs",".heex",".erl",".hrl",".hs",".lhs",".clj",".cljs",".cljc",".edn",".ml",".mli",".re",".rei",".nim",".nims",".zig",".cr",".jl",".d",".adb",".ads",".f90",".f95",".f03",".f08",".f",".for",".cob",".cbl",".cpy",".pas",".pp",".dpr",".cls",".trigger",".abap",".ps1",".psm1",".psd1",".sh",".bash",".zsh",".fish",".bat",".cmd",".sol",".move",".vy",".sql",".psql",".plsql",".graphql",".gql",".proto",".thrift",".html",".htm",".xhtml",".ejs",".hbs",".handlebars",".mustache",".pug",".jade",".haml",".slim",".twig",".njk",".liquid",".jinja",".jinja2",".css",".scss",".sass",".less",".styl",".xml",".xsl",".xslt",".xsd",".wsdl",".svg",".plist",".csproj",".sln",".props",".yaml",".yml",".toml",".ini",".cfg",".conf",".env",".properties",".tf",".hcl",".dockerfile",".bicep",".md",".mdx",".rst",".adoc",".tex",".ipynb",".cmake",".as",".coffee",".ls",".elm",".purs",".v",".vv",".mojo",".tcl",".scm",".ss",".rkt",".lisp",".lsp",".cl",".pro",".P",".st",".vhd",".vhdl",".sv",".svh"].includes(e)&&t.push(i)}}}catch(e){}return t}_shouldIgnore(e){const t=e.replace(/\\/g,"/"),s=["node_modules",".git","dist",".vite"];for(const e of s)if(t.includes("/"+e+"/")||t.startsWith(e+"/")||t===e||t.endsWith("/"+e))return!0;for(const e of this.config.ignorePatterns){const s=e.replace(/\\/g,"/"),i=s.split("/")[0].replace(/\*/g,"");if(i&&(t===i||t.startsWith(i+"/")))return!0;let n=s.replace(/\./g,"\\.").replace(/\*\*/g,".*").replace(/\*/g,"[^/]*");if(new RegExp("^"+n).test(t))return!0}return!1}_runPatternScan(e,t,s,i,n){const r=[],a=path.basename(e),o=this.testFilePatterns.some(e=>e.test(a))||this.testFilePatterns.some(t=>t.test(e)&&!t.source.includes("\\.js$")),c=path.relative(this.config.rootPath,e).replace(/\\/g,"/");for(const a of i){if(a.skipInTests&&o)continue;if(a.skipInDirs&&a.skipInDirs.some(e=>c.startsWith(e+"/")||c.includes("/"+e+"/")))continue;if(a.skipInCliEntrypoints&&s[0]&&s[0].startsWith("#!"))continue;if(a.excludeExtensions){const t=path.extname(e).toLowerCase();if(a.excludeExtensions.includes(t))continue}if(a.context&&!a.lineContext&&!a.context.test(t))continue;let i=0;for(const o of s){if(i++,!a.matchInComments){const e=o.trim();if((e.startsWith("*")||e.startsWith("//")||e.startsWith("/*"))&&"QUAL002"!==a.id&&"QUAL003"!==a.id)continue}const c=o.match(a.pattern);if(c){if(a.skipIfSafe&&this.safePatterns.some(e=>e.test(o)))continue;if(a.check&&!a.check(c,t,e))continue;if("sql_injection"===a.type||"xss"===a.type){if(/\b(?:parseInt|parseFloat|Number|int|float|str|strconv\.(?:Atoi|Itoa|ParseInt|ParseFloat|ParseBool|FormatInt)|\.to_i|\.to_f|CGI\.escapeHTML|ERB::Util\.html_escape|html\.EscapeString|url\.QueryEscape|encodeURIComponent|encodeURI|htmlspecialchars|htmlentities)\b/.test(o))continue;if("sql_injection"===a.type){const e=/\bcreate(?:Hmac|Hash|Cipheriv|Cipher|Decipheriv|Decipher|Sign|Verify)\s*\(/i;let t=e.test(o);if(!t&&/^\s*\.\s*(?:update|digest)\s*\(/.test(o))for(let n=1;n<=5&&i-1-n>=0;n++){const r=s[i-1-n];if(e.test(r)){t=!0;break}if(!/^\s*\./.test(r)&&/[;{}]\s*$/.test(r))break}if(t)continue}if("sql_injection"===a.type&&/%[sd]\b/.test(o)&&/['"]\s*,\s*[(\[]/.test(o))continue}r.push({file:e,line:i,column:c.index,category:n,type:a.type||n,severity:a.severity,id:a.id,name:a.name,message:a.message,code:o.trim().substring(0,100),...a.owasp&&{owasp:a.owasp},...a.cwe&&{cwe:a.cwe}})}}}return r}_runAstScan(e,t,s){let i;try{i=astAnalyzer.analyze(e,t)}catch(e){return[]}if(!i||0===i.length)return[];const n=new Set(s.map(e=>`${e.line}:${e.type}`));return i.filter(e=>!n.has(`${e.line}:${e.type}`))}_buildExportTaintMap(e){try{return taintTracker.buildExportTaintMap(e)}catch(e){return new Map}}_runTaintScan(e,t,s){let i;try{const s=path.extname(e).toLowerCase();if(new Set([".js",".jsx",".ts",".tsx",".mjs",".cjs"]).has(s)){let s;if(this._exportTaintMap){const i=taintTracker._internal.parseJS(t);i&&(s=taintTracker.buildImportSeeds(e,i,this._exportTaintMap,fs.existsSync))}i=taintTracker.analyzeJSTaint(e,t,s&&s.size?s:void 0)}else i=taintTracker.analyze(e,t)}catch(e){return[]}return i&&0!==i.length?i:[]}_runCfgScan(e,t,s){let i;try{i=cfgAnalyzer.analyze(e,t)}catch(e){return[]}if(!i||0===i.length)return[];const n=new Set(s.map(e=>`${e.line}:${e.type}`));return i.filter(e=>!n.has(`${e.line}:${e.type}`))}_analyzeComplexity(e,t,s){const i=[],n=t.match(/(?:^|\n)\s*(?:export\s+)?(?:async\s+)?function\s+\w+|=>\s*\{|(?:^|\n)\s*func\s+(?:\([^)]*\)\s+)?\w+\s*\(|(?:^|\n)\s*(?:pub\s+)?(?:async\s+)?fn\s+\w+|(?:^|\n)\s*def\s+(?:self\.)?\w+|(?:^|\n)\s*(?:public|private|protected|internal)?\s*(?:fun|suspend\s+fun)\s+\w+/gm)||[],r=t.match(/\b(if|else|for|while|switch|case|catch|&&|\|\||\?)\b/g)||[],a=n.length>0?r.length/n.length:0;return a>this.config.complexityThreshold&&i.push({file:e,category:"quality",severity:"warning",id:"CMPLX001",name:"High Complexity",message:`Average cyclomatic complexity is ${a.toFixed(1)} (threshold: ${this.config.complexityThreshold})`}),s.length>500&&i.push({file:e,category:"quality",severity:"info",id:"CMPLX002",name:"Long File",message:`File has ${s.length} lines - consider splitting`}),i}_analyzeNesting(e,t,s){const i=[],n=path.extname(e).toLowerCase();let r=0,a=0,o=0;if(".rb"===n){let e=0;for(const t of s){e++;const s=t.replace(/#.*$/,"").trim();if(!s)continue;const i=(s.match(/\b(?:def|do|if|unless|while|until|for|begin|case|class|module)\b/g)||[]).length;a+=i-(/\b(?:if|unless|while|until)\b/.test(s)&&!s.match(/^\s*(?:if|unless|while|until|elsif)\b/)&&1===i?1:0)-(s.match(/\bend\b/g)||[]).length,a<0&&(a=0),a>r&&(r=a,o=e)}}else if(".py"===n||".pyw"===n){let e=0;for(const i of s){if(e++,!i.trim()||i.trim().startsWith("#"))continue;const s=i.match(/^(\s*)/)[1].length,n=Math.floor(s/(t.includes("\t")?1:4));n>r&&(r=n,o=e)}}else{let e=0;for(const t of s)e++,a+=(t.match(/\{/g)||[]).length-(t.match(/\}/g)||[]).length,a>r&&(r=a,o=e)}return r>this.config.nestingThreshold&&i.push({file:e,line:o,category:"quality",severity:"warning",id:"NEST001",name:"Deep Nesting",message:`Max nesting depth is ${r} at line ${o} (threshold: ${this.config.nestingThreshold})`}),i}_scanJson(e,t){const s=[];try{JSON.parse(t)}catch(t){s.push({file:e,category:"quality",severity:"error",id:"JSON001",name:"Invalid JSON",message:`JSON parse error: ${t.message}`})}return/(password|secret|api[_-]?key|token)/i.test(t)&&s.push({file:e,category:"security",severity:"warning",id:"JSON002",name:"Sensitive Data in JSON",message:"Possible sensitive data in JSON file - verify not committed"}),s}_checkDependencyExists(e,t){const s=e[0].match(/require\(['"]([^'"]+)['"]\)/);if(!s)return!0;const i=s[1];if(i.startsWith("."))return!1;const n=i.startsWith("node:")?i.slice(5).split("/")[0]:i.split("/")[0];if(["assert","async_hooks","buffer","child_process","cluster","console","constants","crypto","dgram","diagnostics_channel","dns","domain","events","fs","http","http2","https","inspector","module","net","os","path","perf_hooks","process","punycode","querystring","readline","repl","stream","string_decoder","sys","test","timers","tls","trace_events","tty","url","util","v8","vm","wasi","worker_threads","zlib"].includes(n))return!1;const r=i.startsWith("@")?i.split("/").slice(0,2).join("/"):n;let a=path.dirname(t);const o=this.config.rootPath;for(;a.length>=o.length;){try{const e=path.join(a,"package.json");if(fs.existsSync(e)){const t=JSON.parse(fs.readFileSync(e,"utf8")),s={...t.dependencies||{},...t.devDependencies||{},...t.peerDependencies||{}};if(s[r]||s[i])return!1}}catch(e){}const e=path.dirname(a);if(e===a)break;a=e}return!0}_checkImportUsage(e,t){const s=e[1];if(!s)return!1;const i=new RegExp("\\b"+s+"\\b","g");return(t.match(i)||[]).length<=1}_summarizeIssues(e){return{total:e.length,bySeverity:{critical:e.filter(e=>"critical"===e.severity).length,error:e.filter(e=>"error"===e.severity).length,warning:e.filter(e=>"warning"===e.severity).length,info:e.filter(e=>"info"===e.severity).length},byCategory:e.reduce((e,t)=>(e[t.category]=(e[t.category]||0)+1,e),{}),topFiles:this._getTopFiles(e,10)}}_getTopFiles(e,t){const s=e.reduce((e,t)=>(e[t.file]=(e[t.file]||0)+1,e),{});return Object.entries(s).sort((e,t)=>t[1]-e[1]).slice(0,t).map(([e,t])=>({file:path.relative(this.config.rootPath,e),count:t}))}}module.exports=CodeScanner;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const FRAMEWORKS={owasp:{name:"OWASP Top 10 (2021)",requirements:[{id:"A01:2021",name:"Broken Access Control"},{id:"A02:2021",name:"Cryptographic Failures"},{id:"A03:2021",name:"Injection"},{id:"A04:2021",name:"Insecure Design"},{id:"A05:2021",name:"Security Misconfiguration"},{id:"A06:2021",name:"Vulnerable and Outdated Components"},{id:"A07:2021",name:"Identification and Authentication Failures"},{id:"A08:2021",name:"Software and Data Integrity Failures"},{id:"A09:2021",name:"Security Logging and Monitoring Failures"},{id:"A10:2021",name:"Server-Side Request Forgery"}]},soc2:{name:"SOC 2 Type II",requirements:[{id:"CC6.1",name:"Logical Access — Provisioning & Credentials"},{id:"CC6.6",name:"Boundaries — External Access Protection"},{id:"CC7.1",name:"Vulnerability Management"},{id:"CC8.1",name:"Change Management"}]},pciDss:{name:"PCI DSS v4.0",requirements:[{id:"Req 6.2",name:"Bespoke/Custom Software Developed Securely"},{id:"Req 6.3",name:"Security Vulnerabilities Identified & Addressed"},{id:"Req 8",name:"Identify Users & Authenticate Access"}]},iso27001:{name:"ISO 27001:2022",requirements:[{id:"A.8.25",name:"Secure Development Life Cycle"},{id:"A.8.28",name:"Secure Coding"}]}},TYPE_MAP={hardcoded_secret:{owasp:"A02:2021",soc2:["CC6.1"],pciDss:["Req 8"],iso27001:["A.8.28"]},sql_injection:{owasp:"A03:2021",soc2:["CC7.1"],pciDss:["Req 6.2","Req 6.3"],iso27001:["A.8.28"]},eval_abuse:{owasp:"A03:2021",soc2:["CC7.1"],pciDss:["Req 6.2"],iso27001:["A.8.28"]},xss:{owasp:"A03:2021",soc2:["CC6.6"],pciDss:["Req 6.2"],iso27001:["A.8.28"]},insecure_config:{owasp:"A05:2021",soc2:["CC6.6"],pciDss:["Req 6.2"],iso27001:["A.8.25"]},memory_safety:{owasp:"A06:2021",soc2:["CC7.1"],pciDss:["Req 6.3"],iso27001:["A.8.28"]},command_injection:{owasp:"A03:2021",soc2:["CC7.1"],pciDss:["Req 6.2"],iso27001:["A.8.28"]},prototype_pollution:{owasp:"A03:2021",soc2:["CC7.1"],pciDss:["Req 6.2"],iso27001:["A.8.28"]},deprecated_api:{owasp:"A06:2021",soc2:["CC8.1"],pciDss:["Req 6.3"],iso27001:["A.8.28"]},env_injection:{owasp:"A05:2021",soc2:["CC6.6"],pciDss:["Req 6.2"],iso27001:["A.8.25"]}},CATEGORY_MAP={hallucination:{owasp:null,soc2:["CC7.1","CC8.1"],pciDss:["Req 6.3"],iso27001:["A.8.28"]},deprecated_api_usage:{owasp:"A06:2021",soc2:["CC8.1"],pciDss:["Req 6.3"],iso27001:["A.8.28"]},ghost_code:{owasp:null,soc2:["CC8.1"],pciDss:[],iso27001:["A.8.28"]},code_clone:{owasp:null,soc2:["CC8.1"],pciDss:[],iso27001:["A.8.28"]}};function _owaspIdFromField(e){if(!e||"string"!=typeof e)return null;const t=/^(A\d{2}:\d{4})/.exec(e.trim());return t?t[1]:null}function _severityRank(e){const t=String(e||"").toLowerCase();return"critical"===t?4:"error"===t||"high"===t?3:"warning"===t||"medium"===t?2:1}class ComplianceMapper{map({scanIssues:e=[],hallResults:t={},ghostResults:s={},cloneResults:i={}}={}){const n=this._collectFindings({scanIssues:e,hallResults:t,ghostResults:s,cloneResults:i}),o={};for(const[e,t]of Object.entries(FRAMEWORKS))o[e]={name:t.name,requirements:t.requirements.map(t=>this._buildRequirementStatus(e,t,n))};return o}_collectFindings({scanIssues:e,hallResults:t,ghostResults:s,cloneResults:i}){const n=[];for(const t of e||[]){const e=TYPE_MAP[t.type];if(!e)continue;const s=_owaspIdFromField(t.owasp)||e.owasp||null;n.push({mapping:{owasp:s,soc2:e.soc2,pciDss:e.pciDss,iso27001:e.iso27001},severity:t.severity||"warning",ref:`${t.file||"?"}:${t.line||"?"} (${t.id||t.type})`})}for(const e of t.phantomAPIs||[])n.push({mapping:CATEGORY_MAP.hallucination,severity:"critical",ref:`${e.file||"?"}:${e.line||"?"} (${e.name||e.id||"phantom API"})`});for(const e of t.deprecatedAPIs||[])n.push({mapping:CATEGORY_MAP.deprecated_api_usage,severity:"high",ref:`${e.file||"?"}:${e.line||"?"} (${e.name||e.id||"deprecated API"})`});for(const e of s.ghosts||[])n.push({mapping:CATEGORY_MAP.ghost_code,severity:e.severity||"low",ref:`${e.file||"?"}:${e.line||"?"} (${e.name||"dead code"})`});for(const e of i.clusters||[]){const t=e.members||[],s=t.length?t.map(e=>`${e.file||"?"}:${e.line||"?"}`).join(", "):e.pattern||"clone cluster";n.push({mapping:CATEGORY_MAP.code_clone,severity:e.severity||"medium",ref:s})}return n}_buildRequirementStatus(e,t,s){const i=s.filter(s=>{const i=s.mapping[e];return!!i&&(Array.isArray(i)?i.includes(t.id):i===t.id)});let n="Pass";return i.length>0&&(n=Math.max(...i.map(e=>_severityRank(e.severity)))>=3?"Fail":"Partial"),{id:t.id,name:t.name,status:n,findingCount:i.length,findings:i.map(e=>e.ref).slice(0,10)}}}function _fmtHours(e){return e<1?`${Math.round(60*e)}m`:Math.round(10*e)/10+"h"}function generateRecommendations({scanIssues:e=[],hallResults:t={},ghostResults:s={},cloneResults:i={},aiScoreResults:n={}}={}){const o=[],a=[],r=[],c=[],l=e.filter(e=>"hardcoded_secret"===e.type);l.length&&o.push({title:`${l.length} hardcoded secret${l.length>1?"s":""} in source code`,detail:"Rotate all exposed credentials immediately and move to environment variables or a secrets manager. Hardcoded secrets are a direct breach vector and a common deal-breaker in due diligence.",effort:_fmtHours(.5*l.length),count:l.length});const d=e.filter(e=>"hardcoded_secret"!==e.type&&"critical"===String(e.severity).toLowerCase());d.length&&o.push({title:`${d.length} other critical security finding${d.length>1?"s":""}`,detail:"Includes issues such as auth bypass patterns, unsafe eval usage, or disabled certificate validation. These pose immediate exploitation risk and should be resolved before closing.",effort:_fmtHours(.75*d.length),count:d.length});const u=e.filter(e=>"sql_injection"===e.type);u.length&&a.push({title:`${u.length} SQL injection risk${u.length>1?"s":""}`,detail:"Replace string-concatenated/interpolated queries with parameterized queries or an ORM query builder.",effort:_fmtHours(.75*u.length),count:u.length});const p=(t.phantomAPIs||[]).length;p&&a.push({title:`${p} hallucinated API call${p>1?"s":""} (will crash at runtime)`,detail:"These calls reference methods/modules that do not exist. Likely AI-generated code that was never executed. Replace with the correct API before these paths are hit in production.",effort:_fmtHours(.5*p),count:p});const h=e.filter(e=>!["hardcoded_secret","sql_injection"].includes(e.type)&&["error","high"].includes(String(e.severity).toLowerCase()));h.length&&a.push({title:`${h.length} other high-severity finding${h.length>1?"s":""}`,detail:"Command injection, XSS, and prototype pollution risks fall in this bucket — review and patch as part of the next sprint.",effort:_fmtHours(.5*h.length),count:h.length});const m=s.totalGhosts||0;m&&r.push({title:`${m} ghost/dead function${m>1?"s":""}`,detail:`${(s.totalWastedLines||0).toLocaleString()} lines of unreachable code inflating maintenance surface area. Safe to remove after a final reference check.`,effort:_fmtHours(m*(1/6)),count:m});const f=i.totalClusters||0;f&&r.push({title:`${f} code clone cluster${f>1?"s":""}`,detail:`${(i.totalDuplicateLines||0).toLocaleString()} duplicated lines. Extract into shared utilities/modules to reduce drift risk between copies.`,effort:_fmtHours(3*f),count:f});const g=(t.deprecatedAPIs||[]).length;g&&r.push({title:`${g} deprecated API${g>1?"s":""} in use`,detail:"Will break on future dependency/runtime upgrades. Schedule replacement before the next major version bump.",effort:_fmtHours(.25*g),count:g}),0===p&&c.push({title:"No hallucinated APIs detected",detail:"All API calls resolve to real methods — low AI-hallucination / runtime-crash risk."});const A=s.wastedPercent;"number"==typeof A&&A<5&&c.push({title:"Low dead-code ratio",detail:`Only ${A}% of the codebase is unreachable, indicating disciplined code hygiene and active maintenance.`}),0===f&&c.push({title:"No significant code duplication detected",detail:"Clean architecture with minimal copy-paste drift between modules."});const C=n.aiPercentage;return"number"==typeof C&&C<30&&c.push({title:"Healthy AI-dependency ratio",detail:`${C}% AI-generated code is within a manageable range — low bus-factor risk from AI tooling dependence.`}),0===e.filter(e=>"critical"===String(e.severity).toLowerCase()).length&&0===l.length&&c.push({title:"No critical security findings",detail:"No hardcoded secrets, auth bypasses, or other critical vulnerabilities were detected in the static scan."}),{beforeClose:o,within30Days:a,within90Days:r,positive:c}}module.exports={ComplianceMapper:ComplianceMapper,generateRecommendations:generateRecommendations,FRAMEWORKS:FRAMEWORKS};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const fs=require("fs"),path=require("path"),MAX_IGNORE_PATTERNS=1e3;function loadThubanIgnore(e){const t=[];try{const n=path.join(e,".thubanignore");if(fs.existsSync(n)){if(fs.statSync(n).size>262144)return console.warn("[THUBAN] WARNING: .thubanignore exceeds 256KB — ignoring to prevent DoS"),t;const e=fs.readFileSync(n,"utf-8");for(const n of e.split(/\r?\n/)){const e=n.trim();if(e&&!e.startsWith("#")&&(t.push(e),t.length>=1e3)){console.warn("[THUBAN] WARNING: .thubanignore has >1000 patterns — truncating to prevent DoS");break}}}}catch{}return t}function matchesIgnorePattern(e,t){const n=e.replace(/\\/g,"/");for(const e of t){const t=e.replace(/\\/g,"/").replace(/\/+$/,"");if(t&&"."!==t&&"*"!==t&&"**"!==t){if(t.endsWith("/**")){const e=t.slice(0,-3);if(!e||"."===e)continue;if(n===e||n.startsWith(e+"/"))return!0}if(n===t)return!0;if(n.startsWith(t+"/"))return!0}}return!1}const GENERATED_OUTPUT_PATTERN=/^thuban-(sbom-(cyclonedx|spdx)|investor-report|scan-results|passport)-.*\.(json|html)$/i,LOCKFILE_NAMES=new Set(["package-lock.json","npm-shrinkwrap.json","yarn.lock","pnpm-lock.yaml","composer.lock","Cargo.lock","Gemfile.lock","poetry.lock","Pipfile.lock","go.sum"]);function collectFiles(e,t=[]){const n=["node_modules",".git","dist","build",".next","__pycache__",".venv","venv","coverage",".cache",".turbo",...t],s=[".js",".ts",".jsx",".tsx",".mjs",".cjs",".py",".pyw",".go",".rs",".java",".kt",".cs",".php",".rb",".json"],i=1048576,o=[],r=path.resolve(e),c=loadThubanIgnore(r);let a=0,l=0;function u(e){const t=r+path.sep,n=path.resolve(e);return n===r||n.startsWith(t)}if(function e(t,f){if(o.length>=5e4)return;if(f>100)return;if(!u(t))return;let h;try{h=fs.readdirSync(t,{withFileTypes:!0})}catch(e){if("ENOTDIR"===e.code)try{const e=fs.lstatSync(t);if(e.isSymbolicLink())return;if(!u(t))return;e.isFile()&&s.some(e=>t.endsWith(e))&&e.size>0&&e.size<=i&&o.push(t)}catch{}return}for(const p of h){if(o.length>=5e4)return;if(n.some(e=>p.name===e))continue;if(p.name.includes("\0"))continue;if(GENERATED_OUTPUT_PATTERN.test(p.name))continue;if(LOCKFILE_NAMES.has(p.name))continue;const h=path.join(t,p.name),g=path.resolve(h);if(!u(g))continue;const m=path.relative(r,g);if(m.startsWith(".."))continue;if(c.length>0&&matchesIgnorePattern(m,c)){a++;continue}let d;try{d=fs.lstatSync(h)}catch{continue}d.isSymbolicLink()||(d.isDirectory()?e(h,f+1):d.isFile()&&s.some(e=>p.name.normalize("NFC").endsWith(e))&&(l++,d.size>0&&d.size<=i&&o.push(h)))}}(e,0),c.length>0&&l>0){const e=o.length+a;if(e>0){const t=a/e;t>.9&&console.warn(`[THUBAN] WARNING: .thubanignore is excluding ${a} of ${e} files (${Math.round(100*t)}%). This may indicate a malicious ignore file designed to suppress scan findings. Review .thubanignore carefully.`)}}return o}module.exports={collectFiles:collectFiles};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const fs=require("fs"),path=require("path"),EventEmitter=require("events");class FileWatcher extends EventEmitter{constructor(t={}){super(),this.config={rootPath:t.rootPath||process.cwd(),watchPatterns:t.watchPatterns||["**/*.js","**/*.ts","**/*.json"],ignorePatterns:t.ignorePatterns||["node_modules/**",".git/**","dist/**","build/**",".orion/snapshots/**","coverage/**","*.log"],debounceMs:t.debounceMs||300,...t},this.watchers=[],this.watchedFiles=new Set,this.debounceTimers=new Map,this.isRunning=!1}async start(){if(this.isRunning)return{success:!0,message:"Already watching"};console.log("[FILE-WATCHER] Starting file watcher..."),console.log(`[FILE-WATCHER] Root path: ${this.config.rootPath}`);try{return await this._discoverFiles(this.config.rootPath),this._setupWatchers(),this.isRunning=!0,console.log(`[FILE-WATCHER] Watching ${this.watchedFiles.size} files`),{success:!0,filesWatched:this.watchedFiles.size}}catch(t){return console.error("[FILE-WATCHER] Start failed"),{success:!1,error:"Start failed"}}}async stop(){console.log("[FILE-WATCHER] Stopping file watcher...");for(const t of this.watchers)try{t.close()}catch(t){}for(const t of this.debounceTimers.values())clearTimeout(t);return this.watchers=[],this.debounceTimers.clear(),this.isRunning=!1,console.log("[FILE-WATCHER] Stopped"),{success:!0}}getWatchedCount(){return this.watchedFiles.size}shouldIgnore(t){const e=path.relative(this.config.rootPath,t);for(const t of this.config.ignorePatterns)if(this._matchPattern(e,t))return!0;return!1}shouldWatch(t){const e=path.relative(this.config.rootPath,t);if(this.shouldIgnore(t))return!1;for(const t of this.config.watchPatterns)if(this._matchPattern(e,t))return!0;return!1}async _discoverFiles(t,e=0){if(!(e>100))try{const s=fs.readdirSync(t,{withFileTypes:!0});for(const i of s){const s=path.join(t,i.name);i.isDirectory()?this.shouldIgnore(s)||await this._discoverFiles(s,e+1):i.isFile()&&this.shouldWatch(s)&&this.watchedFiles.add(s)}}catch(t){"ENOENT"!==t.code&&"EACCES"!==t.code&&console.warn("[FILE-WATCHER] Error scanning directory")}}_setupWatchers(){const t=new Set;for(const e of this.watchedFiles)t.add(path.dirname(e));for(const e of t)try{const t=fs.watch(e,{persistent:!0},(t,s)=>{if(s){const i=path.join(e,s);this._handleFileEvent(t,i)}});t.on("error",()=>{}),this.watchers.push(t)}catch(t){console.warn("[FILE-WATCHER] Could not watch directory")}try{const t=fs.watch(this.config.rootPath,{recursive:!0},(t,e)=>{if(e){const s=path.join(this.config.rootPath,e);this._handleFileEvent(t,s)}});t.on("error",()=>{}),this.watchers.push(t)}catch(t){}}_handleFileEvent(t,e){this.shouldIgnore(e)||(this.debounceTimers.has(e)&&clearTimeout(this.debounceTimers.get(e)),this.debounceTimers.set(e,setTimeout(()=>{this.debounceTimers.delete(e),this._processFileEvent(t,e)},this.config.debounceMs)))}_processFileEvent(t,e){const s=fs.existsSync(e),i=s&&fs.statSync(e).isFile();let o;s?i&&this.shouldWatch(e)&&(this.watchedFiles.has(e)?o={type:"change",filePath:e,timestamp:(new Date).toISOString()}:(this.watchedFiles.add(e),o={type:"add",filePath:e,timestamp:(new Date).toISOString()})):this.watchedFiles.has(e)&&(this.watchedFiles.delete(e),o={type:"delete",filePath:e,timestamp:(new Date).toISOString()}),o&&(this.emit(o.type,o),this.emit("any",o))}_matchPattern(t,e){const s=t.replace(/\\/g,"/");let i=e.replace(/\\/g,"/").replace(/\./g,"\\.").replace(/\*\*/g,"<<<GLOBSTAR>>>").replace(/\*/g,"[^/]*").replace(/<<<GLOBSTAR>>>/g,".*").replace(/\?/g,".");i="^"+i+"$";try{return new RegExp(i).test(s)}catch(t){return!1}}}module.exports=FileWatcher;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const fs=require("fs"),path=require("path");class GhostCodeDetector{constructor(e={}){this.rootPath=e.rootPath||process.cwd()}scan(e){const t=[],s={},n=new Map,i=new Map,o=new Map;for(const r of e){let e;try{if(fs.statSync(r).size>524288)continue;e=fs.readFileSync(r,"utf-8").replace(/\r\n/g,"\n")}catch(e){continue}const c=path.relative(this.rootPath,r);if(this._isSkippable(c)){o.set(c,e);continue}const a=e.split("\n");n.set(c,e),i.set(c,a);const l=path.extname(r).toLowerCase(),f=this._computeTemplateLiteralLines(e);for(let e=0;e<a.length;e++){if(f.has(e))continue;const n=a[e],i=this._extractFunction(n,e,a,l);if(i){i.file=c,i.line=e+1,i.lineCount=this._countFunctionLines(a,e,l),i.declKind="function",i.isExport&&this._isFrameworkEntryFile(c)&&(i.isLifecycle=!0),t.push(i),s[i.name]||(s[i.name]=0);continue}const o=this._extractClass(n);if(o){o.file=c,o.line=e+1,o.lineCount=this._countFunctionLines(a,e,l),o.declKind="class",t.push(o),s[o.name]||(s[o.name]=0);continue}const r=this._extractConstDeclaration(n);if(r){r.file=c,r.line=e+1,r.lineCount=1,r.declKind="const",t.push(r),s[r.name]||(s[r.name]=0);continue}const u=this._extractImports(n);for(const n of u)n.file=c,n.line=e+1,n.lineCount=1,n.declKind="import",t.push(n),s[n.name]||(s[n.name]=0)}}const r=new Map([...n,...o]);for(const[e,n]of r){const i=this._stripCommentsAndStrings(n);for(const n of t){const t=new RegExp(`\\b${this._escapeRegex(n.name)}\\b`,"g"),o=i.match(t);if(o){const t=e===n.file;s[n.name]+=o.length-(t?1:0)}}}const c=t.filter(e=>"function"===e.declKind).filter(e=>(s[e.name]||0)<=0&&!e.isLifecycle&&e.lineCount>=3).map(e=>({...e,references:s[e.name]||0,wastedLines:e.lineCount,category:"ghost",severity:e.isExport?"low":e.lineCount>30?"high":"medium",message:`${e.name}() — ${e.lineCount} lines, never called${e.isExport?" (exported — verify no external consumers)":""}`})),a=(e,n,i,o)=>t.filter(t=>t.declKind===e).filter(e=>(s[e.name]||0)<=0).map(e=>({...e,references:s[e.name]||0,wastedLines:e.lineCount,category:n,severity:i(e),message:o(e)})),l=a("class","ghost_class",e=>e.isExport?"low":"medium",e=>`class ${e.name} — ${e.lineCount} lines, never referenced${e.isExport?" (exported — verify no external consumers)":""}`),f=a("const","ghost_const",e=>e.isExport?"low":"medium",e=>`${e.kind} ${e.name} — declared but never used${e.isExport?" (exported — verify no external consumers)":""}`),u=a("import","ghost_import",()=>"low",e=>`import '${e.name}' from '${e.source}' — never used`),p=this._findDeadClusters(t.filter(e=>"function"===e.declKind),n,s),m=[...c,...l,...f,...u,...p].sort((e,t)=>t.wastedLines-e.wastedLines),h=m.reduce((e,t)=>e+t.wastedLines,0),d=e.reduce((e,t)=>{try{return e+fs.readFileSync(t,"utf-8").replace(/\r\n/g,"\n").split("\n").length}catch(t){return e}},0);return{ghosts:m,totalGhosts:m.length,totalWastedLines:h,wastedPercent:d>0?Math.min(100,Math.round(h/d*1e3)/10):0,totalLines:d,breakdown:{functions:c.length,classes:l.length,consts:f.length,imports:u.length,deadClusters:p.length}}}_extractFunction(e,t,s,n){const i=e.trim(),o=new Set([".py",".pyw",".pyi",".pyx"]),r=n&&o.has(n),c=i.replace(/^export\s+(?:default\s+)?/,"");let a=c.match(/^(?:async\s+)?function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/);return a?{name:a[1],type:"function",isExport:this._isExported(e,t,s),isLifecycle:this._isLifecycle(a[1])}:(a=c.match(/^(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*(?:async\s+)?function/),a?{name:a[1],type:"const-function",isExport:this._isExported(e,t,s),isLifecycle:this._isLifecycle(a[1])}:(a=c.match(/^(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*(?:async\s+)?\(?/),a&&(c.includes("=>")||t+1<s.length&&s[t+1].includes("=>"))?{name:a[1],type:"arrow",isExport:this._isExported(e,t,s),isLifecycle:this._isLifecycle(a[1])}:r&&(a=i.match(/^(?:async\s+)?def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[(\[]/),a)?{name:a[1],type:"python-def",isExport:!/^_/.test(a[1]),isLifecycle:this._isLifecycle(a[1])}:(a=i.match(/^(?:private\s+|public\s+|internal\s+|protected\s+)?(?:suspend\s+)?fun\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[(<]/),a?{name:a[1],type:"kotlin-fun",isExport:!i.startsWith("private"),isLifecycle:this._isLifecycle(a[1])}:(a=i.match(/^func\s+(?:\([^)]*\)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/),a?{name:a[1],type:"go-func",isExport:/^[A-Z]/.test(a[1]),isLifecycle:this._isLifecycle(a[1])}:(a=i.match(/^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[(<]/),a?{name:a[1],type:"rust-fn",isExport:/^pub/.test(i),isLifecycle:this._isLifecycle(a[1])}:(a=i.match(/^(?:(?:public|private|protected|static)\s+)*function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/),a?{name:a[1],type:"php-function",isExport:!/private/.test(i),isLifecycle:this._isLifecycle(a[1])}:(a=i.match(/^def\s+(?:self\.)?([a-zA-Z_][a-zA-Z0-9_?!]*)\s*[(\s]?/),a?{name:a[1],type:"ruby-def",isExport:/^def\s+self\./.test(i),isLifecycle:this._isLifecycle(a[1])}:(a=i.match(/^(?:async\s+)?([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\([^)]*\)\s*{/),a&&!["if","for","while","switch","catch","constructor","render","toString"].includes(a[1])?{name:a[1],type:"method",isExport:!1,isLifecycle:this._isLifecycle(a[1])}:null))))))))}_isExported(e,t,s){return!!/^export\s/.test(e.trim())||!!/module\.exports/.test(e)}_extractClass(e){const t=e.trim(),s=t.match(/^(?:export\s+(?:default\s+)?)?class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);return s?{name:s[1],type:"class",isExport:/^export\s/.test(t),isLifecycle:!1}:null}_extractConstDeclaration(e){const t=e.trim().match(/^(export\s+)?(const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*(.+)$/);if(!t)return null;const[,s,n,i,o]=t;return/^(?:async\s+)?function\b/.test(o)||/=>/.test(o)||""===o.trim()||/^\(/.test(o.trim())&&/=>/.test(o)||/require\s*\(/.test(o)?null:{name:i,kind:n,type:"const-declaration",isExport:!!s,isLifecycle:!1}}_extractImports(e){const t=e.trim(),s=[];let n=t.match(/^import\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/);if(n){const e=n[1].split(",").map(e=>e.trim()).filter(Boolean);for(const t of e){const e=t.split(/\s+as\s+/),i=(e[1]||e[0]).trim();i&&s.push({name:i,source:n[2],type:"import"})}return s}if(n=t.match(/^import\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?:,|from)/),n&&!/^import\s*\{/.test(t)){const e=t.match(/from\s*['"]([^'"]+)['"]/);return s.push({name:n[1],source:e?e[1]:"",type:"import"}),s}if(n=t.match(/^import\s*\*\s*as\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*from\s*['"]([^'"]+)['"]/),n)return s.push({name:n[1],source:n[2],type:"import"}),s;if(n=t.match(/^(?:const|let|var)\s*\{([^}]+)\}\s*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/),n){const e=n[1].split(",").map(e=>e.trim()).filter(Boolean);for(const t of e){const e=t.split(":").map(e=>e.trim()),i=(e[1]||e[0]).trim();i&&s.push({name:i,source:n[2],type:"import"})}return s}return n=t.match(/^(?:const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/),n?(s.push({name:n[1],source:n[2],type:"import"}),s):s}_findDeadClusters(e,t,s){const n=[],i=new Map;for(const t of e)t.isExport||t.isLifecycle||i.set(t.name,t);if(i.size<2)return n;const o=new Map;for(const[e,s]of i){const n=t.get(s.file);if(!n){o.set(e,new Set);continue}const r=n.split("\n").slice(s.line-1,s.line-1+s.lineCount),c=this._stripCommentsAndStrings(r.join("\n")),a=new Set;for(const[t]of i)t!==e&&new RegExp(`\\b${this._escapeRegex(t)}\\b`).test(c)&&a.add(t);o.set(e,a)}const r=new Map,c=e=>{r.has(e)||r.set(e,e);let t=e;for(;r.get(t)!==t;)t=r.get(t);let s=e;for(;r.get(s)!==t;){const e=r.get(s);r.set(s,t),s=e}return t},a=(e,t)=>{const s=c(e),n=c(t);s!==n&&r.set(s,n)};for(const[e,t]of o){c(e);for(const s of t)c(s),a(e,s)}const l=new Map;for(const e of i.keys()){const t=c(e);l.has(t)||l.set(t,[]),l.get(t).push(e)}for(const[,e]of l){if(e.length<2)continue;let t=!1;for(const s of e){for(const n of o.get(s)||[])if(e.includes(n)&&(o.get(n)||new Set).has(s)){t=!0;break}if(t)break}if(!t)continue;let r=!1;for(const t of e)if((s[t]||0)-e.reduce((e,s)=>s===t?e:e+((o.get(s)||new Set).has(t)?1:0),0)>0){r=!0;break}if(r)continue;const c=e.reduce((e,t)=>e+(i.get(t).lineCount||0),0);n.push({name:e.join(", "),file:i.get(e[0]).file,line:i.get(e[0]).line,lineCount:c,wastedLines:c,references:0,category:"dead_cluster",severity:"high",message:`Dead cluster: ${e.join(" ↔ ")} — mutually reference each other but nothing outside the cluster calls them`})}return n}_isLifecycle(e){return["constructor","render","componentDidMount","componentWillUnmount","componentDidUpdate","shouldComponentUpdate","getSnapshotBeforeUpdate","getDerivedStateFromProps","useEffect","useState","useMemo","toString","valueOf","toJSON","inspect","setup","teardown","beforeEach","afterEach","beforeAll","afterAll","init","destroy","configure","bootstrap","main","get","set","post","put","delete","patch","handle","onCreate","onStart","onResume","onPause","onStop","onDestroy","onCreateView","onViewCreated","onDestroyView","hashCode","equals","new","default","drop","fmt","from","into","clone","copy","initialize","to_s","to_str","inspect","freeze","dup","__construct","__destruct","__toString","__get","__set","__call","log_message","log_request","log_error"].includes(e)||/^__/.test(e)||/^on[A-Z]/.test(e)||/^visit_[A-Z]/.test(e)||"visit_comprehension"===e||/^do_[A-Z]/.test(e)||/^test_/.test(e)}_countFunctionLines(e,t,s){const n=(e[t]||"").trim(),i=new Set([".py",".pyw",".pyi",".pyx"]);if(s&&i.has(s)&&/^(?:async\s+)?def\s/.test(n)){const s=(e[t].match(/^[ \t]*/)||[""])[0].length;let n=1;for(let i=t+1;i<e.length&&i<t+200;i++){const t=e[i];if(""!==t.trim()){if((t.match(/^[ \t]*/)||[""])[0].length<=s)break;n++}else n++}return n}if(/^def\s/.test(n)){let s=1,n=1;for(let i=t+1;i<e.length&&i<t+200;i++){n++;const t=e[i].trim();if(/^(?:def|class|module|begin|case)\b/.test(t)&&s++,/^(?:if|unless|while|until|for)\b/.test(t)&&!/\bthen\b/.test(t)&&s++,/\bdo\s*(\|[^|]*\|)?\s*$/.test(t)&&s++,/^end\b/.test(t)&&s--,s<=0)break}return n}let o=0,r=!1,c=0;for(let s=t;s<e.length&&s<t+200;s++){const t=e[s];c++;for(const e of t)"{"===e&&(o++,r=!0),"}"===e&&o--;if(r&&o<=0)break}return c}_isSkippable(e){return[/\.test\./i,/\.spec\./i,/test[\/\\]/i,/spec[\/\\]/i,/__test__/i,/__mocks__/i,/\.config\./i,/\.d\.ts$/,/index\.(js|ts)$/,/server\.(js|ts)$/,/app\.(js|ts)$/,/routes?\.(js|ts)$/,/middleware/i,/crucible\//i,/kenny-mode/i,/thuban-videos\//i,/regression\/fixtures\//i].some(t=>t.test(e))}_isFrameworkEntryFile(e){return/(^|[\/\\])(page|layout|loading|error|not-found|template|default|route)\.(js|jsx|ts|tsx)$/i.test(e)||/(^|[\/\\])middleware\.(js|ts)$/i.test(e)}_escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}_computeTemplateLiteralLines(e){const t=new Set,s=e.length;let n=0,i=0;for(;n<s;){const o=e[n],r=e[n+1];if("\n"!==o)if("/"===o&&"/"===r||"#"===o)for(;n<s&&"\n"!==e[n];)n++;else if("/"!==o||"*"!==r){if('"'===o||"'"===o){const t=o;for(n++;n<s&&e[n]!==t&&"\n"!==e[n];)"\\"===e[n]&&n++,n++;n=Math.min(n+1,s);continue}if("`"===o){const o=i,r=this._findTemplateEnd(e,n);for(let t=n;t<r&&t<s;t++)"\n"===e[t]&&i++;const c=i;if(c>o+1)for(let e=o+1;e<c;e++)t.add(e);n=r;continue}n++}else{for(n+=2;n<s&&("*"!==e[n]||"/"!==e[n+1]);)"\n"===e[n]&&i++,n++;n=Math.min(n+2,s)}else i++,n++}return t}_findTemplateEnd(e,t){let s=t+1;const n=e.length;for(;s<n;){const t=e[s];if("\\"!==t){if("`"===t)return s+1;if("$"===t&&"{"===e[s+1]){let t=1,i=s+2;for(;i<n&&t>0;){const s=e[i];if("{"===s)t++,i++;else if("}"===s)t--,i++;else if("`"===s)i=this._findTemplateEnd(e,i);else if('"'===s||"'"===s){const t=s;for(i++;i<n&&e[i]!==t;)"\\"===e[i]&&i++,i++;i++}else i++}s=i;continue}s++}else s+=2}return n}_stripTemplateLiteral(e,t){let s=t+1;const n=e.length,i=[];for(;s<n;){const t=e[s];if("\\"!==t){if("`"===t){s++;break}if("$"===t&&"{"===e[s+1]){let t=1,o=s+2;const r=o;for(;o<n&&t>0;){const s=e[o];if("{"===s)t++,o++;else if("}"===s)t--,o++;else if("`"===s)o=this._findTemplateEnd(e,o);else if('"'===s||"'"===s){const t=s;for(o++;o<n&&e[o]!==t;)"\\"===e[o]&&o++,o++;o++}else o++}i.push(e.slice(r,o-1)),s=o;continue}s++}else s+=2}return[i.length>0?`"" ${i.map(e=>this._stripCommentsAndStrings(e)).join(" ")} ""`:'""',s]}_canStartRegex(e){return!e||!/[A-Za-z0-9_$)\]]/.test(e)}_findRegexEnd(e,t){let s=t+1,n=!1;const i=e.length;for(;s<i;){const t=e[s];if("\n"===t)return-1;if("\\"!==t)if("["!==t)if("]"!==t){if("/"===t&&!n){for(s++;s<i&&/[a-zA-Z]/.test(e[s]);)s++;return s}s++}else n=!1,s++;else n=!0,s++;else s+=2}return-1}_stripCommentsAndStrings(e){let t="",s=0;const n=e.length;let i="";for(;s<n;){const o=e[s],r=e[s+1];if("/"===o&&"/"===r){let i=s+2;for(;i<n&&"\n"!==e[i];)i++;t+=" ",s=i;continue}if("#"===o){let i=s+1;for(;i<n&&"\n"!==e[i];)i++;t+=" ",s=i;continue}if("/"===o&&"*"===r){let i=s+2;for(;i<n&&("*"!==e[i]||"/"!==e[i+1]);)i++;i=Math.min(i+2,n),t+=" ",s=i;continue}if('"'===o){let o=s+1;for(;o<n&&'"'!==e[o]&&"\n"!==e[o];)"\\"===e[o]&&o++,o++;o=Math.min(o+1,n),t+='""',s=o,i='"';continue}if("'"===o){let o=s+1;for(;o<n&&"'"!==e[o]&&"\n"!==e[o];)"\\"===e[o]&&o++,o++;o=Math.min(o+1,n),t+="''",s=o,i="'";continue}if("`"===o){const[n,o]=this._stripTemplateLiteral(e,s);t+=n,s=o,i="`";continue}if("/"===o&&this._canStartRegex(i)){const n=this._findRegexEnd(e,s);if(-1!==n){t+=" ",s=n,i="/";continue}}t+=o,/\s/.test(o)||(i=o),s++}return t}}module.exports=GhostCodeDetector;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const{execFileSync:execFileSync}=require("child_process"),path=require("path"),fs=require("fs"),EXEC_OPTS_BASE={encoding:"utf-8",maxBuffer:33554432,timeout:2e4,stdio:["ignore","pipe","ignore"]},FS1="",RS1="";class GitVelocityAnalyzer{constructor(t={}){this.rootPath=t.rootPath||process.cwd(),this.now=t.now||new Date}analyze(){if(!this._hasGitBinary())return this._unavailable("git is not installed or not on PATH");if(!this._isGitRepo())return this._unavailable("target path is not inside a git repository");const t=this._getCommitLog();if(0===t.length)return this._unavailable("repository has no commits yet");const e=t.length,o=t[t.length-1].date,r=t[0].date,n=Math.max(1,Math.round((this.now-o)/864e5)),i=+(n/365).toFixed(1),s=this._buildContributorStats(t),a=Object.values(s).sort((t,e)=>e.commits-t.commits),c=a.length,l=this._calculateBusFactor(a,e),m=this._calculateCommitFrequency(t),u=this._calculateAvgTimeBetweenCommits(t),h=this._calculatePrMergeRate(t,e),d=this._attributeFocusAreas(t,a);for(const t of a)t.percentage=e>0?+(t.commits/e*100).toFixed(1):0,t.focusAreas=d[t.email]||[];const f=this._assessHealth({commitFrequency:m,busFactor:l,totalContributors:c,contributorList:a,totalCommits:e});return{available:!0,generatedAt:this.now.toISOString(),metrics:{totalCommits:e,totalContributors:c,repoAgeDays:n,repoAgeYears:i,firstCommitDate:o.toISOString(),lastCommitDate:r.toISOString(),busFactor:l.count,busFactorOwners:l.owners,busFactorThresholdPercent:l.thresholdPercent,commitsLast90Days:m.last90Days,commitsPerDay90d:m.perDay,commitsLast30Days:m.last30Days,commitsPerDay30d:m.perDay30,avgHoursBetweenCommits:u.avgHours,avgDaysBetweenCommits:u.avgDays,prMergeRate:h.rate,mergeCommitCount:h.mergeCommits,directCommitCount:h.directCommits,prMergeRateSource:h.source},contributors:a,health:f}}_unavailable(t){return{available:!1,reason:t,generatedAt:this.now.toISOString(),metrics:null,contributors:[],health:null}}_run(t){return execFileSync("git",t,{...EXEC_OPTS_BASE,cwd:this.rootPath})}_hasGitBinary(){try{return execFileSync("git",["--version"],{encoding:"utf-8",timeout:3e3,stdio:["ignore","pipe","ignore"]}),!0}catch{return!1}}_isGitRepo(){try{return"true"===this._run(["rev-parse","--is-inside-work-tree"]).trim()}catch{return!1}}_getCommitLog(){let t;try{t=this._run(["log","HEAD","--no-renames","--pretty=format:%H%an%ae%at%P"])}catch{return[]}if(!t||!t.trim())return[];const e=t.split("").map(t=>t.trim()).filter(Boolean),o=[],r=new Set;for(const t of e){const[e,n,i,s,a]=t.split("");if(!e||r.has(e))continue;r.add(e);const c=(a||"").trim().split(/\s+/).filter(Boolean);o.push({hash:e,authorName:n||"Unknown",email:(i||"unknown@unknown").toLowerCase(),date:new Date(1e3*parseInt(s,10)),isMerge:c.length>1})}return o.sort((t,e)=>e.date-t.date),o}_buildContributorStats(t){const e={};for(const o of t){const t=o.email;e[t]||(e[t]={name:o.authorName,email:o.email,commits:0,linesAdded:0,linesDeleted:0,firstCommit:o.date,lastCommit:o.date});const r=e[t];r.commits++,o.date>r.lastCommit&&(r.lastCommit=o.date),o.date<r.firstCommit&&(r.firstCommit=o.date)}try{const t=this._run(["log","HEAD","--no-renames","--numstat","--pretty=format:%ae"]).split("").map(t=>t.trim()).filter(Boolean);for(const o of t){const t=o.split("\n"),r=e[(t[0]||"unknown@unknown").trim().toLowerCase()];if(r)for(let e=1;e<t.length;e++){const o=t[e];if(!o)continue;const n=o.match(/^(\d+|-)\t(\d+|-)\t/);if(!n)continue;const i="-"===n[1]?0:parseInt(n[1],10),s="-"===n[2]?0:parseInt(n[2],10);r.linesAdded+=i,r.linesDeleted+=s}}}catch{}for(const t of Object.keys(e)){const o=e[t];o.firstCommit=o.firstCommit.toISOString(),o.lastCommit=o.lastCommit.toISOString()}return e}_calculateBusFactor(t,e){if(0===e||0===t.length)return{count:0,owners:[],thresholdPercent:50};let o=0;const r=[];for(const n of t)if(o+=n.commits,r.push(n.name),o/e>.5)break;return{count:r.length,owners:r,thresholdPercent:50}}_calculateCommitFrequency(t){const e=this.now,o=new Date(e.getTime()-7776e6),r=new Date(e.getTime()-2592e6),n=t.filter(t=>t.date>=o).length,i=t.filter(t=>t.date>=r).length;return{last90Days:n,perDay:+(n/90).toFixed(2),last30Days:i,perDay30:+(i/30).toFixed(2)}}_calculateAvgTimeBetweenCommits(t){if(t.length<2)return{avgHours:0,avgDays:0};const e=[...t].sort((t,e)=>t.date-e.date);let o=0;for(let t=1;t<e.length;t++)o+=e[t].date-e[t-1].date;const r=o/(e.length-1);return{avgHours:+(r/36e5).toFixed(1),avgDays:+(r/864e5).toFixed(2)}}_calculatePrMergeRate(t,e){const o=t.filter(t=>t.isMerge).length,r=e-o,n=e>0?+(o/e*100).toFixed(1):0;let i="local-branch-analysis";try{const t=this._run(["remote","-v"]);/github\.com|gitlab\.com/i.test(t)&&(i="local-branch-analysis (remote detected, API not queried)")}catch{}return{rate:n,mergeCommits:o,directCommits:r,source:i}}_attributeFocusAreas(t,e){const o=t=>"__proto__"===t||"constructor"===t||"prototype"===t,r=Object.create(null);for(const t of e)o(t.email)||(r[t.email]={});try{const t=this._run(["log","HEAD","--no-renames","--name-only","--pretty=format:%ae"]).split("").map(t=>t.trim()).filter(Boolean);for(const e of t){const t=e.split("\n"),o=r[(t[0]||"unknown@unknown").trim().toLowerCase()];if(o)for(let e=1;e<t.length;e++){const r=t[e].trim();if(!r)continue;const n=this._topLevelDir(r);o[n]=(o[n]||0)+1}}}catch{}const n=Object.create(null);for(const t of Object.keys(r)){if("__proto__"===t||"constructor"===t||"prototype"===t)continue;const e=r[t];n[t]=Object.entries(e).sort((t,e)=>e[1]-t[1]).slice(0,3).map(([t,e])=>({dir:t,count:e}))}return n}_topLevelDir(t){const e=t.split("/");return 1===e.length?"(root)":e[0]}_assessHealth({commitFrequency:t,busFactor:e,totalContributors:o,contributorList:r,totalCommits:n}){let i,s,a,c,l,m;t.perDay>=1?(i="Active",s="#00ff88",a=`Averaging ${t.perDay} commits/day over the last 90 days — healthy, sustained development.`):t.perDay>=.2?(i="Moderate",s="#ffd93d",a=`Averaging ${t.perDay} commits/day over the last 90 days — steady but unhurried pace.`):t.last90Days>0?(i="Declining",s="#ff8844",a=`Only ${t.last90Days} commits in the last 90 days — development has slowed significantly.`):(i="Stale",s="#ff4444",a="No commits in the last 90 days — repository appears inactive or abandoned."),e.count>=5?(c="Low Risk",l="#00ff88",m=`Ownership is spread across ${e.count} contributors — no single point of failure.`):e.count>=3?(c="Moderate Risk",l="#ffd93d",m=`Just ${e.count} contributors own over half of all commits — some key-person dependency.`):2===e.count?(c="High Risk",l="#ff8844",m=`Only 2 contributors (${e.owners.join(", ")}) own over half of all commits — losing either would materially disrupt development.`):(c="Critical Risk",l="#ff4444",m=`A single contributor (${e.owners[0]||"unknown"}) owns over half of all commits — losing this person would be an existential risk to continued development.`);const u=r.length>0&&n>0?+(r[0].commits/n*100).toFixed(1):0;let h,d,f;return u>=80?(h="Highly Concentrated",d="#ff4444",f=`${r[0]?.name||"Top contributor"} authored ${u}% of all commits — extreme concentration of code ownership.`):u>=50?(h="Concentrated",d="#ff8844",f=`${r[0]?.name||"Top contributor"} authored ${u}% of all commits — significant concentration of code ownership.`):u>=30?(h="Moderate",d="#ffd93d",f=`${r[0]?.name||"Top contributor"} authored ${u}% of all commits — reasonably distributed, though one contributor still leads.`):(h="Well Distributed",d="#00ff88",f="No single contributor exceeds 30% of commits — ownership is well distributed across the team."),{commitFrequency:{label:i,color:s,note:a},busFactorRisk:{label:c,color:l,note:m},ownershipConcentration:{label:h,color:d,note:f,topContributorSharePercent:u}}}}module.exports=GitVelocityAnalyzer;
|