Repository: controlplaneio/kubesec

Issue:
seccomp rule documentation needs an update
I couldn't find the file to edit for this text:
https://kubesec.io/basics/metadata-annotations-seccomp-security-alpha-kubernetes-io-pod/

This will result in a deprecation warning on currently support Kubernetes platforms. You've even updated the schema definition in #315 

Could you please reflect this:
https://kubernetes.io/docs/tutorials/security/seccomp/#create-a-pod-that-uses-the-container-runtime-default-seccomp-profile



Hints from issue comments:
@atombrella: You may also want to update (or add new) test assets for this:

https://github.com/controlplaneio/kubesec/blob/master/test/asset/score-0-pod-seccomp-non-unconfined.yml
https://github.com/controlplaneio/kubesec/blob/master/test/asset/score-0-pod-seccomp-unconfined.yml@esticansat: @06kellyjac I will be taking this one

Solution patch:
diff --git a/.github/workflows/security_analysis.yml b/.github/workflows/security_analysis.yml
index 15bc369..ba214ee 100644
--- a/.github/workflows/security_analysis.yml
+++ b/.github/workflows/security_analysis.yml
@@ -46,7 +46,7 @@ jobs:
           docker build . -t kubesec:${{ github.sha }}
 
       - name: Run Trivy
-        uses: aquasecurity/trivy-action@0.31.0
+        uses: aquasecurity/trivy-action@0.32.0
         with:
           image-ref: kubesec:${{ github.sha }}
           format: template
diff --git a/README.md b/README.md
index c8e5c6f..2cc2b36 100644
--- a/README.md
+++ b/README.md
@@ -295,7 +295,7 @@ $ kubesec ./score-9-deployment.yml | jq --exit-status '.score > 10' >/dev/null
 
 ## Example output
 
-Kubesec returns a returns a JSON array, and can scan multiple YAML documents in a single input file.
+Kubesec returns a JSON array, and can scan multiple YAML documents in a single input file.
 
 ```json
 [
@@ -327,15 +327,21 @@ Kubesec returns a returns a JSON array, and can scan multiple YAML documents in
 ]
 ```
 
+> [!NOTE]
+> You can also cat multiple files, as long as they're correctly formatted as multiple documents separated by `---`. E.g.
+> ```
+> { cat test/asset/multi.yml;
+> echo "---";
+> cat test/asset/critical-double-multiple.yml;
+> } | dist/kubesec scan -
+> ```
+
 ---
 
-## Contributors
 
-Thanks to our awesome contributors!
+## Contributing
 
