thuban 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/packages/scanner/executive-report.js +1 -1
  2. package/dist/packages/scanner/hallucination-detector.js +1 -1
  3. package/dist/packages/scanner/secret-scanner.js +1 -1
  4. package/package.json +4 -3
  5. package/dist/packages/crucible/seeds/python/seed-021 3.py +0 -37
  6. package/dist/packages/crucible/seeds/python/seed-022 3.py +0 -34
  7. package/dist/packages/crucible/seeds/python/seed-023 3.py +0 -37
  8. package/dist/packages/crucible/seeds/python/seed-024 3.py +0 -38
  9. package/dist/packages/crucible/seeds/python/seed-025 3.py +0 -40
  10. package/dist/packages/crucible/seeds/python/seed-026 3.py +0 -35
  11. package/dist/packages/crucible/seeds/python/seed-027 3.py +0 -35
  12. package/dist/packages/crucible/seeds/python/seed-028 3.py +0 -42
  13. package/dist/packages/crucible/seeds/python/seed-030 3.py +0 -37
  14. package/dist/packages/crucible/seeds/python/seed-031 3.py +0 -34
  15. package/dist/packages/crucible/seeds/python/seed-036 3.py +0 -33
  16. package/dist/packages/crucible/seeds/python/seed-037 3.py +0 -41
  17. package/dist/packages/crucible/seeds/python/seed-038 3.py +0 -33
  18. package/dist/packages/crucible/seeds/python/seed-039 3.py +0 -39
  19. package/dist/packages/crucible/seeds/python/seed-040 3.py +0 -39
  20. package/dist/packages/crucible/seeds/python/seed-041 3.py +0 -37
  21. package/dist/packages/crucible/seeds/python/seed-042 3.py +0 -38
  22. package/dist/packages/crucible/seeds/python/seed-043 3.py +0 -32
  23. package/dist/packages/crucible/seeds/python/seed-044 3.py +0 -38
  24. package/dist/packages/crucible/seeds/python/seed-045 3.py +0 -36
  25. package/dist/packages/crucible/seeds/python/seed-046 3.py +0 -33
  26. package/dist/packages/crucible/seeds/python/seed-047 3.py +0 -44
  27. package/dist/packages/crucible/seeds/python/seed-048 3.py +0 -35
  28. package/dist/packages/crucible/seeds/python/seed-049 3.py +0 -39
  29. package/dist/packages/crucible/seeds/python/seed-050 3.py +0 -39
  30. package/dist/packages/crucible/seeds/python/seed-051 3.py +0 -38
  31. package/dist/packages/crucible/seeds/python/seed-052 3.py +0 -41
  32. package/dist/packages/crucible/seeds/ruby/seed-001 3.rb +0 -15
  33. package/dist/packages/crucible/seeds/ruby/seed-002 3.rb +0 -22
  34. package/dist/packages/crucible/seeds/ruby/seed-003 3.rb +0 -25
  35. package/dist/packages/crucible/seeds/ruby/seed-004 3.rb +0 -17
  36. package/dist/packages/crucible/seeds/ruby/seed-005 3.rb +0 -21
  37. package/dist/packages/crucible/seeds/ruby/seed-006 3.rb +0 -17
  38. package/dist/packages/crucible/seeds/ruby/seed-007 3.rb +0 -16
  39. package/dist/packages/crucible/seeds/ruby/seed-008 3.rb +0 -18
  40. package/dist/packages/crucible/seeds/ruby/seed-009 3.rb +0 -20
  41. package/dist/packages/crucible/seeds/ruby/seed-010 3.rb +0 -24
  42. package/dist/packages/crucible/seeds/ruby/seed-011 3.rb +0 -21
  43. package/dist/packages/crucible/seeds/ruby/seed-012 3.rb +0 -22
  44. package/dist/packages/crucible/seeds/ruby/seed-013 3.rb +0 -21
  45. package/dist/packages/crucible/seeds/ruby/seed-014 3.rb +0 -16
  46. package/dist/packages/crucible/seeds/ruby/seed-015 3.rb +0 -18
  47. package/dist/packages/crucible/seeds/ruby/seed-016 3.rb +0 -17
  48. package/dist/packages/crucible/seeds/ruby/seed-017 3.rb +0 -25
  49. package/dist/packages/crucible/seeds/ruby/seed-018 3.rb +0 -23
  50. package/dist/packages/crucible/seeds/ruby/seed-019 3.rb +0 -20
  51. package/dist/packages/crucible/seeds/ruby/seed-020 3.rb +0 -17
  52. package/dist/packages/crucible/seeds/ruby/seed-021 3.rb +0 -20
  53. package/dist/packages/crucible/seeds/ruby/seed-022 3.rb +0 -21
  54. package/dist/packages/crucible/seeds/ruby/seed-023 3.rb +0 -19
  55. package/dist/packages/crucible/seeds/ruby/seed-024 3.rb +0 -17
  56. package/dist/packages/crucible/seeds/ruby/seed-025 3.rb +0 -17
  57. package/dist/packages/crucible/seeds/ruby/seed-026 3.rb +0 -18
  58. package/dist/packages/crucible/seeds/ruby/seed-027 3.rb +0 -21
  59. package/dist/packages/crucible/seeds/ruby/seed-028 3.rb +0 -22
  60. package/dist/packages/crucible/seeds/ruby/seed-029 3.rb +0 -19
  61. package/dist/packages/crucible/seeds/ruby/seed-030 3.rb +0 -20
  62. package/dist/packages/crucible/seeds/ruby/seed-031 3.rb +0 -17
  63. package/dist/packages/crucible/seeds/ruby/seed-032 3.rb +0 -22
  64. package/dist/packages/crucible/seeds/ruby/seed-033 3.rb +0 -18
  65. package/dist/packages/crucible/seeds/ruby/seed-034 3.rb +0 -19
  66. package/dist/packages/crucible/seeds/ruby/seed-035 3.rb +0 -19
  67. package/dist/packages/crucible/seeds/ruby/seed-036 3.rb +0 -18
  68. package/dist/packages/crucible/seeds/ruby/seed-037 3.rb +0 -21
  69. package/dist/packages/crucible/seeds/ruby/seed-038 3.rb +0 -24
  70. package/dist/packages/crucible/seeds/ruby/seed-039 3.rb +0 -24
  71. package/dist/packages/crucible/seeds/ruby/seed-040 3.rb +0 -22
  72. package/dist/packages/crucible/seeds/ruby/seed-041 3.rb +0 -23
  73. package/dist/packages/crucible/seeds/ruby/seed-042 3.rb +0 -25
  74. package/dist/packages/crucible/seeds/ruby/seed-043 3.rb +0 -23
  75. package/dist/packages/crucible/seeds/ruby/seed-044 3.rb +0 -16
  76. package/dist/packages/crucible/seeds/ruby/seed-045 3.rb +0 -22
  77. package/dist/packages/crucible/seeds/ruby/seed-046 3.rb +0 -27
  78. package/dist/packages/crucible/seeds/ruby/seed-047 3.rb +0 -26
  79. package/dist/packages/crucible/seeds/ruby/seed-048 3.rb +0 -24
  80. package/dist/packages/crucible/seeds/ruby/seed-049 3.rb +0 -20
  81. package/dist/packages/crucible/seeds/ruby/seed-050 3.rb +0 -27
  82. package/dist/packages/crucible/seeds/rust/seed-001 3.rs +0 -25
  83. package/dist/packages/crucible/seeds/rust/seed-002 3.rs +0 -20
  84. package/dist/packages/crucible/seeds/rust/seed-003 3.rs +0 -23
  85. package/dist/packages/crucible/seeds/rust/seed-004 3.rs +0 -21
  86. package/dist/packages/crucible/seeds/rust/seed-005 3.rs +0 -21
  87. package/dist/packages/crucible/seeds/rust/seed-006 3.rs +0 -24
  88. package/dist/packages/crucible/seeds/rust/seed-007 3.rs +0 -20
  89. package/dist/packages/crucible/seeds/rust/seed-008 3.rs +0 -19
  90. package/dist/packages/crucible/seeds/rust/seed-009 3.rs +0 -28
  91. package/dist/packages/crucible/seeds/rust/seed-010 3.rs +0 -28
  92. package/dist/packages/crucible/seeds/rust/seed-011 3.rs +0 -25
  93. package/dist/packages/crucible/seeds/rust/seed-012 3.rs +0 -31
  94. package/dist/packages/crucible/seeds/rust/seed-013 3.rs +0 -27
  95. package/dist/packages/crucible/seeds/rust/seed-014 3.rs +0 -30
  96. package/dist/packages/crucible/seeds/rust/seed-015 3.rs +0 -33
  97. package/dist/packages/crucible/seeds/rust/seed-016 3.rs +0 -22
  98. package/dist/packages/crucible/seeds/rust/seed-017 3.rs +0 -28
  99. package/dist/packages/crucible/seeds/rust/seed-018 3.rs +0 -21
  100. package/dist/packages/crucible/seeds/rust/seed-019 3.rs +0 -36
  101. package/dist/packages/crucible/seeds/rust/seed-020 3.rs +0 -27
  102. package/dist/packages/crucible/seeds/rust/seed-021 3.rs +0 -26
  103. package/dist/packages/crucible/seeds/rust/seed-022 3.rs +0 -23
  104. package/dist/packages/crucible/seeds/rust/seed-023 3.rs +0 -22
  105. package/dist/packages/crucible/seeds/rust/seed-024 3.rs +0 -24
  106. package/dist/packages/crucible/seeds/rust/seed-025 3.rs +0 -29
  107. package/dist/packages/crucible/seeds/rust/seed-026 3.rs +0 -23
  108. package/dist/packages/crucible/seeds/rust/seed-027 3.rs +0 -24
  109. package/dist/packages/crucible/seeds/rust/seed-028 3.rs +0 -25
  110. package/dist/packages/crucible/seeds/rust/seed-029 3.rs +0 -25
  111. package/dist/packages/crucible/seeds/rust/seed-030 3.rs +0 -30
  112. package/dist/packages/crucible/seeds/rust/seed-031 3.rs +0 -22
  113. package/dist/packages/crucible/seeds/rust/seed-032 3.rs +0 -25
  114. package/dist/packages/crucible/seeds/rust/seed-033 3.rs +0 -25
  115. package/dist/packages/crucible/seeds/rust/seed-034 3.rs +0 -20
  116. package/dist/packages/crucible/seeds/rust/seed-035 3.rs +0 -28
  117. package/dist/packages/crucible/seeds/rust/seed-036 3.rs +0 -26
  118. package/dist/packages/crucible/seeds/rust/seed-037 3.rs +0 -31
  119. package/dist/packages/crucible/seeds/rust/seed-038 3.rs +0 -25
  120. package/dist/packages/crucible/seeds/rust/seed-039 3.rs +0 -28
  121. package/dist/packages/crucible/seeds/rust/seed-040 3.rs +0 -27
  122. package/dist/packages/crucible/seeds/rust/seed-041 3.rs +0 -32
  123. package/dist/packages/crucible/seeds/rust/seed-042 3.rs +0 -27
  124. package/dist/packages/crucible/seeds/rust/seed-043 3.rs +0 -29
  125. package/dist/packages/crucible/seeds/rust/seed-044 3.rs +0 -25
  126. package/dist/packages/crucible/seeds/rust/seed-045 3.rs +0 -28
  127. package/dist/packages/crucible/seeds/rust/seed-046 3.rs +0 -25
  128. package/dist/packages/crucible/seeds/rust/seed-047 3.rs +0 -34
  129. package/dist/packages/crucible/seeds/rust/seed-048 3.rs +0 -21
  130. package/dist/packages/crucible/seeds/rust/seed-049 3.rs +0 -26
  131. package/dist/packages/crucible/seeds/rust/seed-050 3.rs +0 -23
  132. package/dist/packages/crucible/seeds/ts/seed-001 3.ts +0 -32
  133. package/dist/packages/crucible/seeds/ts/seed-002 3.ts +0 -34
  134. package/dist/packages/crucible/seeds/ts/seed-003 3.ts +0 -28
  135. package/dist/packages/crucible/seeds/ts/seed-004 3.ts +0 -34
  136. package/dist/packages/crucible/seeds/ts/seed-005 3.ts +0 -32
  137. package/dist/packages/crucible/seeds/ts/seed-006 3.ts +0 -31
  138. package/dist/packages/crucible/seeds/ts/seed-007 3.ts +0 -28
  139. package/dist/packages/crucible/seeds/ts/seed-008 3.ts +0 -40
  140. package/dist/packages/crucible/seeds/ts/seed-009 3.ts +0 -31
  141. package/dist/packages/crucible/seeds/ts/seed-010 3.ts +0 -33
  142. package/dist/packages/crucible/seeds/ts/seed-011 3.ts +0 -29
  143. package/dist/packages/crucible/seeds/ts/seed-012 3.ts +0 -34
  144. package/dist/packages/crucible/seeds/ts/seed-013 3.ts +0 -31
  145. package/dist/packages/crucible/seeds/ts/seed-014 3.ts +0 -36
  146. package/dist/packages/crucible/seeds/ts/seed-015 3.ts +0 -31
  147. package/dist/packages/crucible/seeds/ts/seed-016 3.ts +0 -37
  148. package/dist/packages/crucible/seeds/ts/seed-017 3.ts +0 -44
  149. package/dist/packages/crucible/seeds/ts/seed-018 3.ts +0 -33
  150. package/dist/packages/crucible/seeds/ts/seed-019 3.ts +0 -32
  151. package/dist/packages/crucible/seeds/ts/seed-020 3.ts +0 -33
  152. package/dist/packages/crucible/seeds/ts/seed-021 3.ts +0 -33
  153. package/dist/packages/crucible/seeds/ts/seed-022 3.ts +0 -34
  154. package/dist/packages/crucible/seeds/ts/seed-023 3.ts +0 -33
  155. package/dist/packages/crucible/seeds/ts/seed-024 3.ts +0 -35
  156. package/dist/packages/crucible/seeds/ts/seed-025 3.ts +0 -29
  157. package/dist/packages/crucible/seeds/ts/seed-026 3.ts +0 -36
  158. package/dist/packages/crucible/seeds/ts/seed-027 3.ts +0 -30
  159. package/dist/packages/crucible/seeds/ts/seed-028 3.ts +0 -32
  160. package/dist/packages/crucible/seeds/ts/seed-029 3.ts +0 -34
  161. package/dist/packages/crucible/seeds/ts/seed-030 3.ts +0 -37
  162. package/dist/packages/crucible/seeds/ts/seed-031 3.ts +0 -31
  163. package/dist/packages/crucible/seeds/ts/seed-032 3.ts +0 -32
  164. package/dist/packages/crucible/seeds/ts/seed-033 3.ts +0 -32
  165. package/dist/packages/crucible/seeds/ts/seed-034 3.ts +0 -34
  166. package/dist/packages/crucible/seeds/ts/seed-035 3.ts +0 -29
  167. package/dist/packages/crucible/seeds/ts/seed-036 3.ts +0 -34
  168. package/dist/packages/crucible/seeds/ts/seed-037 3.ts +0 -33
  169. package/dist/packages/crucible/seeds/ts/seed-038 3.ts +0 -29
  170. package/dist/packages/crucible/seeds/ts/seed-039 3.ts +0 -35
  171. package/dist/packages/crucible/seeds/ts/seed-040 3.ts +0 -31
  172. package/dist/packages/crucible/seeds/ts/seed-041 3.ts +0 -29
  173. package/dist/packages/crucible/seeds/ts/seed-042 3.ts +0 -33
  174. package/dist/packages/crucible/seeds/ts/seed-043 3.ts +0 -32
  175. package/dist/packages/crucible/seeds/ts/seed-044 3.ts +0 -36
  176. package/dist/packages/crucible/seeds/ts/seed-045 3.ts +0 -39
  177. package/dist/packages/crucible/seeds/ts/seed-046 3.ts +0 -41
  178. package/dist/packages/crucible/seeds/ts/seed-047 3.ts +0 -33
  179. package/dist/packages/crucible/seeds/ts/seed-048 3.ts +0 -33
  180. package/dist/packages/crucible/seeds/ts/seed-049 3.ts +0 -34
  181. package/dist/packages/crucible/seeds/ts/seed-050 3.ts +0 -41
  182. package/dist/packages/crucible/seeds/ts/seed-051 3.ts +0 -34
  183. package/dist/packages/crucible/seeds/ts/seed-052 3.ts +0 -36
