diff --git a/integration_tests/protocols/code/ps1-snippet.yaml b/integration_tests/protocols/code/ps1-snippet.yaml index 9d6c91f06d..ae8c4d29bf 100644 --- a/integration_tests/protocols/code/ps1-snippet.yaml +++ b/integration_tests/protocols/code/ps1-snippet.yaml @@ -8,6 +8,7 @@ info: description: | ps1-code-snippet +self-contained: true code: - engine: - powershell diff --git a/integration_tests/protocols/code/py-env-var.yaml b/integration_tests/protocols/code/py-env-var.yaml index 067c183bb7..8cf448ee47 100644 --- a/integration_tests/protocols/code/py-env-var.yaml +++ b/integration_tests/protocols/code/py-env-var.yaml @@ -8,6 +8,7 @@ info: description: | py-code-snippet +self-contained: true code: - engine: - py diff --git a/integration_tests/protocols/code/py-file.yaml b/integration_tests/protocols/code/py-file.yaml index 3521ec902d..24c8f185f0 100644 --- a/integration_tests/protocols/code/py-file.yaml +++ b/integration_tests/protocols/code/py-file.yaml @@ -8,6 +8,7 @@ info: description: | py-file +self-contained: true code: - engine: - py diff --git a/integration_tests/protocols/code/py-interactsh.yaml b/integration_tests/protocols/code/py-interactsh.yaml index 0ccab7a7cd..c63d86cdc1 100644 --- a/integration_tests/protocols/code/py-interactsh.yaml +++ b/integration_tests/protocols/code/py-interactsh.yaml @@ -8,6 +8,7 @@ info: description: | testcode +self-contained: true variables: i: "{{interactsh-url}}" diff --git a/integration_tests/protocols/code/py-nosig.yaml b/integration_tests/protocols/code/py-nosig.yaml index d8bd0ac6ac..3630d3bfcb 100644 --- a/integration_tests/protocols/code/py-nosig.yaml +++ b/integration_tests/protocols/code/py-nosig.yaml @@ -8,6 +8,7 @@ info: description: | Python code without signature +self-contained: true code: - engine: - py diff --git a/integration_tests/protocols/code/py-snippet.yaml b/integration_tests/protocols/code/py-snippet.yaml index 5e36c1a673..1934b68fd1 100644 --- a/integration_tests/protocols/code/py-snippet.yaml +++ b/integration_tests/protocols/code/py-snippet.yaml @@ -8,6 +8,7 @@ info: description: | py-code-snippet +self-contained: true code: - engine: - py diff --git a/integration_tests/protocols/code/unsigned.yaml b/integration_tests/protocols/code/unsigned.yaml index 7e483f0e8e..85b4ea8a7f 100644 --- a/integration_tests/protocols/code/unsigned.yaml +++ b/integration_tests/protocols/code/unsigned.yaml @@ -8,6 +8,7 @@ info: description: | unsigned-code-snippet +self-contained: true code: - engine: - py diff --git a/pkg/protocols/code/code.go b/pkg/protocols/code/code.go index b3344d08d4..d2a866036f 100644 --- a/pkg/protocols/code/code.go +++ b/pkg/protocols/code/code.go @@ -47,7 +47,7 @@ var ( ErrCodeExecutionDeadline = errkit.New("code execution deadline exceeded").SetKind(errkit.ErrKindDeadline).Build() ) -// Request is a request for the SSL protocol +// Request is a request for the code protocol type Request struct { // Operators for the current request go here. operators.Operators `yaml:",inline,omitempty"` @@ -70,6 +70,9 @@ type Request struct { // description: | // Source File/Snippet Source string `yaml:"source,omitempty" json:"source,omitempty" jsonschema:"title=source file/snippet,description=Source snippet"` + // description: | + // SelfContained specifies if the request is self-contained. + SelfContained bool `yaml:"-" json:"-"` options *protocols.ExecutorOptions `yaml:"-" json:"-"` preConditionCompiled *goja.Program `yaml:"-" json:"-"` @@ -136,6 +139,11 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error { } request.preConditionCompiled = preConditionCompiled } + + if !request.options.IsMultiProtocol && !request.SelfContained { + return errorutil.NewWithTag(request.TemplateID, "could not compile single %q protocol without enabling self-contained", request.Type()) + } + return nil } diff --git a/pkg/protocols/code/code_test.go b/pkg/protocols/code/code_test.go index 320f7c5481..f32e15d5a0 100644 --- a/pkg/protocols/code/code_test.go +++ b/pkg/protocols/code/code_test.go @@ -21,8 +21,9 @@ func TestCodeProtocol(t *testing.T) { testutils.Init(options) templateID := "testing-code" request := &Request{ - Engine: []string{"sh"}, - Source: "echo test", + SelfContained: true, + Engine: []string{"sh"}, + Source: "echo test", } executerOpts := testutils.NewMockExecuterOptions(options, &testutils.TemplateInfo{ ID: templateID, diff --git a/pkg/templates/compile.go b/pkg/templates/compile.go index b4005afe81..9cb2b8e7f7 100644 --- a/pkg/templates/compile.go +++ b/pkg/templates/compile.go @@ -147,6 +147,9 @@ func (template *Template) parseSelfContainedRequests() { for _, request := range template.RequestsHeadless { request.SelfContained = true } + for _, request := range template.RequestsCode { + request.SelfContained = true + } } // Requests returns the total request count for the template @@ -178,11 +181,12 @@ func (template *Template) compileProtocolRequests(options *protocols.ExecutorOpt var requests []protocols.Request - if template.hasMultipleRequests() { - // when multiple requests are present preserve the order of requests and protocols - // which is already done during unmarshalling + // when multiple requests or protocols are present, preserve the + // order of requests and protocols which already done during the + // unmarshalling process or else. + if template.hasMultipleRequests() || template.hasMultipleProtocols() { requests = template.RequestsQueue - if options.Flow == "" { + if template.hasMultipleProtocols() && options.Flow == "" { options.IsMultiProtocol = true } } else { @@ -430,6 +434,8 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e return nil, err } + template.parseSelfContainedRequests() + if template.Executer != nil { if err := template.Executer.Compile(); err != nil { return nil, errors.Wrap(err, "could not compile request") @@ -439,7 +445,6 @@ func parseTemplate(data []byte, options protocols.ExecutorOptions) (*Template, e if template.Executer == nil && template.CompiledWorkflow == nil { return nil, ErrCreateTemplateExecutor } - template.parseSelfContainedRequests() // check if the template is verified // only valid templates can be verified or signed diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index df0c47648d..6aeae9b1b7 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -508,6 +508,40 @@ func (template *Template) addRequestsToQueue(keys ...string) { } } +// hasMultipleProtocols checks if the template has multiple protocols +func (template *Template) hasMultipleProtocols() bool { + // TODO(dwisiswant0): This should be done using something like + // `Template.GetAllProtocolRequests` method, which returns + // a slice of anything that starts off with "Requests" for + // currently supported protocols - to avoid redundancy and + // keeps it future-proof. + protocolRequests := []int{ + len(template.RequestsCode), + len(template.RequestsDNS), + len(template.RequestsFile), + len(template.RequestsHeadless), + len(template.RequestsHTTP), + len(template.RequestsJavascript), + len(template.RequestsNetwork), + len(template.RequestsSSL), + len(template.RequestsWebsocket), + len(template.RequestsWHOIS), + } + + var protocolCount int + for _, count := range protocolRequests { + if count > 0 { + protocolCount++ + } + + if protocolCount > 1 { + return true + } + } + + return false +} + // hasMultipleRequests checks if the template has multiple requests // if so it preserves the order of the request during compile and execution func (template *Template) hasMultipleRequests() bool {