mirror of
https://github.com/beefproject/beef
synced 2026-06-08 13:15:56 +00:00
Merge remote-tracking branch 'origin/master' into tests/extensions-modules
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
name: JavaScript Linting
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
lint-changed-files:
|
||||
name: Lint Changed JavaScript Files (Blocking)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version: '24.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Get changed JavaScript files
|
||||
id: changed-js-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
with:
|
||||
files: '**/*.js'
|
||||
files_ignore: |
|
||||
node_modules/**
|
||||
core/main/client/lib/**
|
||||
**/*.min.js
|
||||
extensions/admin_ui/media/javascript-min/**
|
||||
separator: ' '
|
||||
|
||||
- name: Lint changed JavaScript files
|
||||
if: steps.changed-js-files.outputs.any_changed == 'true'
|
||||
run: |
|
||||
echo "Linting ${{ steps.changed-js-files.outputs.all_changed_files_count }} changed JavaScript file(s)"
|
||||
npx eslint ${{ steps.changed-js-files.outputs.all_changed_files }}
|
||||
|
||||
- name: No JavaScript files changed
|
||||
if: steps.changed-js-files.outputs.any_changed == 'false'
|
||||
run: |
|
||||
echo "No JavaScript files were changed in this PR. Skipping ESLint."
|
||||
|
||||
lint-all-files:
|
||||
name: Lint All JavaScript Files (Non-blocking Report)
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version: '24.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint all JavaScript files (report-only)
|
||||
run: |
|
||||
echo "Running ESLint on entire codebase"
|
||||
echo "This is a report-only job and will not block the PR."
|
||||
npx eslint . || true
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "Full codebase linting completed. Check the logs above for details."
|
||||
echo "This job does not affect PR merge status."
|
||||
@@ -18,13 +18,13 @@ gem 'mime-types', '~> 3.7'
|
||||
gem 'execjs', '~> 2.10'
|
||||
gem 'ansi', '~> 1.6'
|
||||
gem 'term-ansicolor', :require => 'term/ansicolor'
|
||||
gem 'rubyzip', '~> 3.2'
|
||||
gem 'rubyzip', '~> 3.3'
|
||||
gem 'espeak-ruby', '~> 1.1.0' # Text-to-Voice
|
||||
gem 'rake', '~> 13.3'
|
||||
gem 'rake', '~> 13.4'
|
||||
gem 'activerecord', '~> 8.1'
|
||||
gem 'otr-activerecord', '~> 2.6.0'
|
||||
gem 'sqlite3', '~> 2.9'
|
||||
gem 'rubocop', '~> 1.86.0', require: false
|
||||
gem 'rubocop', '~> 1.86.2', require: false
|
||||
|
||||
# Geolocation support
|
||||
group :geoip do
|
||||
@@ -37,7 +37,7 @@ gem 'erubis', '~> 2.7'
|
||||
# Metasploit Integration extension
|
||||
group :ext_msf do
|
||||
gem 'msfrpc-client', '~> 1.1', '>= 1.1.2'
|
||||
gem 'xmlrpc', '~> 0.3.3'
|
||||
gem 'xmlrpc', '~> 0.3.4'
|
||||
end
|
||||
|
||||
# Notifications extension
|
||||
@@ -67,7 +67,7 @@ group :test do
|
||||
gem 'rdoc', '~> 7.2'
|
||||
gem 'browserstack-local', '~> 1.4'
|
||||
|
||||
gem 'irb', '~> 1.17'
|
||||
gem 'irb', '~> 1.18'
|
||||
gem 'pry-byebug', '~> 3.12'
|
||||
|
||||
gem 'rest-client', '~> 2.1.0'
|
||||
@@ -80,7 +80,7 @@ group :test do
|
||||
# Note: selenium-webdriver 3.x is incompatible with Firefox version 48 and prior
|
||||
# gem 'selenium' # Requires old version of selenium which is no longer available
|
||||
gem 'geckodriver-helper', '~> 0.24.0'
|
||||
gem 'selenium-webdriver', '~> 4.41'
|
||||
gem 'selenium-webdriver', '~> 4.44'
|
||||
|
||||
# Note: nokogiri is needed by capybara which may require one of the below commands
|
||||
# sudo apt-get install libxslt-dev libxml2-dev
|
||||
|
||||
+48
-47
@@ -1,13 +1,13 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel (8.1.2.1)
|
||||
activesupport (= 8.1.2.1)
|
||||
activerecord (8.1.2.1)
|
||||
activemodel (= 8.1.2.1)
|
||||
activesupport (= 8.1.2.1)
|
||||
activemodel (8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
activerecord (8.1.3)
|
||||
activemodel (= 8.1.3)
|
||||
activesupport (= 8.1.3)
|
||||
timeout (>= 0.4.0)
|
||||
activesupport (8.1.2.1)
|
||||
activesupport (8.1.3)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
@@ -20,7 +20,7 @@ GEM
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
uri (>= 0.13.1)
|
||||
addressable (2.8.9)
|
||||
addressable (2.9.0)
|
||||
public_suffix (>= 2.0.2, < 8.0)
|
||||
ansi (1.6.0)
|
||||
archive-zip (0.13.1)
|
||||
@@ -34,7 +34,7 @@ GEM
|
||||
async
|
||||
io-endpoint
|
||||
base64 (0.3.0)
|
||||
bigdecimal (4.0.1)
|
||||
bigdecimal (4.1.2)
|
||||
browserstack-local (1.4.3)
|
||||
byebug (13.0.0)
|
||||
reline (>= 0.6.0)
|
||||
@@ -54,7 +54,7 @@ GEM
|
||||
fiber-annotation
|
||||
fiber-local (~> 1.1)
|
||||
json
|
||||
curb (1.3.1)
|
||||
curb (1.3.5)
|
||||
daemons (1.4.1)
|
||||
date (3.5.1)
|
||||
diff-lcs (1.6.2)
|
||||
@@ -64,7 +64,7 @@ GEM
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
erb (6.0.1)
|
||||
erb (6.0.4)
|
||||
erubis (2.7.0)
|
||||
espeak-ruby (1.1.0)
|
||||
event_emitter (0.2.6)
|
||||
@@ -85,12 +85,12 @@ GEM
|
||||
io-console (0.8.2)
|
||||
io-endpoint (0.15.2)
|
||||
io-like (0.4.0)
|
||||
irb (1.17.0)
|
||||
irb (1.18.0)
|
||||
pp (>= 0.6.0)
|
||||
prism (>= 1.3.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
json (2.19.2)
|
||||
json (2.19.5)
|
||||
language_server-protocol (3.17.0.5)
|
||||
lint_roller (1.1.0)
|
||||
logger (1.7.0)
|
||||
@@ -102,7 +102,7 @@ GEM
|
||||
mime-types-data (~> 3.2025, >= 3.2025.0507)
|
||||
mime-types-data (3.2025.0902)
|
||||
mini_mime (1.1.5)
|
||||
minitest (6.0.2)
|
||||
minitest (6.0.6)
|
||||
drb (~> 2.0)
|
||||
prism (~> 1.5)
|
||||
mojo_magick (0.6.8)
|
||||
@@ -117,27 +117,27 @@ GEM
|
||||
net-protocol
|
||||
netrc (0.11.0)
|
||||
nio4r (2.7.4)
|
||||
nokogiri (1.19.1-aarch64-linux-gnu)
|
||||
nokogiri (1.19.3-aarch64-linux-gnu)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-aarch64-linux-musl)
|
||||
nokogiri (1.19.3-aarch64-linux-musl)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-arm-linux-gnu)
|
||||
nokogiri (1.19.3-arm-linux-gnu)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-arm-linux-musl)
|
||||
nokogiri (1.19.3-arm-linux-musl)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-arm64-darwin)
|
||||
nokogiri (1.19.3-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-x86_64-darwin)
|
||||
nokogiri (1.19.3-x86_64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-x86_64-linux-gnu)
|
||||
nokogiri (1.19.3-x86_64-linux-gnu)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.19.1-x86_64-linux-musl)
|
||||
nokogiri (1.19.3-x86_64-linux-musl)
|
||||
racc (~> 1.4)
|
||||
otr-activerecord (2.6.0)
|
||||
activerecord (>= 6.0, < 9.0)
|
||||
parallel (1.27.0)
|
||||
parallel (2.1.0)
|
||||
parseconfig (1.1.2)
|
||||
parser (3.3.10.2)
|
||||
parser (3.3.11.1)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
power_assert (2.0.5)
|
||||
@@ -165,18 +165,18 @@ GEM
|
||||
base64 (>= 0.1.0)
|
||||
logger (>= 1.6.0)
|
||||
rack (>= 3.0.0, < 4)
|
||||
rack-session (2.1.1)
|
||||
rack-session (2.1.2)
|
||||
base64 (>= 0.1.0)
|
||||
rack (>= 3.0.0)
|
||||
rack-test (2.2.0)
|
||||
rack (>= 1.3)
|
||||
rainbow (3.1.1)
|
||||
rake (13.3.1)
|
||||
rake (13.4.2)
|
||||
rdoc (7.2.0)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
tsort
|
||||
regexp_parser (2.11.3)
|
||||
regexp_parser (2.12.0)
|
||||
reline (0.6.3)
|
||||
io-console (~> 0.5)
|
||||
rest-client (2.1.0)
|
||||
@@ -200,11 +200,11 @@ GEM
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-support (3.13.6)
|
||||
rubocop (1.86.0)
|
||||
rubocop (1.86.2)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
parallel (~> 1.10)
|
||||
parallel (>= 1.10)
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
@@ -216,12 +216,12 @@ GEM
|
||||
prism (~> 1.7)
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (3.2.2)
|
||||
rubyzip (3.3.0)
|
||||
rushover (0.3.0)
|
||||
json
|
||||
rest-client
|
||||
securerandom (0.4.1)
|
||||
selenium-webdriver (4.41.0)
|
||||
selenium-webdriver (4.44.0)
|
||||
base64 (~> 0.2)
|
||||
logger (~> 1.4)
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
@@ -241,14 +241,14 @@ GEM
|
||||
rack-session (>= 2.0.0, < 3)
|
||||
tilt (~> 2.0)
|
||||
slack-notifier (2.4.0)
|
||||
sqlite3 (2.9.2-aarch64-linux-gnu)
|
||||
sqlite3 (2.9.2-aarch64-linux-musl)
|
||||
sqlite3 (2.9.2-arm-linux-gnu)
|
||||
sqlite3 (2.9.2-arm-linux-musl)
|
||||
sqlite3 (2.9.2-arm64-darwin)
|
||||
sqlite3 (2.9.2-x86_64-darwin)
|
||||
sqlite3 (2.9.2-x86_64-linux-gnu)
|
||||
sqlite3 (2.9.2-x86_64-linux-musl)
|
||||
sqlite3 (2.9.4-aarch64-linux-gnu)
|
||||
sqlite3 (2.9.4-aarch64-linux-musl)
|
||||
sqlite3 (2.9.4-arm-linux-gnu)
|
||||
sqlite3 (2.9.4-arm-linux-musl)
|
||||
sqlite3 (2.9.4-arm64-darwin)
|
||||
sqlite3 (2.9.4-x86_64-darwin)
|
||||
sqlite3 (2.9.4-x86_64-linux-gnu)
|
||||
sqlite3 (2.9.4-x86_64-linux-musl)
|
||||
stringio (3.2.0)
|
||||
sync (0.5.0)
|
||||
term-ansicolor (1.11.3)
|
||||
@@ -276,7 +276,7 @@ GEM
|
||||
logger
|
||||
rack (>= 1, < 4)
|
||||
tilt (2.6.1)
|
||||
timeout (0.6.0)
|
||||
timeout (0.6.1)
|
||||
timers (4.4.0)
|
||||
tins (1.43.0)
|
||||
bigdecimal
|
||||
@@ -290,12 +290,13 @@ GEM
|
||||
unicode-emoji (~> 4.1)
|
||||
unicode-emoji (4.2.0)
|
||||
uri (1.1.1)
|
||||
webrick (1.9.1)
|
||||
webrick (1.9.2)
|
||||
websocket (1.2.11)
|
||||
websocket-client-simple (0.6.1)
|
||||
event_emitter
|
||||
websocket
|
||||
xmlrpc (0.3.3)
|
||||
xmlrpc (0.3.4)
|
||||
rexml
|
||||
webrick
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
@@ -324,7 +325,7 @@ DEPENDENCIES
|
||||
eventmachine (~> 1.2, >= 1.2.7)
|
||||
execjs (~> 2.10)
|
||||
geckodriver-helper (~> 0.24.0)
|
||||
irb (~> 1.17)
|
||||
irb (~> 1.18)
|
||||
json
|
||||
maxmind-db (~> 1.4)
|
||||
mime-types (~> 3.7)
|
||||
@@ -336,14 +337,14 @@ DEPENDENCIES
|
||||
qr4r (~> 0.6.1)
|
||||
rack (~> 3.2)
|
||||
rack-protection (~> 4.2.1)
|
||||
rake (~> 13.3)
|
||||
rake (~> 13.4)
|
||||
rdoc (~> 7.2)
|
||||
rest-client (~> 2.1.0)
|
||||
rspec (~> 3.13)
|
||||
rubocop (~> 1.86.0)
|
||||
rubyzip (~> 3.2)
|
||||
rubocop (~> 1.86.2)
|
||||
rubyzip (~> 3.3)
|
||||
rushover (~> 0.3.0)
|
||||
selenium-webdriver (~> 4.41)
|
||||
selenium-webdriver (~> 4.44)
|
||||
simplecov (~> 0.22)
|
||||
sinatra (~> 4.1)
|
||||
slack-notifier (~> 2.4)
|
||||
@@ -353,7 +354,7 @@ DEPENDENCIES
|
||||
thin (~> 2.0)
|
||||
uglifier (~> 4.2)
|
||||
websocket-client-simple (~> 0.6.1)
|
||||
xmlrpc (~> 0.3.3)
|
||||
xmlrpc (~> 0.3.4)
|
||||
|
||||
BUNDLED WITH
|
||||
2.7.2
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
|
||||
const js = require("@eslint/js");
|
||||
const globals = require("globals");
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
ignores: [
|
||||
"core/main/client/lib/**",
|
||||
"modules/**",
|
||||
"node_modules/**",
|
||||
"extensions/admin_ui/media/javascript-min/**",
|
||||
"**/*.min.js",
|
||||
],
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ["**/*.js"],
|
||||
ignores: ["eslint.config.js"],
|
||||
languageOptions: {
|
||||
ecmaVersion: 5,
|
||||
sourceType: "script",
|
||||
globals: {
|
||||
...globals.browser,
|
||||
|
||||
// BeEF
|
||||
beef: "readonly",
|
||||
beef_init: "readonly",
|
||||
|
||||
// jQuery
|
||||
$: "readonly",
|
||||
jQuery: "readonly",
|
||||
$j: "readonly",
|
||||
|
||||
// Libraries
|
||||
MobileEsp: "readonly",
|
||||
evercookie: "readonly",
|
||||
swfobject: "readonly",
|
||||
|
||||
// Browser-specific (old IE / old Firefox)
|
||||
XDomainRequest: "readonly",
|
||||
MozWebSocket: "readonly",
|
||||
clipboardData: "readonly",
|
||||
|
||||
// Debug
|
||||
isDebug: "readonly",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["eslint.config.js"],
|
||||
languageOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "commonjs",
|
||||
globals: {
|
||||
module: "writable",
|
||||
require: "readonly",
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
Generated
+883
-5
File diff suppressed because it is too large
Load Diff
+9
-4
@@ -3,13 +3,18 @@
|
||||
"version": "0.6.0.0",
|
||||
"description": "The Browser Exploitation Framework Project",
|
||||
"scripts": {
|
||||
"docs": "./node_modules/.bin/jsdoc -c conf.json"
|
||||
"docs": "./node_modules/.bin/jsdoc -c conf.json",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix ."
|
||||
},
|
||||
"author": "Wade Alcorn",
|
||||
"license": "GNU General Public License v2.0",
|
||||
"devDependencies": {
|
||||
"jsdoc": "^4.0.5",
|
||||
"jsdoc-to-markdown": "^9.1.3"
|
||||
"@eslint/js": "10.0.1",
|
||||
"eslint": "10.4.0",
|
||||
"globals": "17.6.0",
|
||||
"jsdoc": "4.0.5",
|
||||
"jsdoc-to-markdown": "9.1.3"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
# Example: unit specs for AutorunEngine::Engine using mocks instead of a real server/DB.
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BeEF::Core::AutorunEngine::Engine do
|
||||
let(:engine) { described_class.instance }
|
||||
let(:config) { BeEF::Core::Configuration.instance }
|
||||
|
||||
before do
|
||||
allow(engine).to receive(:print_debug)
|
||||
allow(engine).to receive(:print_info)
|
||||
allow(engine).to receive(:print_more)
|
||||
allow(engine).to receive(:print_error)
|
||||
end
|
||||
|
||||
# Fake rule object (could be a double or a persisted Rule with minimal attributes)
|
||||
def rule_with(browser: 'ALL', browser_version: 'ALL', os: 'ALL', os_version: 'ALL')
|
||||
double(
|
||||
'Rule',
|
||||
id: 1,
|
||||
browser: browser,
|
||||
browser_version: browser_version,
|
||||
os: os,
|
||||
os_version: os_version
|
||||
)
|
||||
end
|
||||
|
||||
describe '#zombie_matches_rule?' do
|
||||
it 'returns false when rule is nil' do
|
||||
expect(engine.zombie_matches_rule?('FF', '41', 'Windows', '7', nil)).to be false
|
||||
end
|
||||
|
||||
it 'returns true when rule is ALL for browser and OS' do
|
||||
rule = rule_with(browser: 'ALL', browser_version: 'ALL', os: 'ALL', os_version: 'ALL')
|
||||
allow(engine).to receive(:zombie_browser_matches_rule?).with('FF', '41', rule).and_return(true)
|
||||
allow(engine).to receive(:zombie_os_matches_rule?).with('Windows', '7', rule).and_return(true)
|
||||
expect(engine.zombie_matches_rule?('FF', '41', 'Windows', '7', rule)).to be true
|
||||
end
|
||||
|
||||
it 'returns false when browser does not match' do
|
||||
rule = rule_with(browser: 'FF', browser_version: '>= 41', os: 'ALL', os_version: 'ALL')
|
||||
allow(engine).to receive(:zombie_browser_matches_rule?).with('FF', '41', rule).and_return(false)
|
||||
expect(engine.zombie_matches_rule?('FF', '41', 'Windows', '7', rule)).to be false
|
||||
end
|
||||
|
||||
it 'returns false when OS does not match' do
|
||||
rule = rule_with(browser: 'ALL', browser_version: 'ALL', os: 'Windows', os_version: '7')
|
||||
allow(engine).to receive(:zombie_browser_matches_rule?).with('FF', '41', rule).and_return(true)
|
||||
allow(engine).to receive(:zombie_os_matches_rule?).with('Windows', '7', rule).and_return(false)
|
||||
expect(engine.zombie_matches_rule?('FF', '41', 'Windows', '7', rule)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#zombie_os_matches_rule?' do
|
||||
it 'returns false when rule is nil' do
|
||||
expect(engine.zombie_os_matches_rule?('Windows', '7', nil)).to be false
|
||||
end
|
||||
|
||||
it 'returns true when rule os is ALL' do
|
||||
rule = double('Rule', os: 'ALL', os_version: 'ALL')
|
||||
expect(engine.zombie_os_matches_rule?('Windows', '7', rule)).to be true
|
||||
end
|
||||
|
||||
it 'returns false when hook os does not match rule os' do
|
||||
rule = double('Rule', os: 'Linux', os_version: 'ALL')
|
||||
expect(engine.zombie_os_matches_rule?('Windows', '7', rule)).to be false
|
||||
end
|
||||
|
||||
it 'returns true when rule os matches and os_version is ALL' do
|
||||
rule = double('Rule', os: 'Windows', os_version: 'ALL')
|
||||
expect(engine.zombie_os_matches_rule?('Windows', '7', rule)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#zombie_browser_matches_rule?' do
|
||||
it 'returns false when rule is nil' do
|
||||
expect(engine.zombie_browser_matches_rule?('FF', '41', nil)).to be false
|
||||
end
|
||||
|
||||
it 'returns true when rule browser is ALL and version is ALL' do
|
||||
rule = double('Rule', browser: 'ALL', browser_version: 'ALL')
|
||||
expect(engine.zombie_browser_matches_rule?('FF', '41', rule)).to be true
|
||||
end
|
||||
|
||||
it 'returns true when rule browser matches and version is ALL' do
|
||||
rule = double('Rule', browser: 'FF', browser_version: 'ALL')
|
||||
expect(engine.zombie_browser_matches_rule?('FF', '41', rule)).to be true
|
||||
end
|
||||
|
||||
it 'returns false when rule browser does not match' do
|
||||
rule = double('Rule', browser: 'IE', browser_version: 'ALL')
|
||||
expect(engine.zombie_browser_matches_rule?('FF', '41', rule)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_matching_rules_for_zombie' do
|
||||
it 'returns nil when no rules exist' do
|
||||
allow(BeEF::Core::Models::Rule).to receive(:all).and_return([])
|
||||
expect(engine.find_matching_rules_for_zombie('FF', '41', 'Windows', '7')).to be_nil
|
||||
end
|
||||
|
||||
it 'returns matching rule ids when rules match zombie' do
|
||||
rule1 = double('Rule', id: 1, name: 'Rule1', browser: 'ALL', browser_version: 'ALL', os: 'ALL', os_version: 'ALL')
|
||||
rule2 = double('Rule', id: 2, name: 'Rule2', browser: 'IE', browser_version: 'ALL', os: 'ALL', os_version: 'ALL')
|
||||
allow(BeEF::Core::Models::Rule).to receive(:all).and_return([rule1, rule2])
|
||||
allow(engine).to receive(:zombie_matches_rule?).with('FF', '41', 'Windows', '7', rule1).and_return(true)
|
||||
allow(engine).to receive(:zombie_matches_rule?).with('FF', '41', 'Windows', '7', rule2).and_return(false)
|
||||
expect(engine.find_matching_rules_for_zombie('FF', '41', 'Windows', '7')).to eq([1])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#compare_versions' do
|
||||
it 'returns true when cond is ALL' do
|
||||
expect(engine.send(:compare_versions, '7', 'ALL', '8')).to be true
|
||||
end
|
||||
|
||||
it 'returns true when cond is == and versions equal' do
|
||||
expect(engine.send(:compare_versions, '41', '==', '41')).to be true
|
||||
end
|
||||
|
||||
it 'returns false when cond is == and versions differ' do
|
||||
expect(engine.send(:compare_versions, '41', '==', '42')).to be false
|
||||
end
|
||||
|
||||
it 'returns true when cond is <= and ver_a <= ver_b' do
|
||||
expect(engine.send(:compare_versions, '41', '<=', '42')).to be true
|
||||
expect(engine.send(:compare_versions, '41', '<=', '41')).to be true
|
||||
end
|
||||
|
||||
it 'returns false when cond is <= and ver_a > ver_b' do
|
||||
expect(engine.send(:compare_versions, '42', '<=', '41')).to be false
|
||||
end
|
||||
|
||||
it 'returns true when cond is < and ver_a < ver_b' do
|
||||
expect(engine.send(:compare_versions, '41', '<', '42')).to be true
|
||||
end
|
||||
|
||||
it 'returns false when cond is < and ver_a >= ver_b' do
|
||||
expect(engine.send(:compare_versions, '42', '<', '41')).to be false
|
||||
expect(engine.send(:compare_versions, '41', '<', '41')).to be false
|
||||
end
|
||||
|
||||
it 'returns true when cond is >= and ver_a >= ver_b' do
|
||||
expect(engine.send(:compare_versions, '42', '>=', '41')).to be true
|
||||
expect(engine.send(:compare_versions, '41', '>=', '41')).to be true
|
||||
end
|
||||
|
||||
it 'returns true when cond is > and ver_a > ver_b' do
|
||||
expect(engine.send(:compare_versions, '42', '>', '41')).to be true
|
||||
end
|
||||
|
||||
it 'returns false when cond is > and ver_a <= ver_b' do
|
||||
expect(engine.send(:compare_versions, '41', '>', '42')).to be false
|
||||
expect(engine.send(:compare_versions, '41', '>', '41')).to be false
|
||||
end
|
||||
|
||||
it 'returns false for unknown cond' do
|
||||
expect(engine.send(:compare_versions, '41', '!=', '42')).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clean_command_body' do
|
||||
it 'extracts body range and replaces single-quoted mod_input when replace_input is true' do
|
||||
body = "beef.execute(function(){\n alert('<<mod_input>>');\n});\n"
|
||||
result = engine.send(:clean_command_body, body, true)
|
||||
expect(result).to include('alert(mod_input)')
|
||||
expect(result).to include('beef.execute(function(){')
|
||||
end
|
||||
|
||||
it 'returns cleaned body without mod_input replacement when replace_input is false' do
|
||||
body = "beef.execute(function(){\n doSomething('<<mod_input>>');\n});\n"
|
||||
result = engine.send(:clean_command_body, body, false)
|
||||
expect(result).to include('<<mod_input>>')
|
||||
end
|
||||
|
||||
it 'replaces double-quoted <<mod_input>> with mod_input when replace_input is true' do
|
||||
body = "beef.execute(function(){\n x(\"<<mod_input>>\");\n});\n"
|
||||
result = engine.send(:clean_command_body, body, true)
|
||||
expect(result).to include('mod_input')
|
||||
expect(result).not_to include('"<<mod_input>>"')
|
||||
end
|
||||
|
||||
it 'replaces single-quoted <<mod_input>> with mod_input when replace_input is true' do
|
||||
body = "beef.execute(function(){\n x('<<mod_input>>');\n});\n"
|
||||
result = engine.send(:clean_command_body, body, true)
|
||||
expect(result).to include('mod_input')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#prepare_sequential_wrapper' do
|
||||
it 'builds wrapper with mod bodies and setTimeout calls in order' do
|
||||
mods = [
|
||||
{ mod_name: 'mod_a', mod_body: 'var mod_a_mod_output = 1;' },
|
||||
{ mod_name: 'mod_b', mod_body: 'var mod_b_mod_output = 2;' }
|
||||
]
|
||||
order = [0, 1]
|
||||
delay = [0, 500]
|
||||
token = 't1'
|
||||
result = engine.send(:prepare_sequential_wrapper, mods, order, delay, token)
|
||||
expect(result).to include('mod_a_t1')
|
||||
expect(result).to include('mod_b_t1')
|
||||
expect(result).to include('setTimeout(function(){mod_a_t1();}, 0)')
|
||||
expect(result).to include('setTimeout(function(){mod_b_t1();}, 500)')
|
||||
expect(result).to include('mod_a_t1_mod_output')
|
||||
expect(result).to include('mod_b_t1_mod_output')
|
||||
end
|
||||
|
||||
it 'handles single module' do
|
||||
mods = [{ mod_name: 'single', mod_body: 'x();' }]
|
||||
order = [0]
|
||||
delay = [0]
|
||||
result = engine.send(:prepare_sequential_wrapper, mods, order, delay, 'tk')
|
||||
expect(result).to include('single_tk')
|
||||
expect(result).to include('setTimeout(function(){single_tk();}, 0)')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#prepare_nested_forward_wrapper' do
|
||||
it 'builds wrapper for single module' do
|
||||
mods = [{ mod_name: 'only', mod_body: 'only();' }]
|
||||
code = ['null']
|
||||
conditions = [true]
|
||||
order = [0]
|
||||
token = 'nf1'
|
||||
result = engine.send(:prepare_nested_forward_wrapper, mods, code, conditions, order, token)
|
||||
expect(result).to include('only_nf1')
|
||||
expect(result).to include('only_nf1_f')
|
||||
expect(result).to include('only_nf1_mod_output')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_and_run_all_matching_rules_for_zombie' do
|
||||
it 'returns without calling run_rules when hb_id is nil' do
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.find_and_run_all_matching_rules_for_zombie(nil)
|
||||
end
|
||||
|
||||
it 'returns without calling run_rules when find_matching_rules returns nil' do
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.name').and_return('FF')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.version').and_return('41')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.name').and_return('Windows')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.version').and_return('7')
|
||||
allow(engine).to receive(:find_matching_rules_for_zombie).with('FF', '41', 'Windows', '7').and_return(nil)
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.find_and_run_all_matching_rules_for_zombie(1)
|
||||
end
|
||||
|
||||
it 'returns without calling run_rules when find_matching_rules returns empty' do
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.name').and_return('FF')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.version').and_return('41')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.name').and_return('Windows')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.version').and_return('7')
|
||||
allow(engine).to receive(:find_matching_rules_for_zombie).with('FF', '41', 'Windows', '7').and_return([])
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.find_and_run_all_matching_rules_for_zombie(1)
|
||||
end
|
||||
|
||||
it 'calls run_rules_on_zombie with matching rule ids when rules match' do
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.name').and_return('FF')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.version').and_return('41')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.name').and_return('Windows')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.version').and_return('7')
|
||||
allow(engine).to receive(:find_matching_rules_for_zombie).with('FF', '41', 'Windows', '7').and_return([1, 2])
|
||||
expect(engine).to receive(:run_rules_on_zombie).with([1, 2], 1)
|
||||
engine.find_and_run_all_matching_rules_for_zombie(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#run_matching_rules_on_zombie' do
|
||||
it 'returns when rule_ids is nil' do
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.run_matching_rules_on_zombie(nil, 1)
|
||||
end
|
||||
|
||||
it 'returns when hb_id is nil' do
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.run_matching_rules_on_zombie([1], nil)
|
||||
end
|
||||
|
||||
it 'returns without calling run_rules when find_matching_rules returns nil' do
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.name').and_return('FF')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.version').and_return('41')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.name').and_return('Windows')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.version').and_return('7')
|
||||
allow(engine).to receive(:find_matching_rules_for_zombie).with('FF', '41', 'Windows', '7').and_return(nil)
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.run_matching_rules_on_zombie([1], 1)
|
||||
end
|
||||
|
||||
it 'calls run_rules_on_zombie with intersection of rule_ids and matching rules' do
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.name').and_return('FF')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.version').and_return('41')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.name').and_return('Windows')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.version').and_return('7')
|
||||
allow(engine).to receive(:find_matching_rules_for_zombie).with('FF', '41', 'Windows', '7').and_return([1, 2])
|
||||
expect(engine).to receive(:run_rules_on_zombie).with([1], 1)
|
||||
engine.run_matching_rules_on_zombie([1], 1)
|
||||
end
|
||||
|
||||
it 'does not call run_rules_on_zombie when no rule_ids overlap matching rules' do
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.name').and_return('FF')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'browser.version').and_return('41')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.name').and_return('Windows')
|
||||
allow(BeEF::Core::Models::BrowserDetails).to receive(:get).with(1, 'host.os.version').and_return('7')
|
||||
allow(engine).to receive(:find_matching_rules_for_zombie).with('FF', '41', 'Windows', '7').and_return([1, 2])
|
||||
expect(engine).not_to receive(:run_rules_on_zombie)
|
||||
engine.run_matching_rules_on_zombie([99], 1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#run_rules_on_zombie' do
|
||||
it 'returns when rule_ids is nil' do
|
||||
expect(BeEF::HBManager).not_to receive(:get_by_id)
|
||||
engine.run_rules_on_zombie(nil, 1)
|
||||
end
|
||||
|
||||
it 'returns when hb_id is nil' do
|
||||
expect(BeEF::HBManager).not_to receive(:get_by_id)
|
||||
engine.run_rules_on_zombie([1], nil)
|
||||
end
|
||||
|
||||
it 'normalizes single Integer rule_id to array and processes rule' do
|
||||
hb = double('HookedBrowser', session: 'sess1')
|
||||
allow(BeEF::HBManager).to receive(:get_by_id).with(1).and_return(hb)
|
||||
rule = double(
|
||||
'Rule',
|
||||
modules: '[]',
|
||||
execution_order: '[]',
|
||||
execution_delay: '[]',
|
||||
chain_mode: 'invalid'
|
||||
)
|
||||
allow(BeEF::Core::Models::Rule).to receive(:find).with(1).and_return(rule)
|
||||
engine.run_rules_on_zombie(1, 1)
|
||||
expect(BeEF::Core::Models::Rule).to have_received(:find).with(1)
|
||||
expect(engine).to have_received(:print_error).with(/Invalid chain mode 'invalid'/)
|
||||
end
|
||||
|
||||
it 'prints error and returns when rule has invalid chain_mode' do
|
||||
hb = double('HookedBrowser', session: 'sess1')
|
||||
allow(BeEF::HBManager).to receive(:get_by_id).with(1).and_return(hb)
|
||||
rule = double(
|
||||
'Rule',
|
||||
modules: '[]',
|
||||
execution_order: '[]',
|
||||
execution_delay: '[]',
|
||||
chain_mode: 'invalid'
|
||||
)
|
||||
allow(BeEF::Core::Models::Rule).to receive(:find).with(1).and_return(rule)
|
||||
engine.run_rules_on_zombie([1], 1)
|
||||
expect(engine).to have_received(:print_error).with(/Invalid chain mode 'invalid'/)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,119 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BeEF::Core::AutorunEngine::Parser do
|
||||
let(:parser) { described_class.instance }
|
||||
|
||||
def valid_minimal_args
|
||||
{
|
||||
name: 'Test Rule',
|
||||
author: 'Test Author',
|
||||
browser: 'ALL',
|
||||
browser_version: 'ALL',
|
||||
os: 'Windows',
|
||||
os_version: 'ALL',
|
||||
modules: [],
|
||||
execution_order: [],
|
||||
execution_delay: [],
|
||||
chain_mode: 'sequential'
|
||||
}
|
||||
end
|
||||
|
||||
describe '#parse' do
|
||||
it 'returns true for valid minimal args (empty modules)' do
|
||||
result = parser.parse(
|
||||
valid_minimal_args[:name],
|
||||
valid_minimal_args[:author],
|
||||
valid_minimal_args[:browser],
|
||||
valid_minimal_args[:browser_version],
|
||||
valid_minimal_args[:os],
|
||||
valid_minimal_args[:os_version],
|
||||
valid_minimal_args[:modules],
|
||||
valid_minimal_args[:execution_order],
|
||||
valid_minimal_args[:execution_delay],
|
||||
valid_minimal_args[:chain_mode]
|
||||
)
|
||||
|
||||
expect(result).to be true
|
||||
end
|
||||
|
||||
it 'raises ArgumentError for empty name' do
|
||||
expect do
|
||||
parser.parse('', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [], [], [], 'sequential')
|
||||
end.to raise_error(ArgumentError, /Invalid rule name/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError for nil name' do
|
||||
expect do
|
||||
parser.parse(nil, 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [], [], [], 'sequential')
|
||||
end.to raise_error(ArgumentError, /Invalid rule name/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError for empty author' do
|
||||
expect do
|
||||
parser.parse('Name', '', 'ALL', 'ALL', 'Windows', 'ALL', [], [], [], 'sequential')
|
||||
end.to raise_error(ArgumentError, /Invalid author name/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError for invalid chain_mode' do
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [], [], [], 'invalid')
|
||||
end.to raise_error(ArgumentError, /Invalid chain_mode definition/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError for invalid os' do
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'ALL', 'ALL', 'InvalidOS', 'ALL', [], [], [], 'sequential')
|
||||
end.to raise_error(ArgumentError, /Invalid os definition/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError when execution_delay size does not match modules size' do
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [{ 'name' => 'a' }], [1], [], 'sequential')
|
||||
end.to raise_error(ArgumentError, /execution_delay.*consistent with number of modules/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError when execution_order size does not match modules size' do
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [{ 'name' => 'a' }], [], [0], 'sequential')
|
||||
end.to raise_error(ArgumentError, /execution_order.*consistent with number of modules/)
|
||||
end
|
||||
|
||||
it 'raises TypeError when execution_delay contains non-Integer' do
|
||||
# Use one module so sizes match; then type check runs on execution_delay
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [{}], [1], ['not_an_int'], 'sequential')
|
||||
end.to raise_error(TypeError, /execution_delay.*Integers/)
|
||||
end
|
||||
|
||||
it 'raises TypeError when execution_order contains non-Integer' do
|
||||
# Use one module so sizes match; then type check runs on execution_order
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [{}], ['x'], [0], 'sequential')
|
||||
end.to raise_error(TypeError, /execution_order.*Integers/)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError for invalid browser' do
|
||||
expect do
|
||||
parser.parse('Name', 'Author', 'XX', 'ALL', 'Windows', 'ALL', [], [], [], 'sequential')
|
||||
end.to raise_error(ArgumentError, /Invalid browser definition/)
|
||||
end
|
||||
|
||||
it 'accepts nested-forward as chain_mode' do
|
||||
result = parser.parse('Name', 'Author', 'ALL', 'ALL', 'Windows', 'ALL', [], [], [], 'nested-forward')
|
||||
expect(result).to be true
|
||||
end
|
||||
|
||||
it 'accepts valid os values' do
|
||||
%w[Linux Windows OSX Android iOS BlackBerry ALL].each do |os|
|
||||
result = parser.parse('Name', 'Author', 'ALL', 'ALL', os, 'ALL', [], [], [], 'sequential')
|
||||
expect(result).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,83 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2006-2026 Wade Alcorn - wade@bindshell.net
|
||||
# Browser Exploitation Framework (BeEF) - https://beefproject.com
|
||||
# See the file 'doc/COPYING' for copying permission
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BeEF::Core::AutorunEngine::RuleLoader do
|
||||
let(:loader) { described_class.instance }
|
||||
|
||||
def valid_rule_data
|
||||
{
|
||||
'name' => 'Test Rule',
|
||||
'author' => 'Test Author',
|
||||
'browser' => 'ALL',
|
||||
'browser_version' => 'ALL',
|
||||
'os' => 'Windows',
|
||||
'os_version' => 'ALL',
|
||||
'modules' => [],
|
||||
'execution_order' => [],
|
||||
'execution_delay' => [],
|
||||
'chain_mode' => 'sequential'
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
allow(loader).to receive(:print_error)
|
||||
allow(loader).to receive(:print_info)
|
||||
allow(loader).to receive(:print_more)
|
||||
end
|
||||
|
||||
describe '#load_rule_json' do
|
||||
it 'returns success and rule_id when parse succeeds and rule is new' do
|
||||
# Parser will succeed with valid minimal data; no existing rule
|
||||
result = loader.load_rule_json(valid_rule_data)
|
||||
|
||||
expect(result['success']).to be true
|
||||
expect(result).to have_key('rule_id')
|
||||
expect(result['rule_id']).to be_a(Integer)
|
||||
end
|
||||
|
||||
it 'returns success false and error when parse raises' do
|
||||
allow(BeEF::Core::AutorunEngine::Parser.instance).to receive(:parse).and_raise(ArgumentError.new('Invalid rule name'))
|
||||
|
||||
result = loader.load_rule_json(valid_rule_data.merge('name' => 'x'))
|
||||
|
||||
expect(result['success']).to be false
|
||||
expect(result['error']).to include('Invalid rule name')
|
||||
end
|
||||
|
||||
it 'returns success false and error when rule already exists' do
|
||||
# Create the rule first so it already exists
|
||||
BeEF::Core::Models::Rule.create!(
|
||||
name: 'Duplicate Rule',
|
||||
author: 'Test Author',
|
||||
browser: 'ALL',
|
||||
browser_version: 'ALL',
|
||||
os: 'Windows',
|
||||
os_version: 'ALL',
|
||||
modules: [].to_json,
|
||||
execution_order: [].to_s,
|
||||
execution_delay: [].to_s,
|
||||
chain_mode: 'sequential'
|
||||
)
|
||||
|
||||
result = loader.load_rule_json(
|
||||
valid_rule_data.merge('name' => 'Duplicate Rule')
|
||||
)
|
||||
|
||||
expect(result['success']).to be false
|
||||
expect(result['error']).to include('Duplicate rule already exists')
|
||||
end
|
||||
|
||||
it 'uses default chain_mode sequential when missing' do
|
||||
data = valid_rule_data.except('chain_mode')
|
||||
result = loader.load_rule_json(data)
|
||||
|
||||
expect(result['success']).to be true
|
||||
expect(result).to have_key('rule_id')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -111,7 +111,6 @@ RSpec.describe BeEF::Core::Handlers::HookedBrowsers do
|
||||
relation = double('Relation', first: hooked_browser)
|
||||
allow(BeEF::Core::Models::HookedBrowser).to receive(:where).with(session: 'existing_session').and_return(relation)
|
||||
allow(BeEF::Core::Models::Command).to receive(:where).with(hooked_browser_id: 1, instructions_sent: false).and_return([])
|
||||
allow(BeEF::Core::Models::Execution).to receive(:where).with(is_sent: false, session_id: 'existing_session').and_return([])
|
||||
allow(BeEF::API::Registrar.instance).to receive(:fire)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user