-- [Andrew Martin](@sublimino)
-- [Stefan Prodan](@stefanprodan)
-- [Jack Kelly](@06kellyjac)
+Check out [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
 
 ## Getting Help
 
@@ -348,7 +354,7 @@ If you have any questions about Kubesec and Kubernetes security:
 Your feedback is always welcome!
 
 [testing_workflow]: https://github.com/controlplaneio/kubesec/actions?query=workflow%3ATesting
-[testing_workflow_badge]: https://github.com/controlplaneio/kubesec/workflows/Testing/badge.svg
+[testing_workflow_badge]: https://github.com/controlplaneio/kubesec/actions/workflows/test_acceptance.yml/badge.svg
 [security_workflow]: https://github.com/controlplaneio/kubesec/actions?query=workflow%3A%22Security+Analysis%22
 [security_workflow_badge]: https://github.com/controlplaneio/kubesec/workflows/Security%20Analysis/badge.svg
 [release_workflow]: https://github.com/controlplaneio/kubesec/actions?query=workflow%3ARelease
diff --git a/go.mod b/go.mod
index bd40965..b203631 100644
--- a/go.mod
+++ b/go.mod
@@ -22,15 +22,16 @@ require (
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/prometheus/client_model v0.6.2 // indirect
 	github.com/prometheus/common v0.65.0 // indirect
-	github.com/prometheus/procfs v0.16.1 // indirect
+	github.com/prometheus/procfs v0.17.0 // indirect
 	github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
 	github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
 	github.com/shibumi/go-pathspec v1.3.0 // indirect
-	github.com/spf13/pflag v1.0.6 // indirect
+	github.com/spf13/pflag v1.0.7 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
-	golang.org/x/crypto v0.39.0 // indirect
-	golang.org/x/sys v0.33.0 // indirect
-	golang.org/x/text v0.26.0 // indirect
+	go.yaml.in/yaml/v2 v2.4.2 // indirect
+	golang.org/x/crypto v0.40.0 // indirect
+	golang.org/x/sys v0.34.0 // indirect
+	golang.org/x/text v0.27.0 // indirect
 	google.golang.org/protobuf v1.36.6 // indirect
-	sigs.k8s.io/yaml v1.4.0 // indirect
+	sigs.k8s.io/yaml v1.5.0 // indirect
 )
diff --git a/go.sum b/go.sum
index b2b354c..0048ee4 100644
--- a/go.sum
+++ b/go.sum
@@ -13,7 +13,6 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
 github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
@@ -48,8 +47,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
 github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
 github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
-github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
-github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
 github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -61,8 +60,9 @@ github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh
 github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
 github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
 github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
-github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
 github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
+github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
@@ -75,14 +75,18 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
-golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
-golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
-golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
-golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
-golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
-golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
+go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
+go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
+go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
+golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
+golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
+golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
+golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
+golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
+golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
+golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
 google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
 google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -92,5 +96,5 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
-sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
+sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
+sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
diff --git a/pkg/ruler/ruleset.go b/pkg/ruler/ruleset.go
index 5b8c3c7..727ae8b 100644
--- a/pkg/ruler/ruleset.go
+++ b/pkg/ruler/ruleset.go
@@ -230,7 +230,7 @@ func NewRuleset(logger *zap.SugaredLogger) *Ruleset {
 	seccompAnyRule := Rule{
 		Predicate: rules.SeccompAny,
 		ID:        "SeccompAny",
-		Selector:  ".metadata .annotations .\"container.seccomp.security.alpha.kubernetes.io/pod\"",
+		Selector:  ".spec .securityContext .seccompProfile .type | .spec .containers[] .securityContext .seccompProfile .type | .spec .initContainers[] .securityContext .seccompProfile .type | .spec .ephemeralContainers[] .securityContext .seccompProfile .type",
 		Reason:    "Seccomp profiles set minimum privilege and secure against unknown threats",
 		Kinds:     []string{"Pod", "Deployment", "StatefulSet", "DaemonSet"},
 		Points:    1,
@@ -240,7 +240,7 @@ func NewRuleset(logger *zap.SugaredLogger) *Ruleset {
 	seccompUnconfinedRule := Rule{
 		Predicate: rules.SeccompUnconfined,
 		ID:        "SeccompUnconfined",
-		Selector:  ".metadata .annotations .\"container.seccomp.security.alpha.kubernetes.io/pod\"",
+		Selector:  ".spec .securityContext .seccompProfile .type | .spec .containers[] .securityContext .seccompProfile .type | .spec .initContainers[] .securityContext .seccompProfile .type | .spec .ephemeralContainers[] .securityContext .seccompProfile .type",
 		Reason:    "Unconfined Seccomp profiles have full system call access",
 		Kinds:     []string{"Pod", "Deployment", "StatefulSet", "DaemonSet"},
 		Points:    -1,
diff --git a/pkg/rules/helper.go b/pkg/rules/helper.go
index f27c05c..61072c5 100644
--- a/pkg/rules/helper.go
+++ b/pkg/rules/helper.go
@@ -41,6 +41,7 @@ func checkSecurityContext(json []byte, checkPodSecurityContext bool, checkFn che
 
 	containersLen := jq.Copy().From(spec + ".containers").Count()
 	initContainersLen := jq.Copy().From(spec + ".initContainers").Count()
+	ephemeralContainersLen := jq.Copy().From(spec + ".ephemeralContainers").Count()
 
 	var valid int
 
@@ -60,6 +61,7 @@ func checkSecurityContext(json []byte, checkPodSecurityContext bool, checkFn che
 
 	ctnFn(initContainersLen, "initContainers")
 	ctnFn(containersLen, "containers")
+	ctnFn(ephemeralContainersLen, "ephemeralContainers")
 
 	return valid
 }
diff --git a/pkg/rules/seccompAny.go b/pkg/rules/seccompAny.go
index ebcb4f1..ff6e6a5 100644
--- a/pkg/rules/seccompAny.go
+++ b/pkg/rules/seccompAny.go
@@ -1,42 +1,35 @@
 package rules
 
 import (
-	"bytes"
-	"fmt"
 	"github.com/thedevsaddam/gojsonq/v2"
-	"regexp"
-	"strings"
 )
 
-// TODO(ajm): tighten these matches, they could be "[seccomp..." or " seccomp...", and "unconfined]" or "unconfined "
-// TODO(ajm): space delimiting matches is insufficient as this could be set to `unconfined blah`
-func SeccompAny(json []byte) int {
-	containers := 0
-	startWordBoundaryRegex := "[\\[ ]"
-	endWordBoundaryRegex := "[\\] ]"
-
-	capDrop := gojsonq.New().Reader(bytes.NewReader(json)).
-		From("metadata.annotations").Get()
-
-	capDropString := fmt.Sprintf("%v", capDrop)
+// isSeccompUnconfined checks the seccompProfile.type field and returns a checkSecurityContextResult struct.
+// If the field is set then unset=false. If, on top of that, the value of Unconfined matches the expected value
+// then return valid=true.
+func isSeccompUnconfined(jq *gojsonq.JSONQ, expectedUnconfined bool) checkSecurityContextResult {
+	value := jq.From("securityContext.seccompProfile.type").Get()
 
-	if capDrop != nil && strings.Contains(capDropString, "seccomp.security.alpha.kubernetes.io/pod:") {
-		if !strings.Contains(capDropString, "seccomp.security.alpha.kubernetes.io/pod:unconfined") {
-			containers++
-		}
-	} else if capDrop != nil {
+	v, ok := value.(string)
 
-		keyNameRegex := "seccomp\\.security\\.alpha\\.kubernetes\\.io/[a-zA-Z-.]+"
-		// TODO(ajm) match end of string in regex
-		isNamedPodMatch, _ := regexp.MatchString(startWordBoundaryRegex+keyNameRegex+":", capDropString)
+	res := checkSecurityContextResult{}
+	if !ok {
+		res.unset = true
+		return res
+	}
 
-		if isNamedPodMatch {
-			isUnconfinedNamedPodMatch, _ := regexp.MatchString(startWordBoundaryRegex+keyNameRegex+":unconfined"+endWordBoundaryRegex, capDropString)
-			if !isUnconfinedNamedPodMatch {
-				containers++
-			}
-		}
+	return checkSecurityContextResult{
+		valid: (v == "Unconfined") == expectedUnconfined,
 	}
+}
 
-	return containers
+// SeccompAny retrieves the number of instances in a manifest where the Seccomp profile has been specified
+// to a value other than 'Unconfined'
+func SeccompAny(json []byte) int {
+	return checkSecurityContext(
+		json,
+		true, // present in PodSecurityContext
+		func(jq *gojsonq.JSONQ) checkSecurityContextResult {
+			return isSeccompUnconfined(jq, false)
+		})
 }
diff --git a/pkg/rules/seccompTestCases.go b/pkg/rules/seccompTestCases.go
new file mode 100644
index 0000000..90bd154
--- /dev/null
+++ b/pkg/rules/seccompTestCases.go
@@ -0,0 +1,250 @@
+package rules
+
+// Currently, seccompProfile can appear under the following places (search for 'seccomp' in
+// the PSS docs https://kubernetes.io/docs/concepts/security/pod-security-standards/):
+//
+//	spec.securityContext.seccompProfile.type
+//	spec.containers[*].securityContext.seccompProfile.type
+//	spec.initContainers[*].securityContext.seccompProfile.type
+//	spec.ephemeralContainers[*].securityContext.seccompProfile.type
+
+const (
+	tcmanSeccompProfileMissing = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  containers:
+    - name: trustworthy-container
+      image: sotrustworthy:latest
+`
+	tcmanSeccompProfileInSecCtxRD = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  securityContext:
+    seccompProfile:
+      type: RuntimeDefault
+  containers:
+    - name: trustworthy-container
+      image: sotrustworthy:latest
+`
+	tcmanSeccompProfileInSecCtxUn = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  securityContext:
+    seccompProfile:
+      type: Unconfined
+  containers:
+    - name: trustworthy-container
+      image: sotrustworthy:latest
+`
+	tcmanSeccompProfileInSecCtxLH = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  securityContext:
+    seccompProfile:
+      type: LocalHost
+      localhostProfile: profiles/audit.json
+  containers:
+    - name: trustworthy-container
+      image: sotrustworthy:latest
+`
+	tcmanSeccompProfileInContainerRD = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  containers:
+  - name: trustworthy-container
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: RuntimeDefault
+`
+	tcmanSeccompProfileInContainerUn = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  containers:
+  - name: trustworthy-container
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: Unconfined
+`
+	tcmanSeccompProfileInContainerLH = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  containers:
+  - name: trustworthy-container
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: LocalHost
+        localhostProfile: profiles/audit.json
+`
+	tcmanSeccompProfileInInitRD = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  initContainers:
+  - name: trustworthy-initcontainer
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: RuntimeDefault
+`
+	tcmanSeccompProfileInInitUn = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  initContainers:
+  - name: trustworthy-initcontainer
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: Unconfined
+`
+	tcmanSeccompProfileInInitLH = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  initContainers:
+  - name: trustworthy-initcontainer
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: LocalHost
+        localhostProfile: profiles/audit.json
+`
+	tcmanSeccompProfileInEphRD = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  ephemeralContainers:
+  - name: trustworthy-ephcontainer
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: RuntimeDefault
+`
+	tcmanSeccompProfileInEphUn = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  ephemeralContainers:
+  - name: trustworthy-ephcontainer
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: Unconfined
+`
+	tcmanSeccompProfileInEphLH = `
+---
+apiVersion: v1
+kind: Pod
+spec:
+  ephemeralContainers:
+  - name: trustworthy-ephcontainer
+    image: sotrustworthy:latest
+    securityContext:
+      seccompProfile:
+        type: LocalHost
+        localhostProfile: profiles/audit.json
+`
+)
+
+type tcSeccompProfileType string
+
+const (
+	tcprofSeccompProfileMissing tcSeccompProfileType = ""
+	tcprofSeccompUnconfined     tcSeccompProfileType = "Unconfined"
+	tcprofSeccompRuntimeDefault tcSeccompProfileType = "RuntimeDefault"
+	tcprofSeccompLocalHost      tcSeccompProfileType = "LocalHost"
+)
+
+var testCasesSeccomp = []struct {
+	description         string
+	expectedProfileType tcSeccompProfileType
+	manifest            string
+}{
+	{
+		description:         "Missing seccompProfile",
+		expectedProfileType: tcprofSeccompProfileMissing,
+		manifest:            tcmanSeccompProfileMissing,
+	},
+	{
+		description:         "RuntimeDefault seccompProfile found inside .spec.securityContext",
+		expectedProfileType: tcprofSeccompRuntimeDefault,
+		manifest:            tcmanSeccompProfileInSecCtxRD,
+	},
+	{
+		description:         "Unconfined seccompProfile found inside .spec.securityContext",
+		expectedProfileType: tcprofSeccompUnconfined,
+		manifest:            tcmanSeccompProfileInSecCtxUn,
+	},
+	{
+		description:         "LocalHost seccompProfile found inside .spec.securityContext",
+		expectedProfileType: tcprofSeccompLocalHost,
+		manifest:            tcmanSeccompProfileInSecCtxLH,
+	},
+	{
+		description:         "RuntimeDefault seccompProfile found inside .spec.containers[*].securityContext",
+		expectedProfileType: tcprofSeccompRuntimeDefault,
+		manifest:            tcmanSeccompProfileInContainerRD,
+	},
+	{
+		description:         "Unconfined seccompProfile found inside .spec.containers[*].securityContext",
+		expectedProfileType: tcprofSeccompUnconfined,
+		manifest:            tcmanSeccompProfileInContainerUn,
+	},
+	{
+		description:         "LocalHost seccompProfile found inside .spec.containers[*].securityContext",
+		expectedProfileType: tcprofSeccompLocalHost,
+		manifest:            tcmanSeccompProfileInContainerLH,
+	},
+	{
+		description:         "RuntimeDefault seccompProfile found inside .spec.initContainers[*].securityContext",
+		expectedProfileType: tcprofSeccompRuntimeDefault,
+		manifest:            tcmanSeccompProfileInInitRD,
+	},
+	{
+		description:         "Unconfined seccompProfile found inside .spec.initContainers[*].securityContext",
+		expectedProfileType: tcprofSeccompUnconfined,
+		manifest:            tcmanSeccompProfileInInitUn,
+	},
+	{
+		description:         "LocalHost seccompProfile found inside .spec.initContainers[*].securityContext",
+		expectedProfileType: tcprofSeccompLocalHost,
+		manifest:            tcmanSeccompProfileInInitLH,
+	},
+	{
+		description:         "RuntimeDefault seccompProfile found inside .spec.ephemeralContainers[*].securityContext",
+		expectedProfileType: tcprofSeccompRuntimeDefault,
+		manifest:            tcmanSeccompProfileInEphRD,
+	},
+	{
+		description:         "Unconfined seccompProfile found inside .spec.ephemeralContainers[*].securityContext",
+		expectedProfileType: tcprofSeccompUnconfined,
+		manifest:            tcmanSeccompProfileInEphUn,
+	},
+	{
+		description:         "LocalHost seccompProfile found inside .spec.ephemeralContainers[*].securityContext",
+		expectedProfileType: tcprofSeccompLocalHost,
+		manifest:            tcmanSeccompProfileInEphLH,
+	},
+}
diff --git a/pkg/rules/seccompUnconfined.go b/pkg/rules/seccompUnconfined.go
index 2874b10..00a1900 100644
--- a/pkg/rules/seccompUnconfined.go
+++ b/pkg/rules/seccompUnconfined.go
@@ -1,41 +1,16 @@
 package rules
 
 import (
-	"bytes"
-	"fmt"
 	"github.com/thedevsaddam/gojsonq/v2"
-	"regexp"
-	"strings"
 )
 
-// TODO(ajm) this is just an inversion of seccompAny.go and should be refactored to use a shared function
+// SeccompUnconfined retrieves the number of instances in a manifest where the Seccomp profile has been specified
+// to a value of 'Unconfined'
 func SeccompUnconfined(json []byte) int {
-	containers := 0
-	startWordBoundaryRegex := "[\\[ ]"
-	endWordBoundaryRegex := "[\\] ]"
-
-	capDrop := gojsonq.New().Reader(bytes.NewReader(json)).
-		From("metadata.annotations").Get()
-
-	capDropString := fmt.Sprintf("%v", capDrop)
-
-	if capDrop != nil && strings.Contains(capDropString, "seccomp.security.alpha.kubernetes.io/pod:") {
-		if strings.Contains(capDropString, "seccomp.security.alpha.kubernetes.io/pod:unconfined") {
-			containers++
-		}
-	} else if capDrop != nil {
-
-		keyNameRegex := "seccomp\\.security\\.alpha\\.kubernetes\\.io/[a-zA-Z-.]+"
-		// TODO(ajm) match end of string in regex
-		isNamedPodMatch, _ := regexp.MatchString(startWordBoundaryRegex+keyNameRegex+":", capDropString)
-
-		if isNamedPodMatch {
-			isUnconfinedNamedPodMatch, _ := regexp.MatchString(startWordBoundaryRegex+keyNameRegex+":unconfined"+endWordBoundaryRegex, capDropString)
-			if isUnconfinedNamedPodMatch {
-				containers++
-			}
-		}
-	}
-
-	return containers
+	return checkSecurityContext(
+		json,
+		true, // present in PodSecurityContext
+		func(jq *gojsonq.JSONQ) checkSecurityContextResult {
+			return isSeccompUnconfined(jq, true)
+		})
 }



Test patch:
diff --git a/pkg/rules/seccompAny_test.go b/pkg/rules/seccompAny_test.go
index 5008465..eb08ba2 100644
--- a/pkg/rules/seccompAny_test.go
+++ b/pkg/rules/seccompAny_test.go
@@ -1,188 +1,110 @@
 package rules
 
 import (
-	"github.com/ghodss/yaml"
 	"testing"
-)
-
-func Test_SeccompAny_Pod(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    other: runtime/default
-    seccomp.security.alpha.kubernetes.io/pod: runtime/default
-    something: runtime/default
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompAny(json)
-	if containers != 1 {
-		t.Errorf("Got %v containers wanted %v", containers, 1)
-	}
-}
-
-func Test_SeccompAny_Pod_Unconfined(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/pod: unconfined
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompAny(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
-	}
-}
-
-func Test_SeccompAny_No_Seccomp(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-spec:
-  containers:
-  - name: c1
-    securityContext:
-      capabilities:
-        drop:
-  - name: c2
-    securityContext:
-      capabilities:
-  - name: c3
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompAny(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
-	}
-}
-
-func Test_SeccompAny_Named_Pod(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/somePodName: runtime/default
-spec:
-  containers:
-    - name: somePodName
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompAny(json)
-	if containers != 1 {
-		t.Errorf("Got %v containers wanted %v", containers, 1)
-	}
-}
-
-func Test_SeccompAny_Named_Pod_Special_Chars(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/my-Named.Pod: runtime/default
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
 
-	containers := SeccompAny(json)
-	if containers != 1 {
-		t.Errorf("Got %v containers wanted %v", containers, 1)
-	}
-}
-
-func Test_SeccompAny_Named_Pod_Special_Chars_Unconfined(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/my-Named.Pod: unconfined
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
+	"github.com/ghodss/yaml"
+	"github.com/thedevsaddam/gojsonq/v2"
+)
 
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
+func Test_isSeccompUnconfined(t *testing.T) {
+	testCases := []struct {
+		description        string
+		json               string
+		expectedUnconfined bool
+		expectedResult     *checkSecurityContextResult
+	}{
+		{
+			description:        "field missing",
+			json:               `{}`,
+			expectedUnconfined: true,
+			expectedResult: &checkSecurityContextResult{
+				unset: true,
+				valid: false,
+			},
+		},
+		{
+			description:        "non-string field",
+			json:               `{"securityContext":{"seccompProfile":{"type":123}}}`,
+			expectedUnconfined: true,
+			expectedResult: &checkSecurityContextResult{
+				unset: true,
+				valid: false,
+			},
+		},
+		{
+			description:        "Unconfined when expectedUnconfined=true",
+			json:               `{"securityContext":{"seccompProfile":{"type":"Unconfined"}}}`,
+			expectedUnconfined: true,
+			expectedResult: &checkSecurityContextResult{
+				unset: false,
+				valid: true,
+			},
+		},
+		{
+			description:        "Unconfined when expectedUnconfined=false",
+			json:               `{"securityContext":{"seccompProfile":{"type":"Unconfined"}}}`,
+			expectedUnconfined: false,
+			expectedResult: &checkSecurityContextResult{
+				unset: false,
+				valid: false,
+			},
+		},
+		{
+			description:        "Profile=RuntimeDefault when expectedUnconfined=false",
+			json:               `{"securityContext":{"seccompProfile":{"type":"RuntimeDefault"}}}`,
+			expectedUnconfined: false,
+			expectedResult: &checkSecurityContextResult{
+				unset: false,
+				valid: true,
+			},
+		},
+		{
+			description:        "Profile=RuntimeDefault when expectedUnconfined=true",
+			json:               `{"securityContext":{"seccompProfile":{"type":"RuntimeDefault"}}}`,
+			expectedUnconfined: true,
+			expectedResult: &checkSecurityContextResult{
+				unset: false,
+				valid: false,
+			},
+		},
 	}
 
-	containers := SeccompAny(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
+	for _, tc := range testCases {
+		t.Run(tc.description, func(t *testing.T) {
+			jq := gojsonq.New().FromString(tc.json)
+			result := isSeccompUnconfined(jq, tc.expectedUnconfined)
+
+			if tc.expectedResult.unset != result.unset {
+				t.Errorf("expected 'checkSecurityContextResult.unset' value for test was %v but received %v instead",
+					tc.expectedResult.unset, result.unset)
+			}
+
+			if tc.expectedResult.valid != result.valid {
+				t.Errorf("expected 'checkSecurityContextResult.valid' value for test was %v but received %v instead",
+					tc.expectedResult.valid, result.valid)
+			}
+		})
 	}
 }
 
-func Test_SeccompAny_Named_Pod_Illegal_Name(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/my-Named.Pod(illegal name): runtime/default
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompAny(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
+func Test_SeccompAny(t *testing.T) {
+	for _, tc := range testCasesSeccomp {
+		t.Run(tc.description, func(t *testing.T) {
+			json, err := yaml.YAMLToJSON([]byte(tc.manifest))
+			if err != nil {
+				t.Fatal(err.Error())
+			}
+
+			count := SeccompAny(json)
+			expectedCount := 0
+			if tc.expectedProfileType == tcprofSeccompRuntimeDefault || tc.expectedProfileType == tcprofSeccompLocalHost {
+				expectedCount = 1
+			}
+
+			if count != expectedCount {
+				t.Errorf("Expected count was %v but received %v", expectedCount, count)
+			}
+		})
 	}
 }
-
-// TODO(ajm) more seccomp tests for deployments
diff --git a/pkg/rules/seccompUnconfined_test.go b/pkg/rules/seccompUnconfined_test.go
index de802ae..88ad7c1 100644
--- a/pkg/rules/seccompUnconfined_test.go
+++ b/pkg/rules/seccompUnconfined_test.go
@@ -5,185 +5,23 @@ import (
 	"testing"
 )
 
-func Test_SeccompUnconfined_Pod(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    other: runtime/default
-    seccomp.security.alpha.kubernetes.io/pod: runtime/default
-    something: runtime/default
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
-	}
-}
-
-func Test_SeccompUnconfined_Pod_Unconfined(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/pod: unconfined
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 1 {
-		t.Errorf("Got %v containers wanted %v", containers, 1)
-	}
-}
-
-func Test_SeccompUnconfined_No_Seccomp(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-spec:
-  containers:
-  - name: c1
-    securityContext:
-      capabilities:
-        drop:
-  - name: c2
-    securityContext:
-      capabilities:
-  - name: c3
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
-	}
-}
-
-func Test_SeccompUnconfined_Named_Pod(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/somePodName: runtime/default
-spec:
-  containers:
-    - name: somePodName
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
-	}
-}
-
-func Test_SeccompUnconfined_Named_Pod_Special_Chars(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/my-Named.Pod: runtime/default
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
-	}
-}
-
-// TODO(ajm) this matches the `unconfined`, but the pod name is invalid. Could lead to unexpected results on CLI (API server should only be sending valid pods for Admission Control)
-func Test_SeccompUnconfined_Named_Pod_Special_Chars_Unconfined(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/my-Named.Pod: unconfined
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 1 {
-		t.Errorf("Got %v containers wanted %v", containers, 1)
-	}
-}
-
-func Test_SeccompUnconfined_Named_Pod_Illegal_Name(t *testing.T) {
-	var data = `
----
-apiVersion: v1
-kind: Pod
-metadata:
- annotations:
-   seccomp.security.alpha.kubernetes.io/my-Named.Pod(illegal name): runtime/default
-spec:
- containers:
-   - name: trustworthy-container
-     image: sotrustworthy:latest
-`
-
-	json, err := yaml.YAMLToJSON([]byte(data))
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-
-	containers := SeccompUnconfined(json)
-	if containers != 0 {
-		t.Errorf("Got %v containers wanted %v", containers, 0)
+func Test_SeccompUnconfined(t *testing.T) {
+	for _, tc := range testCasesSeccomp {
+		t.Run(tc.description, func(t *testing.T) {
+			json, err := yaml.YAMLToJSON([]byte(tc.manifest))
+			if err != nil {
+				t.Fatal(err.Error())
+			}
+
+			count := SeccompUnconfined(json)
+			expectedCount := 0
+			if tc.expectedProfileType == tcprofSeccompUnconfined {
+				expectedCount = 1
+			}
+
+			if count != expectedCount {
+				t.Errorf("Expected count was %v but received %v", expectedCount, count)
+			}
+		})
 	}
 }
-
-// TODO(ajm) more seccomp tests for deployments
diff --git a/test/1_cli.bats b/test/1_cli.bats
index fcf376c..bc19eab 100644
--- a/test/1_cli.bats
+++ b/test/1_cli.bats
@@ -10,11 +10,6 @@ teardown() {
   _global_teardown
 }
 
-@test "fails Pod with unconfined seccomp" {
-  run _app "${TEST_DIR}/asset/score-0-pod-seccomp-unconfined.yml"
-  assert_lt_zero_points
-}
-
 @test "fails with CAP_SYS_ADMIN" {
   run _app "${TEST_DIR}/asset/score-0-cap-sys-admin.yml"
   assert_lt_zero_points
@@ -143,16 +138,51 @@ teardown() {
   assert_gt_zero_points
 }
 
-@test "fails Pod with unconfined seccomp for all containers" {
-  run _app "${TEST_DIR}/asset/score-0-pod-seccomp-unconfined.yml"
+@test "fails Deployment with unconfined seccomp for all containers" {
+  run _app "${TEST_DIR}/asset/score-0-dep-seccomp-empty-securitycontext.yml"
+  assert_zero_points
+}
+
+@test "passes Deployment with non-unconfined seccomp on the .spec section" {
+  run _app "${TEST_DIR}/asset/score-1-dep-seccomp-nonunconfined-spec-securitycontext.yml"
+  assert_gt_zero_points
+}
+
+@test "fails Deployment with unconfined seccomp on the .spec section" {
+  run _app "${TEST_DIR}/asset/score-0-dep-seccomp-unconfined-spec-securitycontext.yml"
+  assert_lt_zero_points
+}
+
+@test "passes Deployment with non-unconfined seccomp on the .spec.containers section" {
+  run _app "${TEST_DIR}/asset/score-1-dep-seccomp-nonunconfined-container.yml"
+  assert_gt_zero_points
+}
+
+@test "fails Deployment with unconfined seccomp on the .spec.containers section" {
+  run _app "${TEST_DIR}/asset/score-0-dep-seccomp-unconfined-container.yml"
+  assert_lt_zero_points
+}
+
+@test "passes Deployment with non-unconfined seccomp on the .spec.initContainers section" {
+  run _app "${TEST_DIR}/asset/score-1-dep-seccomp-nonunconfined-initcontainer.yml"
+  assert_gt_zero_points
+}
+
+@test "fails Deployment with unconfined seccomp on the .spec.initcontainers section" {
+  run _app "${TEST_DIR}/asset/score-0-dep-seccomp-unconfined-initcontainer.yml"
   assert_lt_zero_points
 }
 
-@test "passes Pod with non-unconfined seccomp for all containers" {
-  run _app "${TEST_DIR}/asset/score-0-pod-seccomp-non-unconfined.yml"
+@test "passes Deployment with non-unconfined seccomp on the .spec.ephemeralContainers section" {
+  run _app "${TEST_DIR}/asset/score-1-dep-seccomp-nonunconfined-ephemeralcontainer.yml"
   assert_gt_zero_points
 }
 
+@test "fails Deployment with unconfined seccomp on the .spec.ephemeralContainers section" {
+  run _app "${TEST_DIR}/asset/score-0-dep-seccomp-unconfined-ephemeralcontainer.yml"
+  assert_lt_zero_points
+}
+
 @test "fails DaemonSet with hostNetwork" {
   run _app "${TEST_DIR}/asset/score-0-daemonset-host-network.yml"
   assert_lt_zero_points
diff --git a/test/asset/score-0-dep-seccomp-empty-securitycontext.yml b/test/asset/score-0-dep-seccomp-empty-securitycontext.yml
new file mode 100644
index 0000000..5d57384
--- /dev/null
+++ b/test/asset/score-0-dep-seccomp-empty-securitycontext.yml
@@ -0,0 +1,18 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
diff --git a/test/asset/score-0-dep-seccomp-unconfined-container.yml b/test/asset/score-0-dep-seccomp-unconfined-container.yml
new file mode 100644
index 0000000..c9c7cc9
--- /dev/null
+++ b/test/asset/score-0-dep-seccomp-unconfined-container.yml
@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
+        securityContext:
+          seccompProfile:
+            type: Unconfined
diff --git a/test/asset/score-0-dep-seccomp-unconfined-ephemeralcontainer.yml b/test/asset/score-0-dep-seccomp-unconfined-ephemeralcontainer.yml
new file mode 100644
index 0000000..d08e5fe
--- /dev/null
+++ b/test/asset/score-0-dep-seccomp-unconfined-ephemeralcontainer.yml
@@ -0,0 +1,24 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
+      ephemeralContainers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-ephemeralcontainer
+        securityContext:
+          seccompProfile:
+            type: Unconfined
diff --git a/test/asset/score-0-dep-seccomp-unconfined-initcontainer.yml b/test/asset/score-0-dep-seccomp-unconfined-initcontainer.yml
new file mode 100644
index 0000000..8ac0b31
--- /dev/null
+++ b/test/asset/score-0-dep-seccomp-unconfined-initcontainer.yml
@@ -0,0 +1,24 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
+      initContainers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-initcontainer
+        securityContext:
+          seccompProfile:
+            type: Unconfined
diff --git a/test/asset/score-0-dep-seccomp-unconfined-spec-securitycontext.yml b/test/asset/score-0-dep-seccomp-unconfined-spec-securitycontext.yml
new file mode 100644
index 0000000..f59148d
--- /dev/null
+++ b/test/asset/score-0-dep-seccomp-unconfined-spec-securitycontext.yml
@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      securityContext:
+        seccompProfile:
+          type: Unconfined
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
diff --git a/test/asset/score-0-pod-seccomp-non-unconfined.yml b/test/asset/score-0-pod-seccomp-non-unconfined.yml
deleted file mode 100644
index e1a0fd5..0000000
--- a/test/asset/score-0-pod-seccomp-non-unconfined.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/pod: runtime/default
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
diff --git a/test/asset/score-0-pod-seccomp-unconfined.yml b/test/asset/score-0-pod-seccomp-unconfined.yml
deleted file mode 100644
index 3274849..0000000
--- a/test/asset/score-0-pod-seccomp-unconfined.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-apiVersion: v1
-kind: Pod
-metadata:
-  annotations:
-    seccomp.security.alpha.kubernetes.io/pod: unconfined
-spec:
-  containers:
-    - name: trustworthy-container
-      image: sotrustworthy:latest
diff --git a/test/asset/score-1-dep-seccomp-nonunconfined-container.yml b/test/asset/score-1-dep-seccomp-nonunconfined-container.yml
new file mode 100644
index 0000000..dfa3795
--- /dev/null
+++ b/test/asset/score-1-dep-seccomp-nonunconfined-container.yml
@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
+        securityContext:
+          seccompProfile:
+            type: RuntimeDefault
diff --git a/test/asset/score-1-dep-seccomp-nonunconfined-ephemeralcontainer.yml b/test/asset/score-1-dep-seccomp-nonunconfined-ephemeralcontainer.yml
new file mode 100644
index 0000000..ab8adef
--- /dev/null
+++ b/test/asset/score-1-dep-seccomp-nonunconfined-ephemeralcontainer.yml
@@ -0,0 +1,24 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
+      ephemeralContainers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-initcontainer
+        securityContext:
+          seccompProfile:
+            type: RuntimeDefault
diff --git a/test/asset/score-1-dep-seccomp-nonunconfined-initcontainer.yml b/test/asset/score-1-dep-seccomp-nonunconfined-initcontainer.yml
new file mode 100644
index 0000000..71e5151
--- /dev/null
+++ b/test/asset/score-1-dep-seccomp-nonunconfined-initcontainer.yml
@@ -0,0 +1,24 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container
+      initContainers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-initcontainer
+        securityContext:
+          seccompProfile:
+            type: RuntimeDefault
diff --git a/test/asset/score-1-dep-seccomp-nonunconfined-spec-securitycontext.yml b/test/asset/score-1-dep-seccomp-nonunconfined-spec-securitycontext.yml
new file mode 100644
index 0000000..51ce647
--- /dev/null
+++ b/test/asset/score-1-dep-seccomp-nonunconfined-spec-securitycontext.yml
@@ -0,0 +1,21 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trustworthy-deployment
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trustworthy-deployment
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: trustworthy-deployment
+    spec:
+      securityContext:
+        seccompProfile:
+          type: RuntimeDefault
+      containers:
+      - image: sotrustworthy:latest
+        name: sotrustworthy-container