fullshield 0.0.1 → 0.1.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 (67) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +21 -0
  3. package/README.md +159 -1
  4. package/dist/agent.js +5759 -0
  5. package/dist/cli/index.js +8612 -0
  6. package/dist/compliance.js +126 -0
  7. package/dist/confirm.js +146 -0
  8. package/dist/dashboard.js +143 -0
  9. package/dist/iac.js +84 -0
  10. package/dist/incremental.js +13 -0
  11. package/dist/index.d.ts +334 -0
  12. package/dist/index.js +6199 -0
  13. package/dist/llm.js +105 -0
  14. package/dist/mcp.js +5869 -0
  15. package/dist/runtime/auto.js +1163 -0
  16. package/dist/runtime/express.js +242 -0
  17. package/dist/runtime/fastify.js +254 -0
  18. package/dist/runtime/index.js +229 -0
  19. package/dist/runtime/rasp/loader.js +14 -0
  20. package/dist/runtime/rasp.js +1339 -0
  21. package/dist/runtime/register.js +1171 -0
  22. package/dist/supply.js +228 -0
  23. package/dist/threat.js +63 -0
  24. package/dist/workspaces.js +23 -0
  25. package/package.json +93 -8
  26. package/rules/CONFIG-BODYLIMIT-001.md +9 -0
  27. package/rules/CONFIG-CORS-001.md +9 -0
  28. package/rules/CONFIG-DOCKER-ENV-001.md +9 -0
  29. package/rules/CONFIG-DOCKER-LATEST-001.md +9 -0
  30. package/rules/CONFIG-DOCKER-ROOT-001.md +9 -0
  31. package/rules/CONFIG-ERRSTACK-001.md +9 -0
  32. package/rules/CONFIG-HELMET-001.md +9 -0
  33. package/rules/CONFIG-INSTALLSCRIPT-001.md +9 -0
  34. package/rules/CONFIG-RATELIMIT-001.md +9 -0
  35. package/rules/DEPS-DEPRECATED-001.md +9 -0
  36. package/rules/DEPS-NOLOCK-001.md +9 -0
  37. package/rules/DEPS-TYPOSQUAT-001.md +9 -0
  38. package/rules/DEPS-VULN-001.md +9 -0
  39. package/rules/README.md +60 -0
  40. package/rules/SAST-AUTH-001.md +9 -0
  41. package/rules/SAST-CMDI-001.md +9 -0
  42. package/rules/SAST-CRYPTO-001.md +9 -0
  43. package/rules/SAST-EVAL-001.md +9 -0
  44. package/rules/SAST-JWT-001.md +9 -0
  45. package/rules/SAST-NOSQLI-001.md +9 -0
  46. package/rules/SAST-PATH-001.md +9 -0
  47. package/rules/SAST-PROTO-001.md +9 -0
  48. package/rules/SAST-REDIRECT-001.md +9 -0
  49. package/rules/SAST-SQLI-001.md +9 -0
  50. package/rules/SAST-SSRF-001.md +9 -0
  51. package/rules/SAST-XSS-001.md +9 -0
  52. package/rules/SECRET-AIKEY-001.md +9 -0
  53. package/rules/SECRET-AWS-001.md +9 -0
  54. package/rules/SECRET-DBURL-001.md +9 -0
  55. package/rules/SECRET-ENTROPY-001.md +9 -0
  56. package/rules/SECRET-ENVFILE-001.md +9 -0
  57. package/rules/SECRET-GITHUB-001.md +9 -0
  58. package/rules/SECRET-GOOGLE-001.md +9 -0
  59. package/rules/SECRET-JWT-001.md +9 -0
  60. package/rules/SECRET-PRIVKEY-001.md +9 -0
  61. package/rules/SECRET-SLACK-001.md +9 -0
  62. package/rules/SECRET-STRIPE-001.md +9 -0
  63. package/templates/fullshield.config.json +7 -0
  64. package/templates/github-watch.yml +15 -0
  65. package/templates/github-workflow.yml +19 -0
  66. package/templates/gitlab-ci.yml +11 -0
  67. package/templates/pre-commit.sh +11 -0
