| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 | package nodejsimport (	_ "embed"	"encoding/base64"	"fmt"	"os"	"os/exec"	"path"	"strconv"	"strings"	"time"	"github.com/langgenius/dify-sandbox/internal/core/runner"	"github.com/langgenius/dify-sandbox/internal/core/runner/types"	"github.com/langgenius/dify-sandbox/internal/static")type NodeJsRunner struct {	runner.TempDirRunner}//go:embed prescript.jsvar nodejs_sandbox_fs []bytevar (	REQUIRED_FS = []string{		path.Join(LIB_PATH, PROJECT_NAME, "node_temp"),		path.Join(LIB_PATH, LIB_NAME),		"/etc/ssl/certs/ca-certificates.crt",		"/etc/nsswitch.conf",		"/etc/resolv.conf",		"/run/systemd/resolve/stub-resolv.conf",		"/etc/hosts",	})func (p *NodeJsRunner) Run(	code string,	timeout time.Duration,	stdin []byte,	preload string,	options *types.RunnerOptions,) (chan []byte, chan []byte, chan bool, error) {	configuration := static.GetDifySandboxGlobalConfigurations()	// capture the output	output_handler := runner.NewOutputCaptureRunner()	output_handler.SetTimeout(timeout)	err := p.WithTempDir("/", REQUIRED_FS, func(root_path string) error {		output_handler.SetAfterExitHook(func() {			os.RemoveAll(root_path)			os.Remove(root_path)		})		// initialize the environment		script_path, err := p.InitializeEnvironment(code, preload, root_path)		if err != nil {			return err		}		// create a new process		cmd := exec.Command(			static.GetDifySandboxGlobalConfigurations().NodejsPath,			script_path,			strconv.Itoa(static.SANDBOX_USER_UID),			strconv.Itoa(static.SANDBOX_GROUP_ID),			options.Json(),		)		cmd.Env = []string{}		if len(configuration.AllowedSyscalls) > 0 {			cmd.Env = append(				cmd.Env,				fmt.Sprintf("ALLOWED_SYSCALLS=%s", strings.Trim(					strings.Join(strings.Fields(fmt.Sprint(configuration.AllowedSyscalls)), ","), "[]",				)),			)		}		// capture the output		err = output_handler.CaptureOutput(cmd)		if err != nil {			return err		}		return nil	})	if err != nil {		return nil, nil, nil, err	}	return output_handler.GetStdout(), output_handler.GetStderr(), output_handler.GetDone(), nil}func (p *NodeJsRunner) InitializeEnvironment(code string, preload string, root_path string) (string, error) {	if !checkLibAvaliable() {		releaseLibBinary()	}	node_sandbox_file := string(nodejs_sandbox_fs)	if preload != "" {		node_sandbox_file = fmt.Sprintf("%s\n%s", preload, node_sandbox_file)	}	// join nodejs_sandbox_fs and code	// encode code with base64	code = base64.StdEncoding.EncodeToString([]byte(code))	// FIXE: redeclared function causes code injection	evalCode := fmt.Sprintf("eval(Buffer.from('%s', 'base64').toString('utf-8'))", code)	code = node_sandbox_file + evalCode	// override root_path/tmp/sandbox-nodejs-project/prescript.js	script_path := path.Join(root_path, LIB_PATH, PROJECT_NAME, "node_temp/node_temp/test.js")	err := os.WriteFile(script_path, []byte(code), 0755)	if err != nil {		return "", err	}	return script_path, nil}
 |