thuban 0.4.11 → 0.4.13

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 (184) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/package.json +1 -1
  3. package/dist/packages/crucible/rules/code-scanner-core.json +11 -0
  4. package/dist/packages/scanner/ghost-code-detector.js +1 -1
  5. package/package.json +1 -1
  6. package/dist/packages/crucible/seeds/python/seed-021 2.py +0 -37
  7. package/dist/packages/crucible/seeds/python/seed-022 2.py +0 -34
  8. package/dist/packages/crucible/seeds/python/seed-023 2.py +0 -37
  9. package/dist/packages/crucible/seeds/python/seed-024 2.py +0 -38
  10. package/dist/packages/crucible/seeds/python/seed-025 2.py +0 -40
  11. package/dist/packages/crucible/seeds/python/seed-026 2.py +0 -35
  12. package/dist/packages/crucible/seeds/python/seed-027 2.py +0 -35
  13. package/dist/packages/crucible/seeds/python/seed-028 2.py +0 -42
  14. package/dist/packages/crucible/seeds/python/seed-030 2.py +0 -37
  15. package/dist/packages/crucible/seeds/python/seed-031 2.py +0 -34
  16. package/dist/packages/crucible/seeds/python/seed-036 2.py +0 -33
  17. package/dist/packages/crucible/seeds/python/seed-037 2.py +0 -41
  18. package/dist/packages/crucible/seeds/python/seed-038 2.py +0 -33
  19. package/dist/packages/crucible/seeds/python/seed-039 2.py +0 -39
  20. package/dist/packages/crucible/seeds/python/seed-040 2.py +0 -39
  21. package/dist/packages/crucible/seeds/python/seed-041 2.py +0 -37
  22. package/dist/packages/crucible/seeds/python/seed-042 2.py +0 -38
  23. package/dist/packages/crucible/seeds/python/seed-043 2.py +0 -32
  24. package/dist/packages/crucible/seeds/python/seed-044 2.py +0 -38
  25. package/dist/packages/crucible/seeds/python/seed-045 2.py +0 -36
  26. package/dist/packages/crucible/seeds/python/seed-046 2.py +0 -33
  27. package/dist/packages/crucible/seeds/python/seed-047 2.py +0 -44
  28. package/dist/packages/crucible/seeds/python/seed-048 2.py +0 -35
  29. package/dist/packages/crucible/seeds/python/seed-049 2.py +0 -39
  30. package/dist/packages/crucible/seeds/python/seed-050 2.py +0 -39
  31. package/dist/packages/crucible/seeds/python/seed-051 2.py +0 -38
  32. package/dist/packages/crucible/seeds/python/seed-052 2.py +0 -41
  33. package/dist/packages/crucible/seeds/ruby/seed-001 2.rb +0 -15
  34. package/dist/packages/crucible/seeds/ruby/seed-002 2.rb +0 -22
  35. package/dist/packages/crucible/seeds/ruby/seed-003 2.rb +0 -25
  36. package/dist/packages/crucible/seeds/ruby/seed-004 2.rb +0 -17
  37. package/dist/packages/crucible/seeds/ruby/seed-005 2.rb +0 -21
  38. package/dist/packages/crucible/seeds/ruby/seed-006 2.rb +0 -17
  39. package/dist/packages/crucible/seeds/ruby/seed-007 2.rb +0 -16
  40. package/dist/packages/crucible/seeds/ruby/seed-008 2.rb +0 -18
  41. package/dist/packages/crucible/seeds/ruby/seed-009 2.rb +0 -20
  42. package/dist/packages/crucible/seeds/ruby/seed-010 2.rb +0 -24
  43. package/dist/packages/crucible/seeds/ruby/seed-011 2.rb +0 -21
  44. package/dist/packages/crucible/seeds/ruby/seed-012 2.rb +0 -22
  45. package/dist/packages/crucible/seeds/ruby/seed-013 2.rb +0 -21
  46. package/dist/packages/crucible/seeds/ruby/seed-014 2.rb +0 -16
  47. package/dist/packages/crucible/seeds/ruby/seed-015 2.rb +0 -18
  48. package/dist/packages/crucible/seeds/ruby/seed-016 2.rb +0 -17
  49. package/dist/packages/crucible/seeds/ruby/seed-017 2.rb +0 -25
  50. package/dist/packages/crucible/seeds/ruby/seed-018 2.rb +0 -23
  51. package/dist/packages/crucible/seeds/ruby/seed-019 2.rb +0 -20
  52. package/dist/packages/crucible/seeds/ruby/seed-020 2.rb +0 -17
  53. package/dist/packages/crucible/seeds/ruby/seed-021 2.rb +0 -20
  54. package/dist/packages/crucible/seeds/ruby/seed-022 2.rb +0 -21
  55. package/dist/packages/crucible/seeds/ruby/seed-023 2.rb +0 -19
  56. package/dist/packages/crucible/seeds/ruby/seed-024 2.rb +0 -17
  57. package/dist/packages/crucible/seeds/ruby/seed-025 2.rb +0 -17
  58. package/dist/packages/crucible/seeds/ruby/seed-026 2.rb +0 -18
  59. package/dist/packages/crucible/seeds/ruby/seed-027 2.rb +0 -21
  60. package/dist/packages/crucible/seeds/ruby/seed-028 2.rb +0 -22
  61. package/dist/packages/crucible/seeds/ruby/seed-029 2.rb +0 -19
  62. package/dist/packages/crucible/seeds/ruby/seed-030 2.rb +0 -20
  63. package/dist/packages/crucible/seeds/ruby/seed-031 2.rb +0 -17
  64. package/dist/packages/crucible/seeds/ruby/seed-032 2.rb +0 -22
  65. package/dist/packages/crucible/seeds/ruby/seed-033 2.rb +0 -18
  66. package/dist/packages/crucible/seeds/ruby/seed-034 2.rb +0 -19
  67. package/dist/packages/crucible/seeds/ruby/seed-035 2.rb +0 -19
  68. package/dist/packages/crucible/seeds/ruby/seed-036 2.rb +0 -18
  69. package/dist/packages/crucible/seeds/ruby/seed-037 2.rb +0 -21
  70. package/dist/packages/crucible/seeds/ruby/seed-038 2.rb +0 -24
  71. package/dist/packages/crucible/seeds/ruby/seed-039 2.rb +0 -24
  72. package/dist/packages/crucible/seeds/ruby/seed-040 2.rb +0 -22
  73. package/dist/packages/crucible/seeds/ruby/seed-041 2.rb +0 -23
  74. package/dist/packages/crucible/seeds/ruby/seed-042 2.rb +0 -25
  75. package/dist/packages/crucible/seeds/ruby/seed-043 2.rb +0 -23
  76. package/dist/packages/crucible/seeds/ruby/seed-044 2.rb +0 -16
  77. package/dist/packages/crucible/seeds/ruby/seed-045 2.rb +0 -22
  78. package/dist/packages/crucible/seeds/ruby/seed-046 2.rb +0 -27
  79. package/dist/packages/crucible/seeds/ruby/seed-047 2.rb +0 -26
  80. package/dist/packages/crucible/seeds/ruby/seed-048 2.rb +0 -24
  81. package/dist/packages/crucible/seeds/ruby/seed-049 2.rb +0 -20
  82. package/dist/packages/crucible/seeds/ruby/seed-050 2.rb +0 -27
  83. package/dist/packages/crucible/seeds/rust/seed-001 2.rs +0 -25
  84. package/dist/packages/crucible/seeds/rust/seed-002 2.rs +0 -20
  85. package/dist/packages/crucible/seeds/rust/seed-003 2.rs +0 -23
  86. package/dist/packages/crucible/seeds/rust/seed-004 2.rs +0 -21
  87. package/dist/packages/crucible/seeds/rust/seed-005 2.rs +0 -21
  88. package/dist/packages/crucible/seeds/rust/seed-006 2.rs +0 -24
  89. package/dist/packages/crucible/seeds/rust/seed-007 2.rs +0 -20
  90. package/dist/packages/crucible/seeds/rust/seed-008 2.rs +0 -19
  91. package/dist/packages/crucible/seeds/rust/seed-009 2.rs +0 -28
  92. package/dist/packages/crucible/seeds/rust/seed-010 2.rs +0 -28
  93. package/dist/packages/crucible/seeds/rust/seed-011 2.rs +0 -25
  94. package/dist/packages/crucible/seeds/rust/seed-012 2.rs +0 -31
  95. package/dist/packages/crucible/seeds/rust/seed-013 2.rs +0 -27
  96. package/dist/packages/crucible/seeds/rust/seed-014 2.rs +0 -30
  97. package/dist/packages/crucible/seeds/rust/seed-015 2.rs +0 -33
  98. package/dist/packages/crucible/seeds/rust/seed-016 2.rs +0 -22
  99. package/dist/packages/crucible/seeds/rust/seed-017 2.rs +0 -28
  100. package/dist/packages/crucible/seeds/rust/seed-018 2.rs +0 -21
  101. package/dist/packages/crucible/seeds/rust/seed-019 2.rs +0 -36
  102. package/dist/packages/crucible/seeds/rust/seed-020 2.rs +0 -27
  103. package/dist/packages/crucible/seeds/rust/seed-021 2.rs +0 -26
  104. package/dist/packages/crucible/seeds/rust/seed-022 2.rs +0 -23
  105. package/dist/packages/crucible/seeds/rust/seed-023 2.rs +0 -22
  106. package/dist/packages/crucible/seeds/rust/seed-024 2.rs +0 -24
  107. package/dist/packages/crucible/seeds/rust/seed-025 2.rs +0 -29
  108. package/dist/packages/crucible/seeds/rust/seed-026 2.rs +0 -23
  109. package/dist/packages/crucible/seeds/rust/seed-027 2.rs +0 -24
  110. package/dist/packages/crucible/seeds/rust/seed-028 2.rs +0 -25
  111. package/dist/packages/crucible/seeds/rust/seed-029 2.rs +0 -25
  112. package/dist/packages/crucible/seeds/rust/seed-030 2.rs +0 -30
  113. package/dist/packages/crucible/seeds/rust/seed-031 2.rs +0 -22
  114. package/dist/packages/crucible/seeds/rust/seed-032 2.rs +0 -25
  115. package/dist/packages/crucible/seeds/rust/seed-033 2.rs +0 -25
  116. package/dist/packages/crucible/seeds/rust/seed-034 2.rs +0 -20
  117. package/dist/packages/crucible/seeds/rust/seed-035 2.rs +0 -28
  118. package/dist/packages/crucible/seeds/rust/seed-036 2.rs +0 -26
  119. package/dist/packages/crucible/seeds/rust/seed-037 2.rs +0 -31
  120. package/dist/packages/crucible/seeds/rust/seed-038 2.rs +0 -25
  121. package/dist/packages/crucible/seeds/rust/seed-039 2.rs +0 -28
  122. package/dist/packages/crucible/seeds/rust/seed-040 2.rs +0 -27
  123. package/dist/packages/crucible/seeds/rust/seed-041 2.rs +0 -32
  124. package/dist/packages/crucible/seeds/rust/seed-042 2.rs +0 -27
  125. package/dist/packages/crucible/seeds/rust/seed-043 2.rs +0 -29
  126. package/dist/packages/crucible/seeds/rust/seed-044 2.rs +0 -25
  127. package/dist/packages/crucible/seeds/rust/seed-045 2.rs +0 -28
  128. package/dist/packages/crucible/seeds/rust/seed-046 2.rs +0 -25
  129. package/dist/packages/crucible/seeds/rust/seed-047 2.rs +0 -34
  130. package/dist/packages/crucible/seeds/rust/seed-048 2.rs +0 -21
  131. package/dist/packages/crucible/seeds/rust/seed-049 2.rs +0 -26
  132. package/dist/packages/crucible/seeds/rust/seed-050 2.rs +0 -23
  133. package/dist/packages/crucible/seeds/ts/seed-001 2.ts +0 -32
  134. package/dist/packages/crucible/seeds/ts/seed-002 2.ts +0 -34
  135. package/dist/packages/crucible/seeds/ts/seed-003 2.ts +0 -28
  136. package/dist/packages/crucible/seeds/ts/seed-004 2.ts +0 -34
  137. package/dist/packages/crucible/seeds/ts/seed-005 2.ts +0 -32
  138. package/dist/packages/crucible/seeds/ts/seed-006 2.ts +0 -31
  139. package/dist/packages/crucible/seeds/ts/seed-007 2.ts +0 -28
  140. package/dist/packages/crucible/seeds/ts/seed-008 2.ts +0 -40
  141. package/dist/packages/crucible/seeds/ts/seed-009 2.ts +0 -31
  142. package/dist/packages/crucible/seeds/ts/seed-010 2.ts +0 -33
  143. package/dist/packages/crucible/seeds/ts/seed-011 2.ts +0 -29
  144. package/dist/packages/crucible/seeds/ts/seed-012 2.ts +0 -34
  145. package/dist/packages/crucible/seeds/ts/seed-013 2.ts +0 -31
  146. package/dist/packages/crucible/seeds/ts/seed-014 2.ts +0 -36
  147. package/dist/packages/crucible/seeds/ts/seed-015 2.ts +0 -31
  148. package/dist/packages/crucible/seeds/ts/seed-016 2.ts +0 -37
  149. package/dist/packages/crucible/seeds/ts/seed-017 2.ts +0 -44
  150. package/dist/packages/crucible/seeds/ts/seed-018 2.ts +0 -33
  151. package/dist/packages/crucible/seeds/ts/seed-019 2.ts +0 -32
  152. package/dist/packages/crucible/seeds/ts/seed-020 2.ts +0 -33
  153. package/dist/packages/crucible/seeds/ts/seed-021 2.ts +0 -33
  154. package/dist/packages/crucible/seeds/ts/seed-022 2.ts +0 -34
  155. package/dist/packages/crucible/seeds/ts/seed-023 2.ts +0 -33
  156. package/dist/packages/crucible/seeds/ts/seed-024 2.ts +0 -35
  157. package/dist/packages/crucible/seeds/ts/seed-025 2.ts +0 -29
  158. package/dist/packages/crucible/seeds/ts/seed-026 2.ts +0 -36
  159. package/dist/packages/crucible/seeds/ts/seed-027 2.ts +0 -30
  160. package/dist/packages/crucible/seeds/ts/seed-028 2.ts +0 -32
  161. package/dist/packages/crucible/seeds/ts/seed-029 2.ts +0 -34
  162. package/dist/packages/crucible/seeds/ts/seed-030 2.ts +0 -37
  163. package/dist/packages/crucible/seeds/ts/seed-031 2.ts +0 -31
  164. package/dist/packages/crucible/seeds/ts/seed-032 2.ts +0 -32
  165. package/dist/packages/crucible/seeds/ts/seed-033 2.ts +0 -32
  166. package/dist/packages/crucible/seeds/ts/seed-034 2.ts +0 -34
  167. package/dist/packages/crucible/seeds/ts/seed-035 2.ts +0 -29
  168. package/dist/packages/crucible/seeds/ts/seed-036 2.ts +0 -34
  169. package/dist/packages/crucible/seeds/ts/seed-037 2.ts +0 -33
  170. package/dist/packages/crucible/seeds/ts/seed-038 2.ts +0 -29
  171. package/dist/packages/crucible/seeds/ts/seed-039 2.ts +0 -35
  172. package/dist/packages/crucible/seeds/ts/seed-040 2.ts +0 -31
  173. package/dist/packages/crucible/seeds/ts/seed-041 2.ts +0 -29
  174. package/dist/packages/crucible/seeds/ts/seed-042 2.ts +0 -33
  175. package/dist/packages/crucible/seeds/ts/seed-043 2.ts +0 -32
  176. package/dist/packages/crucible/seeds/ts/seed-044 2.ts +0 -36
  177. package/dist/packages/crucible/seeds/ts/seed-045 2.ts +0 -39
  178. package/dist/packages/crucible/seeds/ts/seed-046 2.ts +0 -41
  179. package/dist/packages/crucible/seeds/ts/seed-047 2.ts +0 -33
  180. package/dist/packages/crucible/seeds/ts/seed-048 2.ts +0 -33
  181. package/dist/packages/crucible/seeds/ts/seed-049 2.ts +0 -34
  182. package/dist/packages/crucible/seeds/ts/seed-050 2.ts +0 -41
  183. package/dist/packages/crucible/seeds/ts/seed-051 2.ts +0 -34
  184. package/dist/packages/crucible/seeds/ts/seed-052 2.ts +0 -36
