Checkov's helm framework renders the chart without a namespace override,
so metadata.namespace (set to .Release.Namespace, bound only at install
time) always resolves to "default" and trips CKV_K8S_21 on service.yaml,
deployment.yaml, and configmap.yaml even though the chart is
namespace-agnostic by design.
Suppressed via per-file checkov:skip comments, following the same
convention already used for the Cloud Run false positives in
deploy/gcp/cloudrun-service.yaml.
Without an explicit namespace in metadata, checkov (CKV_K8S_21) flags
every resource as using the default namespace. Using .Release.Namespace
lets helm install --namespace semantica --create-namespace correctly
scope all resources to the target namespace.
- gcp/cloudrun-service.yaml: add comment + README sed one-liner so PROJECT_ID
is substituted before gcloud run services replace (was a literal placeholder
that caused image-pull failure on the declarative deploy path)
- azure/main.parameters.json: replace wildcard allowedOrigins "*" with a
REPLACE_ME placeholder; add README note to set the real URL after first deploy
- kubernetes/networkpolicy.yaml + helm networkpolicy template: add from: selector
(ingress-nginx namespace + same-namespace pods) so ingress is no longer
allow-all; restrict egress to FalkorDB port 6379 and DNS port 53 instead of
the allow-all egress: - {} wildcard
- helm/values.yaml: expose networkPolicy.ingressNamespace and falkordbPort values
- kubernetes/deployment.yaml: add secretRef for knowledge-explorer-secrets so
FALKORDB_PASSWORD is actually injected into the container
- app.py: add _mutation_bridge_installed guard to prevent closure stacking when
the same GraphSession is passed to create_app() more than once; remove
duplicate app.state.allowed_origins assignment (single source of truth is
app.state.explorer_settings); add comment on falkordb_host/port dead config
- tests: update allowed_origins assertions to use explorer_settings dict
- .checkov.yaml: remove global CKV_K8S_21/28/30 suppressions; rely on per-file
inline checkov:skip comments in cloudrun-service.yaml so future real K8s
manifests are not silently exempted
checkov scans deploy/gcp/cloudrun-service.yaml as a Kubernetes resource
because it has apiVersion: serving.knative.dev/v1. It flags CKV_K8S_21
('default namespace should not be used') because Cloud Run services have
no metadata.namespace field — they are project/region scoped, not
namespace scoped. Add CKV_K8S_21 to .checkov.yaml skip-check and to the
inline skip comment in cloudrun-service.yaml.
checkov scans deploy/gcp/cloudrun-service.yaml as a Kubernetes resource
(it has apiVersion: serving.knative.dev/v1) and raises CKV_K8S_28 /
CKV_K8S_30. Adding those annotations to spec.template.metadata.annotations
caused checkov to crash (exit 1 with no SARIF output) — likely a bug in
checkov's AppArmor check when it tries to match the annotation container
name against containers in a Knative RevisionSpec. Fix:
- Remove the AppArmor / seccomp annotations from the template metadata
- Add checkov:skip comments at the file top so the false-positive checks
are suppressed cleanly (Cloud Run enforces these at platform level)
Also drop the legacy seccomp.security.alpha.kubernetes.io/pod annotation
from deploy/helm/knowledge-explorer/values.yaml: run #186 confirmed that
the modern podSecurityContext.seccompProfile.type: RuntimeDefault field
already satisfies CKV_K8S_28 for the Helm chart without the annotation.
Adding the annotation alongside the modern field was causing the same
crash in checkov's Helm-rendered output.
checkov crashes (exit 1) on two constructs introduced in earlier commits:
1. deploy/gcp/cloudrun-service.yaml: pod-level spec.template.spec.securityContext
is not part of Knative RevisionSpec. checkov's Knative parser panics on
this unknown field. Remove it — CKV_K8S_28 (seccomp) and CKV_K8S_30
(AppArmor) are already satisfied by the legacy annotations in
spec.template.metadata.annotations; the container-level securityContext
that IS valid in Cloud Run Gen 2 is kept.
2. deploy/azure/main.bicep: 'vnetInternal ? { ... } : null' compiles to
ARM null() which crashes checkov's Bicep/ARM parser. Replace the inline
null ternary with two concrete variable objects (vnetConfigInternal and
vnetConfigExternal) so both branches are well-typed objects.
AZR-000363 (Azure.ContainerApp.PublicAccess) — line 29 managedEnvironment:
- Add vnetConfiguration.internal: true (default) so the environment uses
an internal load balancer instead of a public IP
- Parameterize with vnetInternal (bool, default true) and
infrastructureSubnetId so operators can provide their subnet on deploy
AZR-000361 (Azure.ContainerApp.ManagedIdentity) — line 40 containerApp:
- Add identity.type = SystemAssigned so the Container App can
authenticate to Azure services without storing credentials
Also update main.parameters.json and README with the new parameters.
The 2 active checkov HIGH results (CKV_K8S_28 + CKV_K8S_30) were coming
from deploy/gcp/cloudrun-service.yaml — checkov scans it as a Kubernetes
resource (apiVersion: serving.knative.dev/v1) and flagged missing AppArmor
and seccomp on that file, regardless of the fixes made to the k8s/ and
helm/ manifests.
deploy/gcp/cloudrun-service.yaml:
- Add container name (explorer) so AppArmor annotation key matches
- Add AppArmor annotation to pod template metadata (CKV_K8S_30)
- Add legacy seccomp annotation (AC_K8S_0080 / CKV_K8S_28)
- Add pod-level seccompProfile: RuntimeDefault (CKV_K8S_28)
- Add container securityContext (runAsNonRoot, allowPrivilegeEscalation)
Cloud Run Gen 2 supports all of these fields
deploy/kubernetes/deployment.yaml:
- Pin image tag from ':latest' to ':0.5.0' (AC_K8S_0068 / AC_K8S_0069)
- Add legacy seccomp pod annotation alongside existing seccompProfile field
deploy/helm/knowledge-explorer/values.yaml:
- Add legacy seccomp annotation to podAnnotations so it renders into
the Helm-generated pod template alongside the modern seccompProfile
checkov HIGH (2 breaking results, CKV_K8S_30):
- Add AppArmor annotation to k8s deployment pod template
(container.apparmor.security.beta.kubernetes.io/explorer: runtime/default)
- Add AppArmor annotation via Helm values.yaml podAnnotations so it
renders into the Helm-generated pod template
Terrascan warnings (AC_K8S_0087 / AC_K8S_0080 / AC_K8S_0073):
- Add runAsNonRoot: true and seccompProfile: RuntimeDefault at container
securityContext level in both k8s deployment and Helm values (these
were only at pod spec level before)
Terrascan AC_K8S_0002 (noHttps):
- Add nginx ssl-redirect annotation to k8s ingress so HTTPS enforcement
is explicit at the ingress controller layer
Terrascan AC_K8S_0013 (noOwnerLabel):
- Add owner label to k8s namespace.yaml
Terrascan AC_K8S_0068 (imageWithLatestTag):
- Change Helm values.yaml image.tag from 'latest' to '' (falls back to
.Chart.AppVersion at render time)
- Pin values.prod.yaml to explicit release tag 0.5.0
- GCP: remove --allow-unauthenticated, restrict ingress to
internal-and-cloud-load-balancing, replace wildcard ALLOWED_ORIGINS=*
with a substitution variable (_ALLOWED_ORIGINS) so operators supply a
real URL at deploy time; same fix in cloudrun-service.yaml
- Fly.io: replace hardcoded FALKORDB_HOST=localhost with the correct
.internal private-network hostname pattern; update README accordingly
- docker-compose.dev.yml: add missing top-level networks: block so the
frontend service can join the semantica network without --file layering
- K8s/Helm: add readOnlyRootFilesystem: true + runAsUser: 1000 to
container securityContext; mount an emptyDir /tmp so uvicorn can write
temp files
- app.py: fix _read_explorer_settings() or-chain, use in os.environ
checks so an explicit ALLOWED_ORIGINS="" produces an empty allow-list
instead of silently falling through to localhost defaults; remove dead
app.state.falkordb_host/port attributes
- docs: update four locations that still documented {"status":"healthy"}
to reflect the new {"status":"ok"} health response
- tests: update test assertion to read falkordb settings from
app.state.explorer_settings instead of removed top-level attributes