trapline 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +585 -0
- data/config.ru.example +21 -0
- data/exe/trapline +8 -0
- data/lib/generators/trapline/install_generator.rb +34 -0
- data/lib/generators/trapline/templates/initializer.rb +23 -0
- data/lib/tasks/trapline.rake +19 -0
- data/lib/trapline/cli.rb +212 -0
- data/lib/trapline/configuration.rb +19 -0
- data/lib/trapline/cve/client.rb +203 -0
- data/lib/trapline/cve/record.rb +160 -0
- data/lib/trapline/engine.rb +243 -0
- data/lib/trapline/generator.rb +236 -0
- data/lib/trapline/languages.rb +65 -0
- data/lib/trapline/railtie.rb +26 -0
- data/lib/trapline/rule.rb +165 -0
- data/lib/trapline/runtime.rb +148 -0
- data/lib/trapline/store.rb +113 -0
- data/lib/trapline/suite.rb +44 -0
- data/lib/trapline/templates/cwe/cwe-22.yml +167 -0
- data/lib/trapline/templates/cwe/cwe-327.yml +124 -0
- data/lib/trapline/templates/cwe/cwe-502.yml +123 -0
- data/lib/trapline/templates/cwe/cwe-601.yml +124 -0
- data/lib/trapline/templates/cwe/cwe-611.yml +87 -0
- data/lib/trapline/templates/cwe/cwe-78.yml +166 -0
- data/lib/trapline/templates/cwe/cwe-79.yml +164 -0
- data/lib/trapline/templates/cwe/cwe-798.yml +125 -0
- data/lib/trapline/templates/cwe/cwe-89.yml +189 -0
- data/lib/trapline/templates/cwe/cwe-917.yml +46 -0
- data/lib/trapline/templates/cwe/cwe-918.yml +166 -0
- data/lib/trapline/templates/cwe/cwe-94.yml +131 -0
- data/lib/trapline/templates.rb +261 -0
- data/lib/trapline/validator.rb +359 -0
- data/lib/trapline/version.rb +5 -0
- data/lib/trapline/web/app.rb +234 -0
- data/lib/trapline/web/assets/THIRD_PARTY_LICENSES.txt +214 -0
- data/lib/trapline/web/assets/app.css +399 -0
- data/lib/trapline/web/assets/app.js +804 -0
- data/lib/trapline/web/assets/codemirror.css +344 -0
- data/lib/trapline/web/assets/codemirror.js +13263 -0
- data/lib/trapline/web/assets/index.html +165 -0
- data/lib/trapline/web/assets/jetbrains-mono-latin-400-normal.woff2 +0 -0
- data/lib/trapline/web/assets/jetbrains-mono-latin-600-normal.woff2 +0 -0
- data/lib/trapline/web/assets/public-sans-latin-400-normal.woff2 +0 -0
- data/lib/trapline/web/assets/public-sans-latin-500-normal.woff2 +0 -0
- data/lib/trapline/web/assets/public-sans-latin-600-normal.woff2 +0 -0
- data/lib/trapline/web/assets/public-sans-latin-700-normal.woff2 +0 -0
- data/lib/trapline/web/server.rb +108 -0
- data/lib/trapline.rb +70 -0
- metadata +136 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<base href="__BASE__">
|
|
7
|
+
<title>Trapline</title>
|
|
8
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Crect x=%2211%22 y=%2213%22 width=%229%22 height=%224%22 rx=%221%22 fill=%22%23f2b33d%22/%3E%3Cpath d=%22M4 5h9M4 10h16M4 15h6M4 20h12%22 stroke=%22%231c2733%22 stroke-width=%222%22 stroke-linecap=%22round%22/%3E%3C/svg%3E">
|
|
9
|
+
<link rel="stylesheet" href="assets/codemirror.css">
|
|
10
|
+
<link rel="stylesheet" href="assets/app.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<header class="top">
|
|
14
|
+
<div class="brand">
|
|
15
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h9M4 10h16M4 15h6M4 20h12" /><rect x="11" y="13" width="9" height="4" rx="1" /></svg>
|
|
16
|
+
<span>Trapline</span>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="doc">
|
|
19
|
+
<span id="doc-name" class="doc-name">Untitled rule</span>
|
|
20
|
+
<span id="doc-state" class="doc-state" aria-live="polite"></span>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="top-actions">
|
|
23
|
+
<span id="engine" class="engine" title="Engine used to run the rules"></span>
|
|
24
|
+
<button id="btn-download" class="ghost" type="button" title="Download the YAML">Download</button>
|
|
25
|
+
<button id="btn-delete" class="ghost danger" type="button" hidden>Delete</button>
|
|
26
|
+
<button id="btn-save" class="primary" type="button" title="Ctrl+S">Save</button>
|
|
27
|
+
</div>
|
|
28
|
+
</header>
|
|
29
|
+
|
|
30
|
+
<div class="layout">
|
|
31
|
+
<aside class="side" aria-label="Rules">
|
|
32
|
+
<div class="side-actions">
|
|
33
|
+
<button id="btn-new" type="button">New rule</button>
|
|
34
|
+
<button id="btn-cve" type="button" class="accent">Generate from CVE</button>
|
|
35
|
+
</div>
|
|
36
|
+
<label class="search">
|
|
37
|
+
<span class="sr-only">Filter rules</span>
|
|
38
|
+
<input id="filter" type="search" placeholder="Filter by id, CVE or CWE">
|
|
39
|
+
</label>
|
|
40
|
+
<ul id="rule-list" class="rule-list"></ul>
|
|
41
|
+
<p id="rules-path" class="rules-path"></p>
|
|
42
|
+
</aside>
|
|
43
|
+
|
|
44
|
+
<main class="work">
|
|
45
|
+
<section class="pane pane-rule" aria-label="Rule">
|
|
46
|
+
<details id="details" class="details">
|
|
47
|
+
<summary>
|
|
48
|
+
<span>Rule details</span>
|
|
49
|
+
<span id="details-summary" class="details-summary"></span>
|
|
50
|
+
</summary>
|
|
51
|
+
<form id="fields" class="fields" autocomplete="off">
|
|
52
|
+
<label class="f-id">Id <input name="id" required spellcheck="false"></label>
|
|
53
|
+
<label class="f-sev">Severity <select name="severity"></select></label>
|
|
54
|
+
<label class="f-lang">Languages <input name="languages" placeholder="ruby, python" spellcheck="false"></label>
|
|
55
|
+
<label class="f-msg">Message <textarea name="message" rows="2"></textarea></label>
|
|
56
|
+
<label class="f-cwe">CWE <input name="cwe" placeholder="CWE-89: SQL Injection"></label>
|
|
57
|
+
<label class="f-cve">CVE <input name="cve" placeholder="CVE-2024-1234" spellcheck="false"></label>
|
|
58
|
+
<label class="f-conf">Confidence
|
|
59
|
+
<select name="confidence"><option value="">—</option><option>LOW</option><option>MEDIUM</option><option>HIGH</option></select>
|
|
60
|
+
</label>
|
|
61
|
+
<label class="f-refs">References <textarea name="references" rows="2" placeholder="One URL per line" spellcheck="false"></textarea></label>
|
|
62
|
+
</form>
|
|
63
|
+
</details>
|
|
64
|
+
<div class="pane-head">
|
|
65
|
+
<h2>Rule <span class="hint">YAML</span></h2>
|
|
66
|
+
<span id="mode" class="mode"></span>
|
|
67
|
+
</div>
|
|
68
|
+
<div id="yaml-editor" class="editor"></div>
|
|
69
|
+
<div id="issues" class="issues" aria-live="polite"></div>
|
|
70
|
+
</section>
|
|
71
|
+
|
|
72
|
+
<section class="pane pane-test" aria-label="Test">
|
|
73
|
+
<div class="pane-head">
|
|
74
|
+
<h2>Test code <span class="hint" title="Click the margin next to a line: must match → must not match → no expectation">click the margin to mark</span></h2>
|
|
75
|
+
<div class="test-controls">
|
|
76
|
+
<label class="sr-only" for="test-lang">Test language</label>
|
|
77
|
+
<select id="test-lang"></select>
|
|
78
|
+
<label class="auto" title="Show the ruleid/ok comments instead of badges"><input id="raw-ann" type="checkbox"> Show comments</label>
|
|
79
|
+
<label class="auto"><input id="auto-run" type="checkbox" checked> Run on edit</label>
|
|
80
|
+
<button id="btn-run" class="primary" type="button" title="Ctrl+Enter">Run</button>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
<div id="run-status" class="run-status" aria-live="polite"></div>
|
|
84
|
+
<div id="test-editor" class="editor"></div>
|
|
85
|
+
<div id="results" class="results" aria-live="polite">
|
|
86
|
+
<p class="empty">Write a vulnerable example and a fixed one, annotated with <code>ruleid:</code> and <code>ok:</code>, and run the rule.</p>
|
|
87
|
+
</div>
|
|
88
|
+
</section>
|
|
89
|
+
</main>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<dialog id="dlg-new" class="dlg">
|
|
93
|
+
<form method="dialog" id="form-new">
|
|
94
|
+
<h3>New rule</h3>
|
|
95
|
+
<fieldset class="kinds" id="kinds"></fieldset>
|
|
96
|
+
<div class="row">
|
|
97
|
+
<label>Id <input name="id" value="my-rule" spellcheck="false" required></label>
|
|
98
|
+
<label>Language <select name="language" id="new-lang"></select></label>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="dlg-actions">
|
|
101
|
+
<button value="cancel" type="submit" class="ghost" formnovalidate>Cancel</button>
|
|
102
|
+
<button value="ok" type="submit" class="primary">Create</button>
|
|
103
|
+
</div>
|
|
104
|
+
</form>
|
|
105
|
+
</dialog>
|
|
106
|
+
|
|
107
|
+
<dialog id="dlg-cve" class="dlg dlg-wide">
|
|
108
|
+
<form id="form-cve">
|
|
109
|
+
<h3>Generate a rule from a CVE</h3>
|
|
110
|
+
<p class="dlg-lead">Looks up the vulnerability in NVD and OSV and builds drafts from the CWE and the affected packages.</p>
|
|
111
|
+
<div class="row">
|
|
112
|
+
<label class="grow">CVE or GHSA <input name="id" placeholder="CVE-2021-44228" spellcheck="false" required></label>
|
|
113
|
+
<label>Language <select name="language" id="cve-lang"><option value="">Detect</option></select></label>
|
|
114
|
+
<button type="submit" class="primary" id="btn-cve-fetch">Search</button>
|
|
115
|
+
</div>
|
|
116
|
+
<details class="manual" id="cve-manual">
|
|
117
|
+
<summary>No network access? Enter the data manually</summary>
|
|
118
|
+
<div class="manual-grid">
|
|
119
|
+
<label>CWE <input name="m_cwe" placeholder="CWE-89"></label>
|
|
120
|
+
<label>Ecosystem
|
|
121
|
+
<select name="m_ecosystem"><option value="">—</option><option>RubyGems</option><option>PyPI</option><option>npm</option><option>Maven</option><option>Go</option></select>
|
|
122
|
+
</label>
|
|
123
|
+
<label>Package <input name="m_package" placeholder="package name" spellcheck="false"></label>
|
|
124
|
+
<label>Fixed in <input name="m_fixed" placeholder="1.2.3" spellcheck="false"></label>
|
|
125
|
+
<label class="span">Description <textarea name="m_description" rows="3"></textarea></label>
|
|
126
|
+
<button type="button" id="btn-cve-manual">Generate with this data</button>
|
|
127
|
+
</div>
|
|
128
|
+
</details>
|
|
129
|
+
</form>
|
|
130
|
+
<div id="cve-result" class="cve-result"></div>
|
|
131
|
+
<div class="dlg-actions">
|
|
132
|
+
<button type="button" class="ghost" id="btn-cve-close">Close</button>
|
|
133
|
+
<button type="button" class="primary" id="btn-cve-open" disabled>Open in editor</button>
|
|
134
|
+
</div>
|
|
135
|
+
</dialog>
|
|
136
|
+
|
|
137
|
+
<dialog id="dlg-save" class="dlg">
|
|
138
|
+
<form method="dialog" id="form-save">
|
|
139
|
+
<h3>Save rule</h3>
|
|
140
|
+
<label>File name <input name="slug" required spellcheck="false" pattern="[A-Za-z0-9][A-Za-z0-9._\-\/]*"></label>
|
|
141
|
+
<p class="dlg-lead" id="save-path"></p>
|
|
142
|
+
<div class="dlg-actions">
|
|
143
|
+
<button value="cancel" type="submit" class="ghost" formnovalidate>Cancel</button>
|
|
144
|
+
<button value="ok" type="submit" class="primary">Save</button>
|
|
145
|
+
</div>
|
|
146
|
+
</form>
|
|
147
|
+
</dialog>
|
|
148
|
+
|
|
149
|
+
<dialog id="dlg-confirm" class="dlg">
|
|
150
|
+
<form method="dialog">
|
|
151
|
+
<h3 id="confirm-title"></h3>
|
|
152
|
+
<p class="dlg-lead" id="confirm-text"></p>
|
|
153
|
+
<div class="dlg-actions">
|
|
154
|
+
<button value="cancel" class="ghost">Cancel</button>
|
|
155
|
+
<button value="ok" class="primary" id="confirm-ok"></button>
|
|
156
|
+
</div>
|
|
157
|
+
</form>
|
|
158
|
+
</dialog>
|
|
159
|
+
|
|
160
|
+
<div id="toast" class="toast" role="status" hidden></div>
|
|
161
|
+
|
|
162
|
+
<script src="assets/codemirror.js"></script>
|
|
163
|
+
<script src="assets/app.js"></script>
|
|
164
|
+
</body>
|
|
165
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "stringio"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module Trapline
|
|
8
|
+
module Web
|
|
9
|
+
module Server
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def start(app, host: "127.0.0.1", port: 9292, logger: $stdout)
|
|
13
|
+
handler = rack_handler
|
|
14
|
+
url = "http://#{host}:#{port}/"
|
|
15
|
+
if handler
|
|
16
|
+
logger.puts "Trapline #{VERSION} at #{url} (#{handler.name})"
|
|
17
|
+
handler.run(app, Host: host, Port: port)
|
|
18
|
+
else
|
|
19
|
+
logger.puts "Trapline #{VERSION} at #{url} (built-in server)"
|
|
20
|
+
Builtin.new(app, host: host, port: port, logger: logger).run
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def rack_handler
|
|
25
|
+
return nil if ENV["TRAPLINE_BUILTIN_SERVER"] == "1"
|
|
26
|
+
|
|
27
|
+
require "rackup"
|
|
28
|
+
%w[puma webrick].each do |name|
|
|
29
|
+
return Rackup::Handler.get(name)
|
|
30
|
+
rescue LoadError, NameError
|
|
31
|
+
next
|
|
32
|
+
end
|
|
33
|
+
nil
|
|
34
|
+
rescue LoadError
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Builtin
|
|
39
|
+
STATUS = { 200 => "OK", 201 => "Created", 204 => "No Content", 400 => "Bad Request", 401 => "Unauthorized",
|
|
40
|
+
403 => "Forbidden", 404 => "Not Found", 413 => "Payload Too Large", 422 => "Unprocessable Entity",
|
|
41
|
+
500 => "Internal Server Error", 502 => "Bad Gateway", 503 => "Service Unavailable" }.freeze
|
|
42
|
+
|
|
43
|
+
def initialize(app, host:, port:, logger:)
|
|
44
|
+
@app = app
|
|
45
|
+
@host = host
|
|
46
|
+
@port = port
|
|
47
|
+
@logger = logger
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Closing the socket from a trap handler while #accept blocks raises
|
|
51
|
+
# ThreadError, so INT/TERM only interrupt the loop.
|
|
52
|
+
def run
|
|
53
|
+
server = TCPServer.new(@host, @port)
|
|
54
|
+
previous = trap("TERM") { Thread.main.raise(Interrupt) }
|
|
55
|
+
loop do
|
|
56
|
+
client = server.accept
|
|
57
|
+
Thread.new(client) { |c| handle(c) }
|
|
58
|
+
end
|
|
59
|
+
rescue Interrupt, IOError
|
|
60
|
+
@logger.puts "Stopping Trapline"
|
|
61
|
+
ensure
|
|
62
|
+
server&.close rescue nil
|
|
63
|
+
trap("TERM", previous || "DEFAULT")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def handle(client)
|
|
67
|
+
request_line = client.gets("\r\n", 8192).to_s
|
|
68
|
+
method, target, = request_line.split(" ", 3)
|
|
69
|
+
return client.close if method.nil? || target.nil?
|
|
70
|
+
|
|
71
|
+
headers = {}
|
|
72
|
+
while (line = client.gets("\r\n", 8192)) && line != "\r\n"
|
|
73
|
+
k, v = line.split(":", 2)
|
|
74
|
+
headers[k.strip.downcase] = v.to_s.strip
|
|
75
|
+
end
|
|
76
|
+
length = headers["content-length"].to_i
|
|
77
|
+
body = length.positive? ? client.read([length, App::MAX_BODY + 1].min).to_s : ""
|
|
78
|
+
|
|
79
|
+
uri = URI.parse(target)
|
|
80
|
+
env = {
|
|
81
|
+
"REQUEST_METHOD" => method, "SCRIPT_NAME" => "", "PATH_INFO" => uri.path,
|
|
82
|
+
"QUERY_STRING" => uri.query.to_s, "SERVER_NAME" => @host, "SERVER_PORT" => @port.to_s,
|
|
83
|
+
"SERVER_PROTOCOL" => "HTTP/1.1", "rack.input" => StringIO.new(body), "rack.errors" => $stderr,
|
|
84
|
+
"rack.url_scheme" => "http", "CONTENT_TYPE" => headers["content-type"].to_s,
|
|
85
|
+
"CONTENT_LENGTH" => length.to_s
|
|
86
|
+
}
|
|
87
|
+
headers.each { |k, v| env["HTTP_#{k.upcase.tr('-', '_')}"] = v unless %w[content-type content-length].include?(k) }
|
|
88
|
+
|
|
89
|
+
status, res_headers, res_body = @app.call(env)
|
|
90
|
+
payload = String.new(encoding: Encoding::BINARY)
|
|
91
|
+
res_body.each { |chunk| payload << chunk.b }
|
|
92
|
+
res_body.close if res_body.respond_to?(:close)
|
|
93
|
+
|
|
94
|
+
client.write "HTTP/1.1 #{status} #{STATUS.fetch(status, 'OK')}\r\n"
|
|
95
|
+
res_headers.each { |k, v| client.write "#{k}: #{v}\r\n" }
|
|
96
|
+
client.write "content-length: #{payload.bytesize}\r\nconnection: close\r\n\r\n"
|
|
97
|
+
client.write payload
|
|
98
|
+
@logger.puts "#{method} #{uri.path} #{status}" if ENV["TRAPLINE_LOG"]
|
|
99
|
+
rescue StandardError => e
|
|
100
|
+
warn "trapline: #{e.class}: #{e.message}"
|
|
101
|
+
client.write "HTTP/1.1 500 Internal Server Error\r\ncontent-length: 0\r\nconnection: close\r\n\r\n" rescue nil
|
|
102
|
+
ensure
|
|
103
|
+
client.close rescue nil
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
data/lib/trapline.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "time"
|
|
4
|
+
require_relative "trapline/version"
|
|
5
|
+
require_relative "trapline/configuration"
|
|
6
|
+
require_relative "trapline/languages"
|
|
7
|
+
require_relative "trapline/rule"
|
|
8
|
+
require_relative "trapline/validator"
|
|
9
|
+
require_relative "trapline/engine"
|
|
10
|
+
require_relative "trapline/store"
|
|
11
|
+
require_relative "trapline/cve/record"
|
|
12
|
+
require_relative "trapline/cve/client"
|
|
13
|
+
require_relative "trapline/templates"
|
|
14
|
+
require_relative "trapline/runtime"
|
|
15
|
+
require_relative "trapline/generator"
|
|
16
|
+
require_relative "trapline/suite"
|
|
17
|
+
|
|
18
|
+
module Trapline
|
|
19
|
+
class Error < StandardError; end
|
|
20
|
+
|
|
21
|
+
class ParseError < Error
|
|
22
|
+
attr_reader :line, :column
|
|
23
|
+
|
|
24
|
+
def initialize(message, line: nil, column: nil)
|
|
25
|
+
super(message)
|
|
26
|
+
@line = line
|
|
27
|
+
@column = column
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class NotFound < Error; end
|
|
32
|
+
class InvalidSlug < Error; end
|
|
33
|
+
class NetworkError < Error; end
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
def config
|
|
37
|
+
@config ||= Configuration.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def configure
|
|
41
|
+
yield config
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reset_config!
|
|
45
|
+
@config = Configuration.new
|
|
46
|
+
@engine = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
attr_writer :engine
|
|
50
|
+
|
|
51
|
+
def engine
|
|
52
|
+
@engine ||= Engine.detect(config.engine_binary)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def store
|
|
56
|
+
Store.new(config.rules_path)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def validate(yaml, engine: false)
|
|
60
|
+
Validator.new(engine: engine ? self.engine : nil).validate(yaml)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def generate_from_cve(cve_id, **opts)
|
|
64
|
+
Generator.new(**opts).from_cve(cve_id)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
require_relative "trapline/web/app"
|
|
70
|
+
require_relative "trapline/railtie" if defined?(Rails::Railtie)
|
metadata
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: trapline
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jose Augusto
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-11-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: minitest
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '7'
|
|
23
|
+
type: :development
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '5.0'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7'
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: rake
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
type: :development
|
|
41
|
+
prerelease: false
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '13.0'
|
|
47
|
+
description: |
|
|
48
|
+
Trapline is a web editor for creating, testing and maintaining semgrep/opengrep
|
|
49
|
+
rules, with structural validation, execution with ruleid/ok annotations and a
|
|
50
|
+
draft generator from CVEs (NVD + OSV) with per-CWE templates. It works as a
|
|
51
|
+
CLI (`trapline server`), as a Rack app and mounted in a Rails app.
|
|
52
|
+
email:
|
|
53
|
+
- joseaugusto.881@outlook.com
|
|
54
|
+
executables:
|
|
55
|
+
- trapline
|
|
56
|
+
extensions: []
|
|
57
|
+
extra_rdoc_files: []
|
|
58
|
+
files:
|
|
59
|
+
- LICENSE
|
|
60
|
+
- README.md
|
|
61
|
+
- config.ru.example
|
|
62
|
+
- exe/trapline
|
|
63
|
+
- lib/generators/trapline/install_generator.rb
|
|
64
|
+
- lib/generators/trapline/templates/initializer.rb
|
|
65
|
+
- lib/tasks/trapline.rake
|
|
66
|
+
- lib/trapline.rb
|
|
67
|
+
- lib/trapline/cli.rb
|
|
68
|
+
- lib/trapline/configuration.rb
|
|
69
|
+
- lib/trapline/cve/client.rb
|
|
70
|
+
- lib/trapline/cve/record.rb
|
|
71
|
+
- lib/trapline/engine.rb
|
|
72
|
+
- lib/trapline/generator.rb
|
|
73
|
+
- lib/trapline/languages.rb
|
|
74
|
+
- lib/trapline/railtie.rb
|
|
75
|
+
- lib/trapline/rule.rb
|
|
76
|
+
- lib/trapline/runtime.rb
|
|
77
|
+
- lib/trapline/store.rb
|
|
78
|
+
- lib/trapline/suite.rb
|
|
79
|
+
- lib/trapline/templates.rb
|
|
80
|
+
- lib/trapline/templates/cwe/cwe-22.yml
|
|
81
|
+
- lib/trapline/templates/cwe/cwe-327.yml
|
|
82
|
+
- lib/trapline/templates/cwe/cwe-502.yml
|
|
83
|
+
- lib/trapline/templates/cwe/cwe-601.yml
|
|
84
|
+
- lib/trapline/templates/cwe/cwe-611.yml
|
|
85
|
+
- lib/trapline/templates/cwe/cwe-78.yml
|
|
86
|
+
- lib/trapline/templates/cwe/cwe-79.yml
|
|
87
|
+
- lib/trapline/templates/cwe/cwe-798.yml
|
|
88
|
+
- lib/trapline/templates/cwe/cwe-89.yml
|
|
89
|
+
- lib/trapline/templates/cwe/cwe-917.yml
|
|
90
|
+
- lib/trapline/templates/cwe/cwe-918.yml
|
|
91
|
+
- lib/trapline/templates/cwe/cwe-94.yml
|
|
92
|
+
- lib/trapline/validator.rb
|
|
93
|
+
- lib/trapline/version.rb
|
|
94
|
+
- lib/trapline/web/app.rb
|
|
95
|
+
- lib/trapline/web/assets/THIRD_PARTY_LICENSES.txt
|
|
96
|
+
- lib/trapline/web/assets/app.css
|
|
97
|
+
- lib/trapline/web/assets/app.js
|
|
98
|
+
- lib/trapline/web/assets/codemirror.css
|
|
99
|
+
- lib/trapline/web/assets/codemirror.js
|
|
100
|
+
- lib/trapline/web/assets/index.html
|
|
101
|
+
- lib/trapline/web/assets/jetbrains-mono-latin-400-normal.woff2
|
|
102
|
+
- lib/trapline/web/assets/jetbrains-mono-latin-600-normal.woff2
|
|
103
|
+
- lib/trapline/web/assets/public-sans-latin-400-normal.woff2
|
|
104
|
+
- lib/trapline/web/assets/public-sans-latin-500-normal.woff2
|
|
105
|
+
- lib/trapline/web/assets/public-sans-latin-600-normal.woff2
|
|
106
|
+
- lib/trapline/web/assets/public-sans-latin-700-normal.woff2
|
|
107
|
+
- lib/trapline/web/server.rb
|
|
108
|
+
homepage: https://github.com/JAugusto42/trapline
|
|
109
|
+
licenses:
|
|
110
|
+
- MIT
|
|
111
|
+
metadata:
|
|
112
|
+
source_code_uri: https://github.com/JAugusto42/trapline
|
|
113
|
+
bug_tracker_uri: https://github.com/JAugusto42/trapline/issues
|
|
114
|
+
rubygems_mfa_required: 'true'
|
|
115
|
+
post_install_message:
|
|
116
|
+
rdoc_options: []
|
|
117
|
+
require_paths:
|
|
118
|
+
- lib
|
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '3.3'
|
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - ">="
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: '0'
|
|
129
|
+
requirements:
|
|
130
|
+
- opengrep or semgrep on PATH to run rules
|
|
131
|
+
rubygems_version: 3.5.22
|
|
132
|
+
signing_key:
|
|
133
|
+
specification_version: 4
|
|
134
|
+
summary: Editor and generator for semgrep/opengrep rules, standalone or mounted in
|
|
135
|
+
Rails
|
|
136
|
+
test_files: []
|