mirror of
https://github.com/anotherhadi/spilltea.git
synced 2026-05-20 01:32:33 +02:00
check if trufflehog is installed on_start
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
+26
-5
@@ -31,14 +31,14 @@ Plugin = {
|
||||
|
||||
### Hook reference
|
||||
|
||||
| Hook | When called | Sync/async | Return value (sync only) |
|
||||
| Hook | When called | Sync/async | Return value |
|
||||
| ------------------------- | ------------------------------------- | ------------ | ----------------------------------------------- |
|
||||
| `on_config(config_text)` | At startup and on config save | always sync | ignored |
|
||||
| `on_start()` | Once at startup, after `on_config` | configurable | ignored |
|
||||
| `on_start()` | Once at startup, after `on_config` | configurable | `false` to self-disable the plugin, otherwise ignored |
|
||||
| `on_quit()` | When the app exits | always sync | ignored |
|
||||
| `on_request(req)` | Every request, before auto-forward | configurable | `"drop"`, `"forward"`, or `nil` |
|
||||
| `on_response(req, res)` | Every response | configurable | `"drop"`, `"forward"`, or `nil` |
|
||||
| `on_history_entry(entry)` | Sync: before DB insert / Async: after | configurable | `"skip"` (don't save), `"keep"` or `nil` (save) |
|
||||
| `on_request(req)` | Every request, before auto-forward | configurable | `"drop"`, `"forward"`, or `nil` (sync only) |
|
||||
| `on_response(req, res)` | Every response | configurable | `"drop"`, `"forward"`, or `nil` (sync only) |
|
||||
| `on_history_entry(entry)` | Sync: before DB insert / Async: after | configurable | `"skip"` (don't save), `"keep"` or `nil` (save) -- sync only |
|
||||
|
||||
## Request and response objects
|
||||
|
||||
@@ -141,6 +141,27 @@ Each plugin gets a **config textarea** on the Plugins page. The raw text is pass
|
||||
|
||||
### Return values for sync hooks
|
||||
|
||||
**`on_start`:**
|
||||
|
||||
| Return value | Effect |
|
||||
| ------------ | -------------------------------------------------------------------------------------------- |
|
||||
| `false` | The plugin is disabled immediately and the state is persisted (equivalent to toggling it off). |
|
||||
| anything else | Ignored. |
|
||||
|
||||
This is useful for prerequisite checks (binary not found, config invalid, etc.) so the plugin does not silently run in a broken state:
|
||||
|
||||
```lua
|
||||
function on_start()
|
||||
local h = io.popen("command -v mytool 2>/dev/null")
|
||||
local result = h and h:read("*a") or ""
|
||||
if h then h:close() end
|
||||
if result:match("^%s*$") then
|
||||
notif("MyPlugin", "mytool not found, plugin disabled", "error")
|
||||
return false
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**`on_request` and `on_response`:**
|
||||
|
||||
| Return value | Effect |
|
||||
|
||||
@@ -292,22 +292,19 @@ func pushEntry(L *lua.LState, e db.Entry) *lua.LTable {
|
||||
return t
|
||||
}
|
||||
|
||||
func callHook(p *Plugin, hookName string, args ...lua.LValue) (string, error) {
|
||||
func callHook(p *Plugin, hookName string, args ...lua.LValue) (lua.LValue, error) {
|
||||
fn := p.L.GetGlobal(hookName)
|
||||
if fn == lua.LNil {
|
||||
return "", nil
|
||||
return lua.LNil, nil
|
||||
}
|
||||
if err := p.L.CallByParam(lua.P{
|
||||
Fn: fn,
|
||||
NRet: 1,
|
||||
Protect: true,
|
||||
}, args...); err != nil {
|
||||
return "", err
|
||||
return lua.LNil, err
|
||||
}
|
||||
ret := p.L.Get(-1)
|
||||
p.L.Pop(1)
|
||||
if s, ok := ret.(lua.LString); ok {
|
||||
return string(s), nil
|
||||
}
|
||||
return "", nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -191,17 +191,31 @@ func (m *Manager) TogglePlugin(name string) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
disableIfFalse := func(p *Plugin, ret lua.LValue) {
|
||||
if ret == lua.LFalse {
|
||||
p.Enabled = false
|
||||
if m.db != nil {
|
||||
_ = m.db.SavePluginState(p.Name, false, p.ConfigText)
|
||||
}
|
||||
}
|
||||
}
|
||||
if hc.Sync {
|
||||
found.mu.Lock()
|
||||
if _, err := callHook(found, "on_start"); err != nil {
|
||||
ret, err := callHook(found, "on_start")
|
||||
if err != nil {
|
||||
log.Printf("plugin %s on_start: %v", found.Name, err)
|
||||
} else {
|
||||
disableIfFalse(found, ret)
|
||||
}
|
||||
found.mu.Unlock()
|
||||
} else {
|
||||
go func() {
|
||||
found.mu.Lock()
|
||||
if _, err := callHook(found, "on_start"); err != nil {
|
||||
ret, err := callHook(found, "on_start")
|
||||
if err != nil {
|
||||
log.Printf("plugin %s on_start: %v", found.Name, err)
|
||||
} else {
|
||||
disableIfFalse(found, ret)
|
||||
}
|
||||
found.mu.Unlock()
|
||||
}()
|
||||
@@ -264,17 +278,31 @@ func (m *Manager) RunOnStart() {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
disableIfFalse := func(p *Plugin, ret lua.LValue) {
|
||||
if ret == lua.LFalse {
|
||||
p.Enabled = false
|
||||
if m.db != nil {
|
||||
_ = m.db.SavePluginState(p.Name, false, p.ConfigText)
|
||||
}
|
||||
}
|
||||
}
|
||||
if hc.Sync {
|
||||
p.mu.Lock()
|
||||
if _, err := callHook(p, "on_start"); err != nil {
|
||||
ret, err := callHook(p, "on_start")
|
||||
if err != nil {
|
||||
log.Printf("plugin %s on_start: %v", p.Name, err)
|
||||
} else {
|
||||
disableIfFalse(p, ret)
|
||||
}
|
||||
p.mu.Unlock()
|
||||
} else {
|
||||
go func(p *Plugin) {
|
||||
p.mu.Lock()
|
||||
if _, err := callHook(p, "on_start"); err != nil {
|
||||
ret, err := callHook(p, "on_start")
|
||||
if err != nil {
|
||||
log.Printf("plugin %s on_start: %v", p.Name, err)
|
||||
} else {
|
||||
disableIfFalse(p, ret)
|
||||
}
|
||||
p.mu.Unlock()
|
||||
}(p)
|
||||
@@ -316,13 +344,15 @@ func (m *Manager) runSyncDecisionForPlugins(hookName string, argsFor func(*Plugi
|
||||
log.Printf("plugin %s %s: %v", p.Name, hookName, err)
|
||||
continue
|
||||
}
|
||||
switch result {
|
||||
if s, ok := result.(lua.LString); ok {
|
||||
switch string(s) {
|
||||
case "drop":
|
||||
return intercept.Drop
|
||||
case "forward":
|
||||
return intercept.Forward
|
||||
}
|
||||
}
|
||||
}
|
||||
return intercept.Intercept
|
||||
}
|
||||
|
||||
@@ -388,7 +418,7 @@ func (m *Manager) RunSyncOnHistoryEntry(e db.Entry) bool {
|
||||
log.Printf("plugin %s on_history_entry: %v", p.Name, err)
|
||||
continue
|
||||
}
|
||||
if result == "skip" {
|
||||
if s, ok := result.(lua.LString); ok && string(s) == "skip" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,23 @@ Requires `trufflehog` v3+ to be installed and available in PATH.
|
||||
Each finding is stored on the **Findings** page with the matched detector output.
|
||||
Findings are deduplicated per host+path+body content so repeated requests do not create duplicates.
|
||||
]],
|
||||
on_start = { sync = false },
|
||||
on_request = { sync = false },
|
||||
on_response = { sync = false },
|
||||
disable_by_default = true,
|
||||
}
|
||||
|
||||
function on_start()
|
||||
local handle = io.popen("command -v trufflehog 2>/dev/null")
|
||||
local result = handle and handle:read("*a") or ""
|
||||
if handle then handle:close() end
|
||||
if not result or result:match("^%s*$") then
|
||||
log("trufflehog is not installed or not in PATH")
|
||||
notif("TruffleHog", "trufflehog is not installed or not in PATH, plugin disabled", "error")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local function scan(label, content, host, path)
|
||||
if not content or content == "" then return end
|
||||
local out, err = shell_pipe("f=$(mktemp) && cat > \"$f\" && trufflehog filesystem --no-color \"$f\"; rc=$?; rm -f \"$f\"; exit $rc", content)
|
||||
|
||||
Reference in New Issue
Block a user