Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
github.com/congop/execstub
Package execstub provides stubbing for a usage of a command line API which is based on an executable discovered using the environment or some sort of + configuration. An example of command line api usage is:
cmd := exec.Command("genisoimage", "-output", cloudInitPath, "-V", "cidata", "-joliet", "-rock", nocloudDir)
stdInOutBytes, err := cmd.CombinedOutput()
Please check out Execstub package doc for more details about the concepts being used.
go get github.com/congop/execstub
Read the package documentation for more information.
import (
"bytes"
"fmt"
"os"
"os/exec"
"reflect"
"testing"
rt "github.com/congop/execstub/internal/runtime"
"github.com/congop/execstub/pkg/comproto"
)
func Example_dynamicDefaultSettings() {
stubber := NewExecStubber()
defer stubber.CleanUp()
staticOutcome := comproto.ExecOutcome{
Stderr: "err1",
Stdout: "sout1",
ExitCode: 0,
}
recStubFunc, reqStore := comproto.RecordingExecutions(
comproto.AdaptOutcomeToCmdStub(&staticOutcome))
key, err := stubber.WhenExecDoStubFunc(recStubFunc, rt.EnsureHasExecExt("SuperExe"), comproto.Settings{})
ifNotEqPanic(nil, err, "fail to setup stub")
cmd := exec.Command("SuperExe", "arg1", "argb")
var bufStderr, bufStdout bytes.Buffer
cmd.Stderr = &bufStderr
cmd.Stdout = &bufStdout
err = cmd.Run()
ifNotEqPanic(nil, err, "should have hat successful execution")
// accessing and checking stubrequest dynymic mode
gotRequests := *reqStore
wanRequets := []comproto.StubRequest{
{
CmdName: rt.EnsureHasExecExt("SuperExe"), Args: []string{"arg1", "argb"}, Key: key,
},
}
ifNotEqPanic(wanRequets, gotRequests, "unexpected stub requests")
// accessing and checking outcome
gotStderr := bufStderr.String()
ifNotEqPanic(staticOutcome.Stderr, gotStderr, "unexpected stderr")
gotStdout := bufStdout.String()
ifNotEqPanic(staticOutcome.Stdout, gotStdout, "unexpected stdout")
gotExitCode := cmd.ProcessState.ExitCode()
ifNotEqPanic(int(staticOutcome.ExitCode), gotExitCode, "unexpected exec exit code")
// Output:
}
// used as test process help Settings{TestHelperProcessMethodName: "TestHelperProcExample_dynamic"}
func TestHelperProcExample_dynamic(t *testing.T) {
comproto.EffectuateConfiguredExecOutcome(nil)
}
func Example_dynamicWithTestHelperProc() {
stubber := NewExecStubber()
defer stubber.CleanUp()
staticOutcome := comproto.ExecOutcome{
Stderr: "",
Stdout: `REPOSITORY:TAG
golang:1.14
golang:latest
golang:1.14-alpine3.12
ubuntu:18.04`,
ExitCode: 0,
}
recStubFunc, reqStore := comproto.RecordingExecutions(
comproto.AdaptOutcomeToCmdStub(&staticOutcome))
setting := comproto.Settings{TestHelperProcessMethodName: "TestHelperProcExample_dynamic"}
key, err := stubber.WhenExecDoStubFunc(recStubFunc, rt.EnsureHasExecExt("docker"), setting)
ifNotEqPanic(nil, err, "fail to setip stub")
// args := []string{"image", "ls", "--format", "\"{{.Repository}}:{{.Tag}}\""}
args := []string{"image", "ls", "--format", "table '{{.Repository}}:{{.Tag}}'"}
cmd := exec.Command("docker", args...)
var bufStderr, bufStdout bytes.Buffer
cmd.Stderr = &bufStderr
cmd.Stdout = &bufStdout
err = cmd.Run()
ifNotEqPanic(nil, err, "exit code set to 0 ==> execution should succeed")
// accessing and checking stubrequest dynymic mode
gotRequests := *reqStore
wanRequets := []comproto.StubRequest{
{
CmdName: rt.EnsureHasExecExt("docker"), Args: args, Key: key,
},
}
ifNotEqPanic(wanRequets, gotRequests, "unexpected stub requests")
// accessing and checking outcome
gotStderr := bufStderr.String()
ifNotEqPanic(staticOutcome.Stderr, gotStderr, "unexpected stderr")
gotStdout := bufStdout.String()
ifNotEqPanic(staticOutcome.Stdout, gotStdout, "unexpected stdout")
gotExitCode := cmd.ProcessState.ExitCode()
ifNotEqPanic(int(staticOutcome.ExitCode), gotExitCode, "unexpected exec exit code")
// Output:
}
func Example_static() {
stubber := NewExecStubber()
defer stubber.CleanUp()
staticOutcome := comproto.ExecOutcome{
Stderr: "err1",
Stdout: "sout1",
ExitCode: 0,
}
recStubFunc, reqStore := comproto.RecordingExecutions(
comproto.AdaptOutcomeToCmdStub(&staticOutcome))
settings := comproto.Settings{Mode: comproto.StubbingModeStatic}
key, err := stubber.WhenExecDoStubFunc(recStubFunc, rt.EnsureHasExecExt("SuperExe"), settings)
ifNotEqPanic(nil, err, "fail to setup stub")
ifNotEqPanic(
[]comproto.StubRequest{{Key: key, CmdName: rt.EnsureHasExecExt("SuperExe"), Args: nil}},
*reqStore,
"Static mod evaluate StubFunc at setup with a stubrequest havin nil args")
*reqStore = (*reqStore)[:0]
cmd := exec.Command("SuperExe", "arg1", "argb")
var bufStderr, bufStdout bytes.Buffer
cmd.Stderr = &bufStderr
cmd.Stdout = &bufStdout
err = cmd.Run()
ifNotEqPanic(nil, err, "should have hat successful execution")
// accessing and checking stubrequest static mode
ifNotEqPanic(0, len(*reqStore), "Unexpected StubFunc call in static mode")
gotRequests, err := stubber.FindAllPersistedStubRequests(key)
ifNotEqPanic(nil, err, "fail to find all persisted stub request")
wanRequets := []comproto.StubRequest{
{
CmdName: rt.EnsureHasExecExt("SuperExe"), Args: []string{"arg1", "argb"}, Key: key,
},
}
ifNotEqPanic(wanRequets, *gotRequests, "unexpected stub requests")
// accessing and checking outcome
gotStderr := bufStderr.String()
ifNotEqPanic(staticOutcome.Stderr, gotStderr, "unexpected stderr")
gotStdout := bufStdout.String()
ifNotEqPanic(staticOutcome.Stdout, gotStdout, "unexpected stdout")
gotExitCode := cmd.ProcessState.ExitCode()
ifNotEqPanic(int(staticOutcome.ExitCode), gotExitCode, "unexpected exec exit code")
// Output:
}
// TestHelperProcExample_static is used as test process help .
// Configured wihh: Settings{TestHelperProcessMethodName: "TestHelperProcExample_static"}
func TestHelperProcExample_static(t *testing.T) {
extraJobOnStubRequest := func(req comproto.StubRequest) error {
// some extrat side effect
// we are adding to stdout
fmt.Print("extra_side_effect_")
return nil
}
comproto.EffectuateConfiguredExecOutcome(extraJobOnStubRequest)
}
func Example_staticWithTestHelperProc() {
stubber := NewExecStubber()
defer stubber.CleanUp()
staticOutcome := comproto.ExecOutcome{
Stderr: "err1",
Stdout: "sout1",
ExitCode: 0,
}
recStubFunc, reqStore := comproto.RecordingExecutions(
comproto.AdaptOutcomeToCmdStub(&staticOutcome))
settings := comproto.Settings{
Mode: comproto.StubbingModeStatic,
TestHelperProcessMethodName: "TestHelperProcExample_static",
}
key, err := stubber.WhenExecDoStubFunc(recStubFunc, rt.EnsureHasExecExt("SuperExe"), settings)
ifNotEqPanic(nil, err, "fail to setip stub")
ifNotEqPanic(
[]comproto.StubRequest{{Key: key, CmdName: rt.EnsureHasExecExt("SuperExe"), Args: nil}},
*reqStore,
"Static mod evaluate StubFunc at setup with stubrequest having nil args")
*reqStore = (*reqStore)[:0]
cmd := exec.Command("SuperExe", "arg1", "argb")
var bufStderr, bufStdout bytes.Buffer
cmd.Stderr = &bufStderr
cmd.Stdout = &bufStdout
err = cmd.Run()
ifNotEqPanic(nil, err, "should have hat successful execution")
// accessing and checking stubrequest static mode
ifNotEqPanic(0, len(*reqStore), "Unexpected StubFunc call in static mode")
gotRequests, err := stubber.FindAllPersistedStubRequests(key)
ifNotEqPanic(nil, err, "fail to find all persisted stub request")
wanRequets := []comproto.StubRequest{
{
CmdName: rt.EnsureHasExecExt("SuperExe"), Args: []string{"arg1", "argb"}, Key: key,
},
}
ifNotEqPanic(wanRequets, *gotRequests, "unexpected stub requests")
// accessing and checking outcome
gotStderr := bufStderr.String()
ifNotEqPanic(staticOutcome.Stderr, gotStderr, "unexpected stderr")
gotStdout := bufStdout.String()
ifNotEqPanic("extra_side_effect_"+staticOutcome.Stdout, gotStdout, "unexpected stdout")
gotExitCode := cmd.ProcessState.ExitCode()
ifNotEqPanic(int(staticOutcome.ExitCode), gotExitCode, "unexpected exec exit code")
// Output:
}
func Example_homeBinDir() {
stubber := NewExecStubber()
defer stubber.CleanUp()
staticOutcome := comproto.ExecOutcome{
Stderr: "",
Stdout: "%s openjdk version \"11.x.x\" 2020-mm-dd",
ExitCode: 0,
}
recStubFunc, reqStore := comproto.RecordingExecutions(
comproto.AdaptOutcomeToCmdStub(&staticOutcome))
settings := comproto.Settings{
DiscoveredBy: comproto.DiscoveredByHomeBinDir,
DiscoveredByHomeDirBinData: comproto.DiscoveredByHomeDirBinData{
EnvHomeKey: "JAVA_HOME",
BinDirs: []string{"bin"},
},
ExecType: comproto.ExecTypeExe,
}
key, err := stubber.WhenExecDoStubFunc(recStubFunc, rt.EnsureHasExecExt("java"), settings)
ifNotEqPanic(nil, err, "fail to setip stub")
javaCmd := os.ExpandEnv("${JAVA_HOME}/bin/java")
cmd := exec.Command(javaCmd, "-version")
var bufStderr, bufStdout bytes.Buffer
cmd.Stderr = &bufStderr
cmd.Stdout = &bufStdout
err = cmd.Run()
ifNotEqPanic(nil, err, "should have hat successful execution")
// accessing and checking stubrequest dynymic mode
wantRequests := []comproto.StubRequest{
{
CmdName: rt.EnsureHasExecExt("java"), Args: []string{"-version"}, Key: key,
},
}
ifNotEqPanic(wantRequests, *reqStore, "unexpected stub requests")
// accessing and checking outcome
gotStderr := bufStderr.String()
ifNotEqPanic(staticOutcome.Stderr, gotStderr, "unexpected stderr //stdout:"+bufStdout.String())
gotStdout := bufStdout.String()
ifNotEqPanic(staticOutcome.Stdout, gotStdout, "unexpected stdout")
gotExitCode := cmd.ProcessState.ExitCode()
ifNotEqPanic(int(staticOutcome.ExitCode), gotExitCode, "unexpected exec exit code")
// Output:
}
...
I started the journey by using bash for a quick implementation. At some point I moved the stub code in a standalone more serious package. But I kept bash as a challenge (can I do that in bash!?!) I suggest you prefer the Exec base stub, which is the default if you do not set:
comproto.Settings.ExecType
I believe in having options/choices. So use this package whenever you pleases. You should however be aware of the following alternatives to or for CLI API usage:
You are welcome to add more greatness to this project. Here some things you could do:
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.