@@ -1,32 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: race_condition
3
- // severity: critical
4
- // language: rust
5
- // expected: Unsafe impl Send for type containing raw pointer — data race
6
-
7
- use std::ptr;
8
-
9
- pub struct RawBuffer {
10
- ptr: *mut u8,
11
- len: usize,
12
- }
13
-
14
- unsafe impl Send for RawBuffer {}
15
- unsafe impl Sync for RawBuffer {}
16
-
17
- impl RawBuffer {
18
- pub fn new(size: usize) -> Self {
19
- let mut data = vec![0u8; size];
20
- let ptr = data.as_mut_ptr();
21
- std::mem::forget(data);
22
- RawBuffer { ptr, len: size }
23
- }
24
-
25
- pub fn write_at(&self, offset: usize, value: u8) {
26
- unsafe { ptr::write(self.ptr.add(offset), value) }
27
- }
28
-
29
- pub fn read_at(&self, offset: usize) -> u8 {
30
- unsafe { ptr::read(self.ptr.add(offset)) }
31
- }
32
- }
@@ -1,27 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: race_condition
3
- // severity: high
4
- // language: rust
5
- // expected: Multiple threads access static mut without synchronization
6
-
7
- static mut GLOBAL_COUNTER: u64 = 0;
8
- static mut INITIALIZED: bool = false;
9
-
10
- pub fn increment_global() {
11
- unsafe {
12
- GLOBAL_COUNTER += 1;
13
- }
14
- }
15
-
16
- pub fn get_global() -> u64 {
17
- unsafe { GLOBAL_COUNTER }
18
- }
19
-
20
- pub fn initialize_once(value: u64) {
21
- unsafe {
22
- if !INITIALIZED {
23
- GLOBAL_COUNTER = value;
24
- INITIALIZED = true;
25
- }
26
- }
27
- }
@@ -1,29 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: race_condition
3
- // severity: high
4
- // language: rust
5
- // expected: Mutex poisoning ignored with unwrap — may expose partial state
6
-
7
- use std::sync::{Arc, Mutex};
8
- use std::thread;
9
-
10
- pub fn parallel_updates(shared: Arc<Mutex<Vec<i32>>>, items: Vec<i32>) {
11
- let handles: Vec<_> = items.into_iter().map(|item| {
12
- let shared = Arc::clone(&shared);
13
- thread::spawn(move || {
14
- let mut guard = shared.lock().unwrap();
15
- guard.push(item);
16
- if item == 42 {
17
- panic!("Special case panic — poisons the Mutex");
18
- }
19
- })
20
- }).collect();
21
-
22
- for h in handles {
23
- let _ = h.join();
24
- }
25
- }
26
-
27
- pub fn read_poisoned(shared: Arc<Mutex<Vec<i32>>>) -> Vec<i32> {
28
- shared.lock().unwrap().clone()
29
- }
@@ -1,25 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: crypto_misuse
3
- // severity: high
4
- // language: rust
5
- // expected: MD5 crate used for password or data integrity hashing
6
-
7
- use md5;
8
-
9
- pub fn hash_password(password: &str) -> String {
10
- let digest = md5::compute(password.as_bytes());
11
- format!("{:x}", digest)
12
- }
13
-
14
- pub fn hash_with_salt(password: &str, username: &str) -> String {
15
- let input = format!("{}:{}", username, password);
16
- format!("{:x}", md5::compute(input.as_bytes()))
17
- }
18
-
19
- pub fn verify_password(password: &str, stored_hash: &str) -> bool {
20
- hash_password(password) == stored_hash
21
- }
22
-
23
- pub fn generate_cache_key(data: &str) -> String {
24
- format!("{:x}", md5::compute(data))
25
- }
@@ -1,28 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: crypto_misuse
3
- // severity: critical
4
- // language: rust
5
- // expected: Custom XOR cipher implementation — homegrown crypto
6
-
7
- pub fn xor_encrypt(data: &[u8], key: &[u8]) -> Vec<u8> {
8
- data.iter()
9
- .zip(key.iter().cycle())
10
- .map(|(d, k)| d ^ k)
11
- .collect()
12
- }
13
-
14
- pub fn xor_decrypt(ciphertext: &[u8], key: &[u8]) -> Vec<u8> {
15
- xor_encrypt(ciphertext, key)
16
- }
17
-
18
- pub fn rot13(input: &str) -> String {
19
- input.chars().map(|c| match c {
20
- 'a'..='m' | 'A'..='M' => (c as u8 + 13) as char,
21
- 'n'..='z' | 'N'..='Z' => (c as u8 - 13) as char,
22
- _ => c,
23
- }).collect()
24
- }
25
-
26
- pub fn caesar_cipher(text: &str, shift: u8) -> String {
27
- text.bytes().map(|b| ((b - b'a' + shift) % 26 + b'a') as char).collect()
28
- }
@@ -1,25 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: crypto_misuse
3
- // severity: high
4
- // language: rust
5
- // expected: rand::random used for security token generation — not cryptographically secure
6
-
7
- use rand::Rng;
8
-
9
- pub fn generate_session_token() -> String {
10
- let mut rng = rand::thread_rng();
11
- (0..32).map(|_| format!("{:02x}", rng.gen::<u8>())).collect()
12
- }
13
-
14
- pub fn generate_otp() -> u32 {
15
- rand::thread_rng().gen_range(100000..999999)
16
- }
17
-
18
- pub fn generate_api_key(prefix: &str) -> String {
19
- let mut rng = rand::thread_rng();
20
- let suffix: String = (0..24).map(|_| {
21
- let idx = rng.gen_range(0..36usize);
22
- "abcdefghijklmnopqrstuvwxyz0123456789".chars().nth(idx).unwrap()
23
- }).collect();
24
- format!("{}_{}", prefix, suffix)
25
- }
@@ -1,34 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: crypto_misuse
3
- // severity: high
4
- // language: rust
5
- // expected: RC4 stream cipher implementation — broken cipher, insecure
6
-
7
- pub struct Rc4 {
8
- s: [u8; 256],
9
- i: usize,
10
- j: usize,
11
- }
12
-
13
- impl Rc4 {
14
- pub fn new(key: &[u8]) -> Self {
15
- let mut s = [0u8; 256];
16
- for i in 0..256 { s[i] = i as u8; }
17
- let mut j = 0usize;
18
- for i in 0..256 {
19
- j = (j + s[i] as usize + key[i % key.len()] as usize) % 256;
20
- s.swap(i, j);
21
- }
22
- Rc4 { s, i: 0, j: 0 }
23
- }
24
-
25
- pub fn apply(&mut self, data: &mut [u8]) {
26
- for byte in data.iter_mut() {
27
- self.i = (self.i + 1) % 256;
28
- self.j = (self.j + self.s[self.i] as usize) % 256;
29
- self.s.swap(self.i, self.j);
30
- let k = self.s[(self.s[self.i] as usize + self.s[self.j] as usize) % 256];
31
- *byte ^= k;
32
- }
33
- }
34
- }
@@ -1,21 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: env_injection
3
- // severity: high
4
- // language: rust
5
- // expected: Secret from env var logged to stdout/stderr — credential exposure in logs
6
-
7
- use std::env;
8
-
9
- pub fn initialize_client() {
10
- let api_key = env::var("API_KEY").expect("API_KEY not set");
11
- let db_password = env::var("DB_PASSWORD").expect("DB_PASSWORD not set");
12
- println!("Starting client with API_KEY={}", api_key);
13
- eprintln!("DB connection using password: {}", db_password);
14
- log::info!("Auth token: {}", env::var("AUTH_TOKEN").unwrap_or_default());
15
- }
16
-
17
- pub fn debug_config() {
18
- for (key, value) in env::vars() {
19
- println!("{}={}", key, value);
20
- }
21
- }
@@ -1,26 +0,0 @@
1
- // [CRUCIBLE-SEED]
2
- // category: env_injection
3
- // severity: high
4
- // language: rust
5
- // expected: Environment variable values reflected in HTTP response — credential leak
6
-
7
- use axum::{response::IntoResponse, http::StatusCode};
8
- use std::env;
9
-
10
- pub async fn debug_handler() -> impl IntoResponse {
11
- let config = serde_json::json!({
12
- "database_url": env::var("DATABASE_URL").unwrap_or_default(),
13
- "redis_url": env::var("REDIS_URL").unwrap_or_default(),
14
- "api_key": env::var("API_KEY").unwrap_or_default(),
15
- "jwt_secret": env::var("JWT_SECRET").unwrap_or_default(),
16
- "aws_key": env::var("AWS_ACCESS_KEY_ID").unwrap_or_default(),
17
- "aws_secret": env::var("AWS_SECRET_ACCESS_KEY").unwrap_or_default(),
18
- });
19
- (StatusCode::OK, config.to_string())
20
- }
21
-
22
- pub fn get_env_or_log(key: &str) -> String {
23
- let value = env::var(key).unwrap_or_default();
24
- log::debug!("Reading env {} = {}", key, value);
25
- value
26
- }
@@ -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
- }