plugins-evert/debug/plugin.ts

118 lines
3.3 KiB
TypeScript

import util from 'util';
import cprog from 'child_process';
import {
Plugin,
Configurable,
EventListener,
DependencyLoad
} from '@squeebot/core/lib/plugin';
import { IMessage, MessageResolver } from '@squeebot/core/lib/types';
import { ISqueebotCore, logger } from '@squeebot/core/lib/core';
function addCommands(plugin: UtilityPlugin, commands: any): void {
const cmds = [{
plugin: plugin.manifest.name,
name: 'evaljs',
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
if (!simplified[0]) {
return true;
}
const script = simplified.join(' ');
// Disallow child_process when shell is disallowed
if ((script.indexOf('child_process') !== -1 ||
script.indexOf('cprog') !== -1 ||
script.indexOf('fork') !== -1) &&
!plugin.config.config.allowShell) {
msg.resolve('Error: child_process is not allowed in evaljs due to security reasons.');
return true;
}
try {
// tslint:disable-next-line: no-eval
const mesh = eval(script);
if (mesh === undefined) {
return true;
}
msg.resolve(util.format(mesh));
} catch (e: any) {
msg.resolve('Error: ' + e.message);
}
return true;
},
usage: '<javascript>',
description: 'Execute JavaScript in a command context',
permissions: ['system_execute'],
hidden: true
}];
if (plugin.config.config.allowShell) {
logger.warn('WARNING! Shell command execution is enabled! Make absolutely sure that there is proper authentication!');
if (process.getuid && process.getuid() === 0) {
logger.warn('NEVER run Squeebot as root! Run `useradd squeebot`! We are not responsible for possible security leaks!');
}
cmds.push({
plugin: plugin.manifest.name,
name: 'sh',
execute: async (msg: IMessage, msr: MessageResolver, spec: any, prefix: string, ...simplified: any[]): Promise<boolean> => {
const stripnl = (simplified[0] !== '-n');
const cmd = simplified.slice(stripnl ? 0 : 1).join(' ');
if (!cmd) {
msg.resolve('Nothing to execute!');
return true;
}
cprog.exec(cmd, {shell: '/bin/bash'}, (error, stdout, stderr) => {
if (stdout) {
if (stripnl) { stdout = stdout.replace(/\n/g, ' ;; '); }
return msg.resolve(stdout);
}
msg.resolve('Error executing command.');
logger.error(stderr || error);
});
return true;
},
description: 'Run raw shell command',
usage: '<shell>',
hidden: true,
permissions: ['system_shell'],
});
}
commands.registerCommand(cmds);
}
@Configurable({
allowShell: false,
})
class UtilityPlugin extends Plugin {
public core: ISqueebotCore | null = null;
@DependencyLoad('simplecommands')
addCommands(cmd: any): void {
addCommands(this, cmd);
}
@EventListener('pluginUnload')
public unloadEventHandler(plugin: string | Plugin): void {
if (plugin === this.name || plugin === this) {
this.emit('pluginUnloaded', this);
}
}
initialize(): void {
this.on('core', (c: ISqueebotCore) => this.core = c);
this.emitTo('core', 'request-core', this.name);
}
}
module.exports = UtilityPlugin;