guardrails-ruby 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MILESTONES.md +11 -0
- data/lib/guardrails_ruby/checks/code_execution.rb +56 -0
- data/lib/guardrails_ruby/checks/disclaimer.rb +28 -0
- data/lib/guardrails_ruby/checks/pii.rb +15 -2
- data/lib/guardrails_ruby/checks/prompt_injection.rb +34 -1
- data/lib/guardrails_ruby/checks/script_detection.rb +53 -0
- data/lib/guardrails_ruby/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6012f0c117ac82c9c7feb863260f3b84f5ec527dccbe1d85390eff74c7e192e6
|
|
4
|
+
data.tar.gz: e2dab3618bb598cf932bb4e57c5300242e1816c893dee844084c8c36bc396deb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a0777fb4f923885b9975f7ab174f9d1c3105551957cc71571921fbc34ad1daa26647b707a5605050d877002b0339336db6ce89276a77003ea4eb7baffc802c4d
|
|
7
|
+
data.tar.gz: a6565dc714a17497fdbe907b654c073ab00be71a39c39ae05e78d176ac7e160ad2b06f11507c32ddd825888ad178877f41d0396ace3d5647426e0beb4b3983cf
|
data/MILESTONES.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GuardrailsRuby
|
|
4
|
+
module Checks
|
|
5
|
+
class CodeExecution < Check
|
|
6
|
+
check_name :code_execution
|
|
7
|
+
direction :input
|
|
8
|
+
|
|
9
|
+
PATTERNS = [
|
|
10
|
+
# Shell commands
|
|
11
|
+
/\brm\s+-rf\b/i,
|
|
12
|
+
/\brm\s+-f\b/i,
|
|
13
|
+
/\bcurl\b.+\|\s*(ba)?sh\b/i,
|
|
14
|
+
/\bwget\b.+\|\s*(ba)?sh\b/i,
|
|
15
|
+
/\bchmod\s+[0-7]{3,4}\b/,
|
|
16
|
+
/\bchown\b/,
|
|
17
|
+
/\bsudo\b/,
|
|
18
|
+
/\bmkdir\s+-p\b/,
|
|
19
|
+
/\bdd\s+if=/,
|
|
20
|
+
/\b:(){ :\|:& };:/, # fork bomb
|
|
21
|
+
|
|
22
|
+
# Code execution functions
|
|
23
|
+
/\beval\s*\(/i,
|
|
24
|
+
/\bexec\s*\(/i,
|
|
25
|
+
/\bsystem\s*\(/i,
|
|
26
|
+
/\b__import__\s*\(/i,
|
|
27
|
+
/\bos\.system\s*\(/i,
|
|
28
|
+
/\bsubprocess\.(run|call|Popen)\s*\(/i,
|
|
29
|
+
/\bRuntime\.getRuntime\(\)\.exec\s*\(/i,
|
|
30
|
+
|
|
31
|
+
# Shell interpolation
|
|
32
|
+
/`[^`]+`/, # backticks
|
|
33
|
+
/\$\([^)]+\)/, # $() command substitution
|
|
34
|
+
|
|
35
|
+
# Dangerous redirects
|
|
36
|
+
/>\s*\/dev\/sd[a-z]/,
|
|
37
|
+
/>\s*\/etc\//,
|
|
38
|
+
/;\s*shutdown\b/i,
|
|
39
|
+
/;\s*reboot\b/i,
|
|
40
|
+
/;\s*halt\b/i,
|
|
41
|
+
/\bpowershell\b.+-enc/i,
|
|
42
|
+
].freeze
|
|
43
|
+
|
|
44
|
+
def call(text, context: {})
|
|
45
|
+
matched = PATTERNS.select { |p| text.match?(p) }
|
|
46
|
+
|
|
47
|
+
if matched.any?
|
|
48
|
+
fail! "Potential code execution detected",
|
|
49
|
+
matches: matched.map(&:source)
|
|
50
|
+
else
|
|
51
|
+
pass!
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GuardrailsRuby
|
|
4
|
+
module Checks
|
|
5
|
+
class Disclaimer < Check
|
|
6
|
+
check_name :disclaimer
|
|
7
|
+
direction :output
|
|
8
|
+
|
|
9
|
+
DEFAULT_PHRASES = [].freeze
|
|
10
|
+
|
|
11
|
+
def call(text, context: {})
|
|
12
|
+
required = @options.fetch(:required_phrases, DEFAULT_PHRASES)
|
|
13
|
+
return pass! if required.empty?
|
|
14
|
+
|
|
15
|
+
missing = required.reject do |phrase|
|
|
16
|
+
text.downcase.include?(phrase.downcase)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if missing.any?
|
|
20
|
+
fail! "Missing required disclaimers: #{missing.join('; ')}",
|
|
21
|
+
matches: missing
|
|
22
|
+
else
|
|
23
|
+
pass!
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -12,7 +12,13 @@ module GuardrailsRuby
|
|
|
12
12
|
email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/,
|
|
13
13
|
phone_us: /\b(?:\+?1[-.]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/,
|
|
14
14
|
ip_address: /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/,
|
|
15
|
-
date_of_birth: /\b(?:DOB|date of birth|born)[:\s]*\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}\b/i
|
|
15
|
+
date_of_birth: /\b(?:DOB|date of birth|born)[:\s]*\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}\b/i,
|
|
16
|
+
|
|
17
|
+
# International formats
|
|
18
|
+
nik_indonesia: /\b\d{16}\b/,
|
|
19
|
+
phone_international: /\b\+(?:62|44|49|33|81|86|91|61|64|65)\d{8,12}\b/,
|
|
20
|
+
iban: /\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}(?:[A-Z0-9]{0,16})\b/,
|
|
21
|
+
passport: /\b[A-Z]{1,2}\d{6,9}\b/
|
|
16
22
|
}.freeze
|
|
17
23
|
|
|
18
24
|
REDACT_MAP = {
|
|
@@ -21,12 +27,19 @@ module GuardrailsRuby
|
|
|
21
27
|
email: "[EMAIL REDACTED]",
|
|
22
28
|
phone_us: "[PHONE REDACTED]",
|
|
23
29
|
ip_address: "[IP REDACTED]",
|
|
24
|
-
date_of_birth: "[DOB REDACTED]"
|
|
30
|
+
date_of_birth: "[DOB REDACTED]",
|
|
31
|
+
nik_indonesia: "[NIK REDACTED]",
|
|
32
|
+
phone_international: "[PHONE REDACTED]",
|
|
33
|
+
iban: "[IBAN REDACTED]",
|
|
34
|
+
passport: "[PASSPORT REDACTED]"
|
|
25
35
|
}.freeze
|
|
26
36
|
|
|
27
37
|
def call(text, context: {})
|
|
38
|
+
enabled = @options.fetch(:patterns, PATTERNS.keys)
|
|
28
39
|
found = {}
|
|
40
|
+
|
|
29
41
|
PATTERNS.each do |type, pattern|
|
|
42
|
+
next unless enabled.include?(type)
|
|
30
43
|
matches = text.scan(pattern)
|
|
31
44
|
found[type] = matches if matches.any?
|
|
32
45
|
end
|
|
@@ -7,6 +7,7 @@ module GuardrailsRuby
|
|
|
7
7
|
direction :input
|
|
8
8
|
|
|
9
9
|
INJECTION_PATTERNS = [
|
|
10
|
+
# Original patterns
|
|
10
11
|
/ignore\s+(all\s+)?previous\s+instructions/i,
|
|
11
12
|
/ignore\s+(all\s+)?above/i,
|
|
12
13
|
/disregard\s+(all\s+)?previous/i,
|
|
@@ -18,7 +19,39 @@ module GuardrailsRuby
|
|
|
18
19
|
/\[\s*system\s*\]/i,
|
|
19
20
|
/<\s*system\s*>/i,
|
|
20
21
|
/```\s*(system|instruction)/i,
|
|
21
|
-
/STOP\.?\s*(forget|ignore|disregard)/i
|
|
22
|
+
/STOP\.?\s*(forget|ignore|disregard)/i,
|
|
23
|
+
|
|
24
|
+
# Role-play and identity attacks
|
|
25
|
+
/from\s+now\s+on\s+(you|your)\s+(are|will|must|should)/i,
|
|
26
|
+
/forget\s+(everything|all|your)\s+(you|about|previous)/i,
|
|
27
|
+
/your\s+new\s+(role|persona|identity|name)\s+(is|will\s+be)/i,
|
|
28
|
+
/you\s+must\s+(now\s+)?(obey|follow|comply)/i,
|
|
29
|
+
/override\s+(your|all|previous)\s+(instructions|rules|guidelines)/i,
|
|
30
|
+
/bypass\s+(your|all|the)\s+(rules|restrictions|filters|safety)/i,
|
|
31
|
+
|
|
32
|
+
# Jailbreak patterns
|
|
33
|
+
/do\s+anything\s+now/i,
|
|
34
|
+
/\bDAN\b.*\bmode\b/i,
|
|
35
|
+
/jailbreak/i,
|
|
36
|
+
/developer\s+mode\s+(enabled|on|activated)/i,
|
|
37
|
+
/\bunlocked\s+mode\b/i,
|
|
38
|
+
|
|
39
|
+
# Instruction injection via delimiters
|
|
40
|
+
/---\s*(new|system|override)\s*(instructions?|prompt)/i,
|
|
41
|
+
/###\s*(instruction|system|override)/i,
|
|
42
|
+
/<<\s*(SYS|SYSTEM|INST)/i,
|
|
43
|
+
/\[INST\]/i,
|
|
44
|
+
|
|
45
|
+
# Encoding attacks
|
|
46
|
+
/base64[:\s]+[A-Za-z0-9+\/=]{20,}/i,
|
|
47
|
+
/hex[:\s]+(?:[0-9a-f]{2}\s*){10,}/i,
|
|
48
|
+
/rot13[:\s]/i,
|
|
49
|
+
|
|
50
|
+
# Prompt leaking
|
|
51
|
+
/reveal\s+(your|the)\s+(system\s+)?prompt/i,
|
|
52
|
+
/show\s+me\s+(your|the)\s+(system\s+)?(prompt|instructions)/i,
|
|
53
|
+
/what\s+(are|is)\s+your\s+(system\s+)?(prompt|instructions)/i,
|
|
54
|
+
/repeat\s+(your|the)\s+(system\s+)?(prompt|instructions)/i,
|
|
22
55
|
].freeze
|
|
23
56
|
|
|
24
57
|
def call(text, context: {})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GuardrailsRuby
|
|
4
|
+
module Checks
|
|
5
|
+
class ScriptDetection < Check
|
|
6
|
+
check_name :script_detection
|
|
7
|
+
direction :input
|
|
8
|
+
|
|
9
|
+
SCRIPTS = {
|
|
10
|
+
latin: /[\p{Latin}]/,
|
|
11
|
+
cyrillic: /[\p{Cyrillic}]/,
|
|
12
|
+
arabic: /[\p{Arabic}]/,
|
|
13
|
+
cjk: /[\p{Han}]/,
|
|
14
|
+
hangul: /[\p{Hangul}]/,
|
|
15
|
+
hiragana: /[\p{Hiragana}]/,
|
|
16
|
+
katakana: /[\p{Katakana}]/,
|
|
17
|
+
thai: /[\p{Thai}]/,
|
|
18
|
+
devanagari: /[\p{Devanagari}]/,
|
|
19
|
+
greek: /[\p{Greek}]/,
|
|
20
|
+
hebrew: /[\p{Hebrew}]/,
|
|
21
|
+
georgian: /[\p{Georgian}]/,
|
|
22
|
+
armenian: /[\p{Armenian}]/,
|
|
23
|
+
ethiopic: /[\p{Ethiopic}]/,
|
|
24
|
+
tamil: /[\p{Tamil}]/
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
def call(text, context: {})
|
|
28
|
+
allowed = @options.fetch(:allowed_scripts, [:latin])
|
|
29
|
+
allowed = allowed.map(&:to_sym)
|
|
30
|
+
|
|
31
|
+
detected = detect_scripts(text)
|
|
32
|
+
unexpected = detected - allowed
|
|
33
|
+
|
|
34
|
+
if unexpected.any?
|
|
35
|
+
fail! "Unexpected scripts detected: #{unexpected.join(', ')}",
|
|
36
|
+
matches: unexpected.map(&:to_s)
|
|
37
|
+
else
|
|
38
|
+
pass!
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def detect_scripts(text)
|
|
45
|
+
found = []
|
|
46
|
+
SCRIPTS.each do |name, pattern|
|
|
47
|
+
found << name if text.match?(pattern)
|
|
48
|
+
end
|
|
49
|
+
found
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: guardrails-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Johannes Dwi Cahyo
|
|
@@ -57,6 +57,7 @@ extra_rdoc_files: []
|
|
|
57
57
|
files:
|
|
58
58
|
- Gemfile
|
|
59
59
|
- LICENSE
|
|
60
|
+
- MILESTONES.md
|
|
60
61
|
- README.md
|
|
61
62
|
- Rakefile
|
|
62
63
|
- examples/basic.rb
|
|
@@ -65,7 +66,9 @@ files:
|
|
|
65
66
|
- guardrails-ruby.gemspec
|
|
66
67
|
- lib/guardrails_ruby.rb
|
|
67
68
|
- lib/guardrails_ruby/check.rb
|
|
69
|
+
- lib/guardrails_ruby/checks/code_execution.rb
|
|
68
70
|
- lib/guardrails_ruby/checks/competitor_mention.rb
|
|
71
|
+
- lib/guardrails_ruby/checks/disclaimer.rb
|
|
69
72
|
- lib/guardrails_ruby/checks/encoding.rb
|
|
70
73
|
- lib/guardrails_ruby/checks/format.rb
|
|
71
74
|
- lib/guardrails_ruby/checks/hallucinated_emails.rb
|
|
@@ -75,6 +78,7 @@ files:
|
|
|
75
78
|
- lib/guardrails_ruby/checks/pii.rb
|
|
76
79
|
- lib/guardrails_ruby/checks/prompt_injection.rb
|
|
77
80
|
- lib/guardrails_ruby/checks/relevance.rb
|
|
81
|
+
- lib/guardrails_ruby/checks/script_detection.rb
|
|
78
82
|
- lib/guardrails_ruby/checks/topic.rb
|
|
79
83
|
- lib/guardrails_ruby/checks/toxic_language.rb
|
|
80
84
|
- lib/guardrails_ruby/configuration.rb
|