From 343d5ee6f5d65d710d8075cd329e9288846a9947 Mon Sep 17 00:00:00 2001 From: MANZI RURANGIRWA Elvis Date: Sat, 1 Nov 2025 17:24:31 +0200 Subject: [PATCH] Disabling inspector element --- package.json | 4 ++- scripts/README.md | 0 scripts/obfuscate.js | 59 ++++++++++++++++++++++++++++++++++++++++ server.js | 28 +++++++++++++++++++ src/utils/antiInspect.js | 38 ++++++++++++++++++++++++++ tsconfig.json | 2 +- 6 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 scripts/README.md create mode 100644 scripts/obfuscate.js create mode 100644 server.js create mode 100644 src/utils/antiInspect.js diff --git a/package.json b/package.json index 284696840..1672b2691 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "build": "webpack --mode production", "test": "jest", "lint": "eslint src", - "scan-translations": "pnpx jest ./tests/i18nScan.test.js" + "scan-translations": "pnpx jest ./tests/i18nScan.test.js", + "build:all": "npm run build && echo Build complete && echo Obfuscating... && node scripts/obfuscate.js", + "serve": "node server.js" }, "dependencies": { "@babel/runtime": "7.26.0", diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/obfuscate.js b/scripts/obfuscate.js new file mode 100644 index 000000000..78a2befff --- /dev/null +++ b/scripts/obfuscate.js @@ -0,0 +1,59 @@ +const fs = require('fs'); +const path = require('path'); +const JavaScriptObfuscator = require('javascript-obfuscator'); + +const INPUT_DIR = path.join(__dirname, '..', 'dist'); +const OUTPUT_DIR = path.join(__dirname, '..', 'dist-obf'); + +function ensureDir(dir) { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); +} + +function obfuscateFileContents(sourcePath, destPath) { + const code = fs.readFileSync(sourcePath, 'utf8'); + const obf = JavaScriptObfuscator.obfuscate(code, { + compact: true, + controlFlowFlattening: true, + controlFlowFlatteningThreshold: 0.75, + deadCodeInjection: true, + deadCodeInjectionThreshold: 0.4, + stringArray: true, + stringArrayEncoding: ['base64'], + rotateStringArray: true, + stringArrayThreshold: 0.75, + }); + fs.writeFileSync(destPath, obf.getObfuscatedCode(), 'utf8'); +} + +function copyAndObfuscate(srcDir, destDir) { + ensureDir(destDir); + for (const name of fs.readdirSync(srcDir)) { + const srcPath = path.join(srcDir, name); + const destPath = path.join(destDir, name); + const stat = fs.statSync(srcPath); + if (stat.isDirectory()) { + copyAndObfuscate(srcPath, destPath); + } else { + if (name.endsWith('.js')) { + obfuscateFileContents(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); + } + } + } +} + +try { + if (!fs.existsSync(INPUT_DIR)) { + console.error('Input dist folder not found. Run `npm run build` first.'); + process.exit(1); + } + if (fs.existsSync(OUTPUT_DIR)) { + fs.rmSync(OUTPUT_DIR, { recursive: true, force: true }); + } + copyAndObfuscate(INPUT_DIR, OUTPUT_DIR); + console.log('Obfuscated build written to:', OUTPUT_DIR); +} catch (err) { + console.error('Obfuscation failed', err); + process.exit(1); +} diff --git a/server.js b/server.js new file mode 100644 index 000000000..23ab84945 --- /dev/null +++ b/server.js @@ -0,0 +1,28 @@ +const express = require('express'); +const helmet = require('helmet'); +const path = require('path'); + +const app = express(); +const PORT = process.env.PORT || 3000; +const DIST = path.join(__dirname, 'dist-obf'); +// Security middleware +app.use(helmet()); +app.use(helmet.contentSecurityPolicy({ + directives: { + defaultSrc: ["'self'"], + scriptSrc: ["'self'"], + styleSrc: ["'self'", "'unsafe-inline'"], + imgSrc: ["'self'", 'data:'], + connectSrc: ["'self'"], + } +})); + +app.use(express.static(DIST)); + +app.get('*', (req, res) => { + res.sendFile(path.join(DIST, 'index.html')); +}); + +app.listen(PORT, () => { + console.log(`Server running on http://localhost:${PORT}`); +}); diff --git a/src/utils/antiInspect.js b/src/utils/antiInspect.js new file mode 100644 index 000000000..719c2cb75 --- /dev/null +++ b/src/utils/antiInspect.js @@ -0,0 +1,38 @@ +function disableShortcuts() { + document.addEventListener('contextmenu', (e) => e.preventDefault()); + document.addEventListener('keydown', (e) => { + if ( + e.key === 'F12' || + (e.ctrlKey && e.shiftKey && (e.key === 'I' || e.key === 'C' || e.key === 'J')) || + (e.ctrlKey && e.key === 'u') + ) { + e.preventDefault(); + e.stopPropagation(); + } + }, { capture: true }); +} + +function detectDevTools(onDetect = () => {}) { + let last = new Date().getTime(); + setInterval(() => { + const t0 = new Date().getTime(); + debugger; + const t1 = new Date().getTime(); + if (t1 - t0 > 100) { + onDetect(); + } + last = t1; + }, 1000); +} + +export function initAntiInspect() { + try { + disableShortcuts(); + detectDevTools(() => { + console.warn('Developer tools detected — reloading page.'); + window.location.reload(); + }); + } catch (e) { + // fail silently + } +} diff --git a/tsconfig.json b/tsconfig.json index c4b0a8626..18264e80d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,6 @@ "strict": true, }, "include": [ - "src/", + "src/", "scripts", ] }