package/dist/llm.js ADDED
@@ -0,0 +1,105 @@
1
+ import { existsSync, statSync, readFileSync, readdirSync } from 'fs';
2
+ import { relative, join } from 'path';
3
+ import { createHash } from 'crypto';
4
+
5
+ // src/llm/index.ts
6
+ function makeFindingId(ruleId, file, snippet) {
7
+ const normalized = (snippet ?? "").replace(/\s+/g, " ").trim();
8
+ return createHash("sha256").update(`${ruleId}\0${file ?? ""}\0${normalized}`).digest("hex").slice(0, 16);
9
+ }
10
+
11
+ // src/llm/index.ts
12
+ function finding(ruleId, title, message, file, severity = "high") {
13
+ return {
14
+ id: makeFindingId(ruleId, file, message),
15
+ ruleId,
16
+ module: "sast",
17
+ title,
18
+ severity,
19
+ confidence: "medium",
20
+ file,
21
+ message,
22
+ remediation: "Keep user text in the user role, never concatenate into the system prompt; do not send model output to sinks; require confirmation for dangerous tools; keep API keys server-side; set max_tokens.",
23
+ cwe: "CWE-1426"
24
+ };
25
+ }
26
+ function walk(dir, out = []) {
27
+ if (!existsSync(dir)) return out;
28
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
29
+ const full = join(dir, entry.name);
30
+ if (entry.isDirectory()) {
31
+ if (["node_modules", "dist", ".git"].includes(entry.name)) continue;
32
+ walk(full, out);
33
+ } else if (entry.isFile() && /\.[cm]?[jt]sx?$/.test(entry.name)) {
34
+ out.push(full);
35
+ }
36
+ }
37
+ return out;
38
+ }
39
+ function scanLlmApp(dir, opts = {}) {
40
+ if (!opts.experimental && process.env.FULLSHIELD_EXPERIMENTAL_LLM !== "1") return [];
41
+ if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];
42
+ const findings = [];
43
+ for (const file of walk(dir)) {
44
+ const rel = relative(dir, file) || file;
45
+ const text = readFileSync(file, "utf8");
46
+ if (/role\s*:\s*['"]system['"]/.test(text) && /content\s*:\s*['"][^'"]*['"]\s*\+|content\s*:\s*.*\+\s*req\.(body|query|params)/.test(text)) {
47
+ findings.push(
48
+ finding(
49
+ "LLM-001",
50
+ "User input concatenated into an LLM system prompt",
51
+ "User-controlled data is concatenated into a system-role message (OWASP LLM01).",
52
+ rel
53
+ )
54
+ );
55
+ }
56
+ if (/\b(exec|execSync|execFile|spawn|eval|query)\s*\(\s*(completion|response|llm|output|answer|choices)/.test(
57
+ text
58
+ ) || /\.innerHTML\s*=\s*.*(completion|choices\[)/.test(text)) {
59
+ findings.push(
60
+ finding(
61
+ "LLM-002",
62
+ "LLM output passed into a dangerous sink",
63
+ "Model output reaches exec/eval/SQL/HTML without validation (OWASP LLM02).",
64
+ rel
65
+ )
66
+ );
67
+ }
68
+ if (/name\s*:\s*['"](run_shell|shell|exec|write_file|send_payment)['"]/.test(text) && !/require(Confirmation|Approval)|confirm(ation)?\s*:/.test(text)) {
69
+ findings.push(
70
+ finding(
71
+ "LLM-003",
72
+ "Dangerous LLM tool without confirmation",
73
+ "Function-calling exposes shell/file/payment tools without a confirmation step (OWASP LLM06).",
74
+ rel
75
+ )
76
+ );
77
+ }
78
+ const browserish = /(^|\/)(public|client|browser|static)\//.test(rel.replaceAll("\\", "/"));
79
+ if (browserish && /OPENAI_API_KEY|ANTHROPIC_API_KEY|sk-[a-zA-Z0-9]{8,}/.test(text)) {
80
+ findings.push(
81
+ finding(
82
+ "LLM-004",
83
+ "LLM API key exposed to a browser bundle",
84
+ "An OpenAI/Anthropic-style key is present in a public/client file (OWASP LLM06/sensitive info).",
85
+ rel,
86
+ "critical"
87
+ )
88
+ );
89
+ }
90
+ if (/chat\.completions\.create|messages\.create|anthropic\.messages/.test(text) && !/max_tokens|max_completion_tokens|maxTokens/.test(text)) {
91
+ findings.push(
92
+ finding(
93
+ "LLM-005",
94
+ "LLM call has no output length or cost limit",
95
+ "chat/completions call does not set max_tokens (OWASP LLM10 unbounded consumption).",
96
+ rel,
97
+ "medium"
98
+ )
99
+ );
100
+ }
101
+ }
102
+ return findings;
103
+ }
104
+
105
+ export { scanLlmApp };