tainted 0.1.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b26e5de6db90715d8868475b14f828ee951472378e2ab3d751bb36e0ab570a1
4
- data.tar.gz: 4e84f893cefc8c37f52b9b353ff80ea3a63eba096f625d6acb2061aefb83d299
3
+ metadata.gz: 278da9234147c4a8df18795ca9666877032253e8cb4409219ba0fd8e4420444b
4
+ data.tar.gz: 16e24fa14406e9755b3f631809a23a13fcf255605b5f6a2f66fc60d27ecee27a
5
5
  SHA512:
6
- metadata.gz: 2a73d2e0c62366eb397b64c7f4cd8d78f643ba1179bafa4534664c901cadc683d3b1d375a205024e0716930d17634076de122e36e3f96c2c8f53f0310ac747c9
7
- data.tar.gz: f1444e63ab1f1fa2cbb328b19d2676c5eabc5948ae6a4bc7af0167ce08c7dd898ea5ee203629ab30adec04c76d0ed652c1966ff008c4806775d8e4039726aaeb
6
+ metadata.gz: b1fdc6834f8e8727e6e7fa0328ddd4193d4a7433f3c020f16eacaa6d63ef61f96b682a7a7e8b34db7e39d28a4554c77373d96467bb3a9cab8b8b00348d4b0fd0
7
+ data.tar.gz: 96b9a1687308bed7f57317dd66ece9eca69a7d0e2a7544cc8e40861017911d447aa11244daf44d5e3d27620358e80150e117b008c3a7a97b76e633608ff73f31
data/README.md CHANGED
@@ -29,8 +29,13 @@ require 'tainted'
29
29
  file = "#{__dir__}/../fixtures/simple.rb"
30
30
  lint = Tainted::Lint.new(file, %i[tainted], %i[unsafe])
31
31
  lint.analyze
32
- # Method `unsafe()` consuming tainted variable `d`
33
- # Method `unsafe()` consuming tainted variable `c`
32
+ =>
33
+ [#<Tainted::Offense:0x0000000107caf690
34
+ @message="Method `unsafe()` consuming tainted variable `d`",
35
+ @node=(call nil nil (ident "unsafe") (arg_paren (args ((var_ref (ident "d"))))))>,
36
+ #<Tainted::Offense:0x0000000107caf5f0
37
+ @message="Method `unsafe()` consuming tainted variable `c`",
38
+ @node=(call nil nil (ident "unsafe") (arg_paren (args ((var_ref (ident "c"))))))>]
34
39
  ```
35
40
 
36
41
  ## Development
data/Rakefile CHANGED
@@ -9,4 +9,4 @@ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
- task default: %i[spec rubocop]
12
+ task default: %i[spec]
data/lib/tainted/lint.rb CHANGED
@@ -5,7 +5,7 @@ module Tainted
5
5
  def initialize(filepath, sources, sinks)
6
6
  @filepath = filepath
7
7
 
8
- t = Tainted::DataFlow.new(@filepath)
8
+ t = DataFlow.new(@filepath)
9
9
  t.generate
10
10
  var_dependencies = t.tainted
11
11
  State.instance.var_dependencies = var_dependencies
@@ -15,7 +15,7 @@ module Tainted
15
15
 
16
16
  def analyze
17
17
  @visitor.visit(SyntaxTree.parse_file(@filepath))
18
- @visitor.result
18
+ @visitor.offenses
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tainted
4
+ class Offense
5
+ attr_reader :node, :message
6
+
7
+ def initialize(node, message)
8
+ @node = node
9
+ @message = message
10
+ end
11
+ end
12
+ end
@@ -2,13 +2,14 @@
2
2
 
3
3
  module Tainted
4
4
  class Static < SyntaxTree::Visitor
5
- attr_reader :result
5
+ attr_reader :offenses
6
6
 
7
- def initialize(sources, _sinks)
7
+ def initialize(sources, sinks)
8
8
  super()
9
9
 
10
10
  @sources = sources
11
- @result = []
11
+ @sinks = sinks
12
+ @offenses = []
12
13
  end
13
14
 
14
15
  def visit(node)
@@ -29,10 +30,17 @@ module Tainted
29
30
 
30
31
  def parse_assign(node)
31
32
  variable_name = node.target.value.value
32
- # pp node.value.class
33
- return unless node.value.is_a?(SyntaxTree::CallNode)
34
33
 
35
- method_name = node.value.message.value
34
+ method_name =
35
+ case node.value
36
+ when SyntaxTree::CallNode
37
+ node.value.message.value
38
+ when SyntaxTree::ARef
39
+ # (aref (vcall (ident "<method_name>")))
40
+ node.value.collection.value.value
41
+ end
42
+
43
+ return if method_name.nil?
36
44
  return unless @sources.include?(method_name&.to_sym)
37
45
 
38
46
  State.instance.var_dependencies[variable_name.to_sym][:tainted] = true
@@ -45,10 +53,12 @@ module Tainted
45
53
  arguments.map { |arg| [arg, taint_status(arg.value.value.to_sym)] }
46
54
 
47
55
  method_name = node.message.value
56
+ return unless @sinks.include?(method_name.to_sym)
57
+
48
58
  taint_statuses.each do |status|
49
59
  next unless status[1]
50
60
 
51
- @result << "Method `#{method_name}()` consuming tainted variable `#{status[0].value.value}`"
61
+ @offenses << Offense.new(node, "Method `#{method_name}()` consuming tainted variable `#{status[0].value.value}`")
52
62
  end
53
63
  end
54
64
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tainted
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/tainted.rb CHANGED
@@ -6,6 +6,7 @@ require_relative "tainted/state"
6
6
  require_relative "tainted/static"
7
7
  require_relative "tainted/lint"
8
8
  require_relative "tainted/dataflow"
9
+ require_relative "tainted/offense"
9
10
  require_relative "tainted/version"
10
11
 
11
12
  module Tainted
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tainted
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Syed Faraaz Ahmad
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-23 00:00:00.000000000 Z
11
+ date: 2023-11-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -23,10 +23,10 @@ files:
23
23
  - LICENSE.txt
24
24
  - README.md
25
25
  - Rakefile
26
- - fixtures/simple.rb
27
26
  - lib/tainted.rb
28
27
  - lib/tainted/dataflow.rb
29
28
  - lib/tainted/lint.rb
29
+ - lib/tainted/offense.rb
30
30
  - lib/tainted/state.rb
31
31
  - lib/tainted/static.rb
32
32
  - lib/tainted/version.rb
data/fixtures/simple.rb DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- a = tainted()
4
- b = a + 1
5
- c = b + 2
6
- d = b + c
7
- unsafe(d)
8
- unsafe(c)