@@ -1,23 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: env_injection
3
- // severity: critical
4
- // language: rust
5
- // expected: User-controlled key used to read arbitrary env var — information disclosure
6
-
7
- use std::env;
8
- use axum::{extract::Query, response::IntoResponse};
9
- use std::collections::HashMap;
10
-
11
- pub async fn get_config(Query(params): Query<HashMap<String, String>>) -> impl IntoResponse {
12
- let key = params.get("key").cloned().unwrap_or_default();
13
- let value = env::var(&key).unwrap_or_else(|_| "not set".to_string());
14
- format!("{}={}", key, value)
15
- }
16
-
17
- pub fn lookup_env(user_key: &str) -> String {
18
- env::var(user_key).unwrap_or_default()
19
- }
20
-
21
- pub fn set_env_from_input(name: &str, value: &str) {
22
- unsafe { env::set_var(name, value) }
23
- }
@@ -1,32 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: critical
4
- // language: typescript
5
- // expected: hardcoded AWS credentials in typed config object
6
-
7
- import * as AWS from 'aws-sdk';
8
-
9
- interface AwsCredentials {
10
- accessKeyId: string;
11
- secretAccessKey: string;
12
- region: string;
13
- }
14
-
15
- const credentials: AwsCredentials = {
16
- accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
17
- secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
18
- region: 'us-east-1',
19
- };
20
-
21
- AWS.config.update(credentials);
22
-
23
- const s3 = new AWS.S3();
24
- const sqs = new AWS.SQS();
25
-
26
- export async function putObject(bucket: string, key: string, body: Buffer): Promise<void> {
27
- await s3.putObject({ Bucket: bucket, Key: key, Body: body }).promise();
28
- }
29
-
30
- export async function sendMessage(queueUrl: string, payload: object): Promise<void> {
31
- await sqs.sendMessage({ QueueUrl: queueUrl, MessageBody: JSON.stringify(payload) }).promise();
32
- }
@@ -1,34 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: critical
4
- // language: typescript
5
- // expected: hardcoded JWT secret in typed auth service
6
-
7
- import jwt, { SignOptions, JwtPayload } from 'jsonwebtoken';
8
-
9
- interface TokenPayload {
10
- userId: string;
11
- role: 'admin' | 'user' | 'moderator';
12
- email: string;
13
- }
14
-
15
- const JWT_SECRET: string = 'super-secret-jwt-signing-key-never-rotate-me-abc123!';
16
- const JWT_REFRESH_SECRET: string = 'refresh-token-secret-xyz-456-do-not-share';
17
-
18
- const signOptions: SignOptions = { expiresIn: '1h', algorithm: 'HS256' };
19
-
20
- export function signAccessToken(payload: TokenPayload): string {
21
- return jwt.sign(payload, JWT_SECRET, signOptions);
22
- }
23
-
24
- export function signRefreshToken(userId: string): string {
25
- return jwt.sign({ userId }, JWT_REFRESH_SECRET, { expiresIn: '30d' });
26
- }
27
-
28
- export function verifyAccessToken(token: string): JwtPayload {
29
- return jwt.verify(token, JWT_SECRET) as JwtPayload;
30
- }
31
-
32
- export function verifyRefreshToken(token: string): JwtPayload {
33
- return jwt.verify(token, JWT_REFRESH_SECRET) as JwtPayload;
34
- }
@@ -1,28 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: critical
4
- // language: typescript
5
- // expected: hardcoded database credentials in TypeORM DataSource config
6
-
7
- import { DataSource } from 'typeorm';
8
- import { User } from './entities/User';
9
- import { Order } from './entities/Order';
10
-
11
- export const AppDataSource = new DataSource({
12
- type: 'postgres',
13
- host: 'prod-postgres.internal',
14
- port: 5432,
15
- username: 'app_user',
16
- password: 'Pr0dPassw0rd!@#$',
17
- database: 'production_db',
18
- synchronize: false,
19
- logging: false,
20
- ssl: { rejectUnauthorized: false },
21
- entities: [User, Order],
22
- migrations: ['dist/migrations/*.js'],
23
- });
24
-
25
- export async function initializeDatabase(): Promise<void> {
26
- await AppDataSource.initialize();
27
- console.log('Database connection established');
28
- }
@@ -1,34 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: critical
4
- // language: typescript
5
- // expected: hardcoded Stripe secret key and webhook secret in typed service
6
-
7
- import Stripe from 'stripe';
8
-
9
- const STRIPE_SECRET_KEY = 'sk_live_51HqT3kLkjhGHJKL9mNoPqRstuvWxYz1234567890abcdef';
10
- const STRIPE_WEBHOOK_SECRET = 'whsec_abcdefghijklmnopqrstuvwxyz1234567890ABCDEF';
11
-
12
- const stripe = new Stripe(STRIPE_SECRET_KEY, { apiVersion: '2023-10-16' });
13
-
14
- export async function createPaymentIntent(
15
- amount: number,
16
- currency: string = 'usd',
17
- customerId?: string
18
- ): Promise<Stripe.PaymentIntent> {
19
- return stripe.paymentIntents.create({
20
- amount,
21
- currency,
22
- customer: customerId,
23
- automatic_payment_methods: { enabled: true },
24
- });
25
- }
26
-
27
- export function constructWebhookEvent(
28
- payload: Buffer,
29
- signature: string
30
- ): Stripe.Event {
31
- return stripe.webhooks.constructEvent(payload, signature, STRIPE_WEBHOOK_SECRET);
32
- }
33
-
34
- export { stripe };
@@ -1,32 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: high
4
- // language: typescript
5
- // expected: hardcoded SendGrid API key and SMTP credentials in typed mailer service
6
-
7
- import sgMail from '@sendgrid/mail';
8
- import nodemailer from 'nodemailer';
9
-
10
- const SENDGRID_KEY = 'SG.abcDEFghiJKLmnoPQRstUVwxYZ.1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd';
11
- sgMail.setApiKey(SENDGRID_KEY);
12
-
13
- interface EmailOptions {
14
- to: string;
15
- subject: string;
16
- text?: string;
17
- html?: string;
18
- }
19
-
20
- export async function sendTransactional(opts: EmailOptions): Promise<void> {
21
- await sgMail.send({ ...opts, from: 'noreply@myapp.com' });
22
- }
23
-
24
- const smtpTransport = nodemailer.createTransport({
25
- host: 'smtp.myapp.com',
26
- port: 587,
27
- auth: { user: 'mailer@myapp.com', pass: 'Smtp$Pass#2024!' },
28
- });
29
-
30
- export async function sendInternal(opts: EmailOptions): Promise<void> {
31
- await smtpTransport.sendMail({ ...opts, from: 'internal@myapp.com' });
32
- }
@@ -1,31 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: critical
4
- // language: typescript
5
- // expected: hardcoded GitHub token and Slack webhook URL in typed integration config
6
-
7
- import { Octokit } from '@octokit/rest';
8
- import axios from 'axios';
9
-
10
- interface IntegrationConfig {
11
- githubToken: string;
12
- slackWebhookUrl: string;
13
- slackSigningSecret: string;
14
- }
15
-
16
- const config: IntegrationConfig = {
17
- githubToken: 'ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890',
18
- slackWebhookUrl: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX',
19
- slackSigningSecret: 'abc123def456ghi789jkl012mno345pqr678stu',
20
- };
21
-
22
- const octokit = new Octokit({ auth: config.githubToken });
23
-
24
- export async function postToSlack(text: string): Promise<void> {
25
- await axios.post(config.slackWebhookUrl, { text });
26
- }
27
-
28
- export async function createIssue(owner: string, repo: string, title: string): Promise<number> {
29
- const { data } = await octokit.issues.create({ owner, repo, title });
30
- return data.number;
31
- }
@@ -1,28 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: high
4
- // language: typescript
5
- // expected: hardcoded encryption key and static IV in typed crypto utility
6
-
7
- import * as crypto from 'crypto';
8
-
9
- const ENCRYPTION_KEY: Buffer = Buffer.from('12345678901234567890123456789012', 'utf8'); // 32 bytes
10
- const STATIC_IV: Buffer = Buffer.from('abcdef1234567890', 'utf8'); // 16 bytes — never rotated
11
-
12
- export function encrypt(plaintext: string): string {
13
- const cipher = crypto.createCipheriv('aes-256-cbc', ENCRYPTION_KEY, STATIC_IV);
14
- let encrypted = cipher.update(plaintext, 'utf8', 'base64');
15
- encrypted += cipher.final('base64');
16
- return encrypted;
17
- }
18
-
19
- export function decrypt(ciphertext: string): string {
20
- const decipher = crypto.createDecipheriv('aes-256-cbc', ENCRYPTION_KEY, STATIC_IV);
21
- let decrypted = decipher.update(ciphertext, 'base64', 'utf8');
22
- decrypted += decipher.final('utf8');
23
- return decrypted;
24
- }
25
-
26
- export function hashToken(token: string): string {
27
- return crypto.createHash('md5').update(token + 'static-pepper').digest('hex');
28
- }
@@ -1,40 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: hardcoded_secret
3
- // severity: high
4
- // language: typescript
5
- // expected: hardcoded OAuth2 client credentials and admin API key in typed config
6
-
7
- import { Router, Request, Response } from 'express';
8
-
9
- interface OAuthConfig {
10
- clientId: string;
11
- clientSecret: string;
12
- redirectUri: string;
13
- }
14
-
15
- interface AdminConfig {
16
- apiKey: string;
17
- adminPassword: string;
18
- }
19
-
20
- const oauthConfig: OAuthConfig = {
21
- clientId: 'oauth2-client-production-id-abc123',
22
- clientSecret: 'oauth2-client-secret-XyZ9876543210abcdefGHIJKL',
23
- redirectUri: 'https://app.company.com/oauth/callback',
24
- };
25
-
26
- const adminConfig: AdminConfig = {
27
- apiKey: 'admin-api-key-supersecret-prod-2024',
28
- adminPassword: 'AdminP@ssw0rd!#$',
29
- };
30
-
31
- const router = Router();
32
-
33
- router.post('/oauth/token', (req: Request, res: Response) => {
34
- if (req.body.client_secret !== oauthConfig.clientSecret) {
35
- return res.status(401).json({ error: 'invalid_client' });
36
- }
37
- res.json({ access_token: 'generated', token_type: 'bearer' });
38
- });
39
-
40
- export default router;
@@ -1,31 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: critical
4
- // language: typescript
5
- // expected: SQL injection via TypeORM query() with string concatenation
6
-
7
- import { AppDataSource } from '../data-source';
8
-
9
- export async function findUserByUsername(username: string) {
10
- // Raw query with direct string interpolation — bypasses parameterization
11
- const result = await AppDataSource.query(
12
- `SELECT * FROM users WHERE username = '${username}'`
13
- );
14
- return result[0] ?? null;
15
- }
16
-
17
- export async function searchProducts(term: string, category: string) {
18
- const sql = `
19
- SELECT p.*, c.name as category_name
20
- FROM products p
21
- JOIN categories c ON p.category_id = c.id
22
- WHERE p.name ILIKE '%` + term + `%'
23
- AND c.slug = '` + category + `'
24
- ORDER BY p.created_at DESC
25
- `;
26
- return AppDataSource.query(sql);
27
- }
28
-
29
- export async function deleteUserSessions(userId: string) {
30
- await AppDataSource.query('DELETE FROM sessions WHERE user_id = ' + userId);
31
- }
@@ -1,33 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: critical
4
- // language: typescript
5
- // expected: SQL injection in TypeORM repository createQueryBuilder with raw where clause
6
-
7
- import { Repository } from 'typeorm';
8
- import { User } from '../entities/User';
9
-
10
- export class UserRepository {
11
- constructor(private repo: Repository<User>) {}
12
-
13
- async findByEmail(email: string): Promise<User | null> {
14
- return this.repo
15
- .createQueryBuilder('user')
16
- // Direct interpolation into where() — SQL injection
17
- .where(`user.email = '${email}'`)
18
- .getOne();
19
- }
20
-
21
- async searchByName(query: string, role: string): Promise<User[]> {
22
- return this.repo
23
- .createQueryBuilder('user')
24
- .where(`user.name ILIKE '%${query}%' AND user.role = '${role}'`)
25
- .orderBy('user.createdAt', 'DESC')
26
- .getMany();
27
- }
28
-
29
- async getByIds(ids: string[]): Promise<User[]> {
30
- const idList = ids.join(', ');
31
- return this.repo.query(`SELECT * FROM users WHERE id IN (${idList})`);
32
- }
33
- }
@@ -1,29 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: critical
4
- // language: typescript
5
- // expected: SQL injection in Prisma $queryRaw with tagged template bypassed via string concat
6
-
7
- import { PrismaClient } from '@prisma/client';
8
-
9
- const prisma = new PrismaClient();
10
-
11
- export async function getUserOrders(userId: string, status: string) {
12
- // $queryRawUnsafe does NOT parameterize — direct string concatenation
13
- const orders = await prisma.$queryRawUnsafe(
14
- `SELECT * FROM orders WHERE user_id = '${userId}' AND status = '${status}'`
15
- );
16
- return orders;
17
- }
18
-
19
- export async function searchInventory(searchTerm: string, warehouseId: string) {
20
- const query = `
21
- SELECT i.*, w.name as warehouse
22
- FROM inventory i
23
- JOIN warehouses w ON i.warehouse_id = w.id
24
- WHERE i.sku ILIKE '%` + searchTerm + `%'
25
- OR i.description ILIKE '%` + searchTerm + `%'
26
- AND w.id = '` + warehouseId + `'
27
- `;
28
- return prisma.$queryRawUnsafe(query);
29
- }
@@ -1,34 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: critical
4
- // language: typescript
5
- // expected: SQL injection in NestJS service using raw pg query with string interpolation
6
-
7
- import { Injectable } from '@nestjs/common';
8
- import { InjectConnection } from '@nestjs/typeorm';
9
- import { Connection } from 'typeorm';
10
-
11
- @Injectable()
12
- export class ReportService {
13
- constructor(@InjectConnection() private connection: Connection) {}
14
-
15
- async getRevenueReport(fromDate: string, toDate: string, groupBy: string): Promise<any[]> {
16
- const sql = `
17
- SELECT
18
- ${groupBy} as period,
19
- SUM(amount) as total_revenue,
20
- COUNT(*) as transaction_count
21
- FROM transactions
22
- WHERE created_at BETWEEN '${fromDate}' AND '${toDate}'
23
- GROUP BY ${groupBy}
24
- ORDER BY period ASC
25
- `;
26
- return this.connection.query(sql);
27
- }
28
-
29
- async getUserActivity(userId: string, action: string): Promise<any[]> {
30
- return this.connection.query(
31
- `SELECT * FROM audit_log WHERE user_id = '` + userId + `' AND action = '` + action + `'`
32
- );
33
- }
34
- }
@@ -1,31 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: high
4
- // language: typescript
5
- // expected: SQL injection via dynamic ORDER BY column name from user input
6
-
7
- import { Pool } from 'pg';
8
-
9
- const pool = new Pool({ connectionString: process.env.DATABASE_URL });
10
-
11
- interface ListOptions {
12
- sortField: string; // user-controlled
13
- sortDir: 'asc' | 'desc'; // type claim but not validated
14
- limit: number;
15
- offset: number;
16
- filter?: string;
17
- }
18
-
19
- export async function listProducts(opts: ListOptions) {
20
- // sortField and sortDir inserted verbatim — type annotations don't prevent injection
21
- const query = `
22
- SELECT id, name, price, stock, created_at
23
- FROM products
24
- WHERE archived = false
25
- ${opts.filter ? `AND name ILIKE '%${opts.filter}%'` : ''}
26
- ORDER BY ${opts.sortField} ${opts.sortDir}
27
- LIMIT ${opts.limit} OFFSET ${opts.offset}
28
- `;
29
- const { rows } = await pool.query(query);
30
- return rows;
31
- }
@@ -1,36 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: critical
4
- // language: typescript
5
- // expected: SQL injection in authentication middleware via raw query with login credentials
6
-
7
- import { Request, Response, NextFunction } from 'express';
8
- import { Pool } from 'pg';
9
-
10
- const pool = new Pool({ connectionString: process.env.DATABASE_URL });
11
-
12
- export async function authenticateMiddleware(
13
- req: Request,
14
- res: Response,
15
- next: NextFunction
16
- ): Promise<void> {
17
- const { username, password } = req.body as { username: string; password: string };
18
-
19
- // Classic auth bypass: username = "admin'--"
20
- const query = `
21
- SELECT id, username, role, email
22
- FROM users
23
- WHERE username = '${username}'
24
- AND password_hash = crypt('${password}', password_hash)
25
- AND active = true
26
- `;
27
-
28
- const { rows } = await pool.query(query);
29
- if (!rows.length) {
30
- res.status(401).json({ error: 'Invalid credentials' });
31
- return;
32
- }
33
-
34
- req.user = rows[0];
35
- next();
36
- }
@@ -1,31 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: sql_injection
3
- // severity: high
4
- // language: typescript
5
- // expected: SQL injection via Sequelize literal() with user-controlled search input
6
-
7
- import { Sequelize, QueryTypes } from 'sequelize';
8
-
9
- const sequelize = new Sequelize(process.env.DATABASE_URL!);
10
-
11
- export async function fullTextSearch(
12
- query: string,
13
- table: 'products' | 'articles' | 'users',
14
- fields: string[]
15
- ): Promise<Record<string, unknown>[]> {
16
- const fieldList = fields.join(', ');
17
- const whereClause = fields
18
- .map(f => `${f} ILIKE '%${query}%'`)
19
- .join(' OR ');
20
-
21
- // Both fieldList and whereClause derived from user input — injection possible
22
- const sql = `SELECT ${fieldList} FROM "${table}" WHERE ${whereClause} LIMIT 50`;
23
- return sequelize.query(sql, { type: QueryTypes.SELECT });
24
- }
25
-
26
- export async function bulkUpdate(ids: number[], status: string): Promise<void> {
27
- const idList = ids.join(',');
28
- await sequelize.query(
29
- `UPDATE orders SET status = '${status}' WHERE id IN (${idList})`
30
- );
31
- }
@@ -1,37 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: xss
3
- // severity: high
4
- // language: typescript
5
- // expected: XSS via React dangerouslySetInnerHTML with user-controlled content
6
-
7
- import React from 'react';
8
-
9
- interface Comment {
10
- id: string;
11
- author: string;
12
- body: string;
13
- avatarHtml: string;
14
- }
15
-
16
- interface CommentCardProps {
17
- comment: Comment;
18
- }
19
-
20
- export const CommentCard: React.FC<CommentCardProps> = ({ comment }) => {
21
- return (
22
- <div className="comment-card">
23
- {/* avatarHtml and body come from server/user — XSS if unsanitized */}
24
- <div className="avatar" dangerouslySetInnerHTML={{ __html: comment.avatarHtml }} />
25
- <div className="author">{comment.author}</div>
26
- <div className="body" dangerouslySetInnerHTML={{ __html: comment.body }} />
27
- </div>
28
- );
29
- };
30
-
31
- interface RichTextProps {
32
- content: string; // user-submitted rich text
33
- }
34
-
35
- export const RichTextRenderer: React.FC<RichTextProps> = ({ content }) => (
36
- <article dangerouslySetInnerHTML={{ __html: content }} />
37
- );
@@ -1,44 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: xss
3
- // severity: high
4
- // language: typescript
5
- // expected: XSS via Angular [innerHTML] binding with user-controlled data
6
-
7
- import { Component, OnInit } from '@angular/core';
8
- import { ActivatedRoute } from '@angular/router';
9
- import { UserService } from '../services/user.service';
10
-
11
- interface UserProfile {
12
- displayName: string;
13
- bio: string; // Rich HTML from user
14
- signature: string; // HTML signature from user
15
- }
16
-
17
- @Component({
18
- selector: 'app-user-profile',
19
- template: `
20
- <div class="profile">
21
- <h1>{{ user?.displayName }}</h1>
22
- <!-- [innerHTML] bypasses Angular's sanitization when DomSanitizer.bypassSecurityTrustHtml is used -->
23
- <div class="bio" [innerHTML]="trustedBio"></div>
24
- <footer [innerHTML]="trustedSignature"></footer>
25
- </div>
26
- `,
27
- })
28
- export class UserProfileComponent implements OnInit {
29
- user: UserProfile | null = null;
30
- trustedBio: any;
31
- trustedSignature: any;
32
-
33
- constructor(private route: ActivatedRoute, private userService: UserService) {}
34
-
35
- ngOnInit(): void {
36
- const id = this.route.snapshot.paramMap.get('id')!;
37
- this.userService.getProfile(id).subscribe(user => {
38
- this.user = user;
39
- // Bypasses Angular's built-in XSS protection
40
- this.trustedBio = user.bio;
41
- this.trustedSignature = user.signature;
42
- });
43
- }
44
- }
@@ -1,33 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: xss
3
- // severity: high
4
- // language: typescript
5
- // expected: XSS via innerHTML in typed DOM manipulation utility
6
-
7
- export class DomRenderer {
8
- private container: HTMLElement;
9
-
10
- constructor(containerId: string) {
11
- this.container = document.getElementById(containerId) as HTMLElement;
12
- }
13
-
14
- renderUserContent(content: string): void {
15
- // Direct innerHTML assignment — content from user input
16
- this.container.innerHTML = content;
17
- }
18
-
19
- appendItem(title: string, description: string): void {
20
- // Template literal with user data written to innerHTML
21
- this.container.innerHTML += `
22
- <div class="item">
23
- <h3>${title}</h3>
24
- <p>${description}</p>
25
- </div>
26
- `;
27
- }
28
-
29
- showBanner(message: string, type: 'info' | 'warning' | 'error'): void {
30
- const banner = document.querySelector('.banner') as HTMLElement;
31
- banner.innerHTML = `<div class="alert alert-${type}">${message}</div>`;
32
- }
33
- }
@@ -1,32 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: xss
3
- // severity: high
4
- // language: typescript
5
- // expected: XSS via Express response with unsanitized template literal containing user input
6
-
7
- import { Request, Response, Router } from 'express';
8
-
9
- const router = Router();
10
-
11
- router.get('/search', (req: Request, res: Response) => {
12
- const query = (req.query.q as string) || '';
13
- const category = (req.query.cat as string) || 'all';
14
-
15
- // Both query and category embedded directly in HTML without encoding
16
- res.send(`
17
- <!DOCTYPE html>
18
- <html lang="en">
19
- <head><title>Search - ${category}</title></head>
20
- <body>
21
- <h1>Results for: <em>${query}</em></h1>
22
- <p>Category: ${category}</p>
23
- <script>
24
- const searchQuery = "${query}";
25
- const searchCategory = "${category}";
26
- </script>
27
- </body>
28
- </html>
29
- `);
30
- });
31
-
32
- export default router;