-
Notifications
You must be signed in to change notification settings - Fork 1
feat: full rule sweep for the four lagging apps + restore per-attack card info #168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
ae478f1
e5b1392
09b99e9
b364704
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| apiVersion: spdx.softwarecomposition.kubescape.io/v1beta1 | ||
| kind: ContainerProfile | ||
| metadata: | ||
| name: argocd-application-controller | ||
| namespace: argocd | ||
| annotations: | ||
| kubescape.io/managed-by: User | ||
| spec: | ||
| architectures: [amd64] | ||
| execs: | ||
| - path: /usr/bin/tini | ||
| args: [/usr/bin/tini, "⋯⋯"] | ||
| - path: /usr/local/bin/argocd | ||
| args: [/usr/local/bin/argocd-application-controller, "⋯⋯"] | ||
| opens: | ||
| - {path: /etc/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/apache/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/apache2/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/httpd/conf/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/share/mime/globs2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/share/mime/globs2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/ld.so.cache, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/passwd, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/hosts, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/nsswitch.conf, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/resolv.conf, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libc.so.6, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/bin/argocd, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/share/zoneinfo/Etc/UTC, flags: [O_RDONLY]} | ||
| - {path: /home/argocd/.kube/config, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /run/secrets/kubernetes.io/serviceaccount/⋯/ca.crt, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /run/secrets/kubernetes.io/serviceaccount/⋯/namespace, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /run/secrets/kubernetes.io/serviceaccount/⋯/token, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /proc/⋯/net/core/somaxconn, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /proc/⋯/task/1/fd, flags: [O_RDONLY, O_DIRECTORY, O_CLOEXEC]} | ||
| - {path: /sys/kernel/mm/transparent_hugepage/hpage_pmd_size, flags: [O_RDONLY]} | ||
| capabilities: [] | ||
| endpoints: [] | ||
| rulePolicies: | ||
| R0002: | ||
| processAllowed: ["runc:[1:INIT]", "runc:[1:CHILD]", "runc:[2:INIT]", "runc:[3:INIT]"] | ||
| R0004: | ||
| processAllowed: ["runc:[1:INIT]", "runc:[1:CHILD]", "runc:[2:INIT]", "runc:[3:INIT]"] | ||
| R0006: | ||
| processAllowed: ["argocd-applicat"] | ||
| matchLabels: | ||
| app.kubernetes.io/name: argocd-application-controller | ||
| ingress: | ||
| - identifier: metrics-scrape | ||
| type: internal | ||
| ports: | ||
| - {name: TCP-8082, port: 8082, protocol: TCP} | ||
| egress: | ||
| - identifier: kube-apiserver | ||
| type: internal | ||
| ipAddress: 10.43.0.1 | ||
| ports: | ||
| - {name: TCP-443, port: 443, protocol: TCP} | ||
| - identifier: argocd-redis | ||
| type: internal | ||
| podSelector: | ||
| matchLabels: | ||
| app.kubernetes.io/name: argocd-redis | ||
| ports: | ||
| - {name: TCP-6379, port: 6379, protocol: TCP} | ||
| - identifier: cluster-dns | ||
| type: internal | ||
| podSelector: | ||
| matchLabels: | ||
| k8s-app: kube-dns | ||
| ports: | ||
| - {name: UDP-53, port: 53, protocol: UDP} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| apiVersion: spdx.softwarecomposition.kubescape.io/v1beta1 | ||
| kind: ContainerProfile | ||
| metadata: | ||
| name: argocd-applicationset-controller | ||
| namespace: argocd | ||
| annotations: | ||
| kubescape.io/managed-by: User | ||
| spec: | ||
| architectures: [amd64] | ||
| execs: | ||
| - path: /usr/bin/tini | ||
| args: [/usr/bin/tini, "⋯⋯"] | ||
| - path: /usr/local/bin/argocd | ||
| args: [/usr/local/bin/argocd-applicationset-controller, "⋯⋯"] | ||
| opens: | ||
| - {path: /etc/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/apache/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/apache2/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/httpd/conf/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/share/mime/globs2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/share/mime/globs2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/ld.so.cache, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/passwd, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libc.so.6, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/bin/argocd, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/share/zoneinfo/Etc/UTC, flags: [O_RDONLY]} | ||
| - {path: /home/argocd/.kube/config, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /run/secrets/kubernetes.io/serviceaccount/⋯/ca.crt, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /run/secrets/kubernetes.io/serviceaccount/⋯/namespace, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /run/secrets/kubernetes.io/serviceaccount/⋯/token, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /proc/⋯/net/core/somaxconn, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /proc/⋯/task/1/fd, flags: [O_RDONLY, O_DIRECTORY, O_CLOEXEC]} | ||
| - {path: /sys/kernel/mm/transparent_hugepage/hpage_pmd_size, flags: [O_RDONLY]} | ||
| capabilities: [] | ||
| endpoints: [] | ||
| rulePolicies: | ||
| R0002: | ||
| processAllowed: ["runc:[1:INIT]", "runc:[1:CHILD]", "runc:[2:INIT]", "runc:[3:INIT]"] | ||
| R0004: | ||
| processAllowed: ["runc:[1:INIT]", "runc:[1:CHILD]", "runc:[2:INIT]", "runc:[3:INIT]"] | ||
| R0006: | ||
| processAllowed: ["argocd-applicat"] | ||
| matchLabels: | ||
| app.kubernetes.io/name: argocd-applicationset-controller | ||
| ingress: | ||
| - identifier: webhook-and-metrics | ||
| type: internal | ||
| ports: | ||
| - {name: TCP-7000, port: 7000, protocol: TCP} | ||
| - {name: TCP-8080, port: 8080, protocol: TCP} | ||
| egress: | ||
| - identifier: kube-apiserver | ||
| type: internal | ||
| ipAddress: 10.43.0.1 | ||
| ports: | ||
| - {name: TCP-443, port: 443, protocol: TCP} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| apiVersion: spdx.softwarecomposition.kubescape.io/v1beta1 | ||
| kind: ContainerProfile | ||
| metadata: | ||
| name: argocd-repo-server | ||
| namespace: argocd | ||
| annotations: | ||
| kubescape.io/managed-by: User | ||
| spec: | ||
| architectures: [amd64] | ||
| execs: | ||
| - path: /usr/bin/tini | ||
| args: [/usr/bin/tini, "⋯⋯"] | ||
| - path: /usr/local/bin/argocd | ||
| args: [/usr/local/bin/argocd-repo-server, "⋯⋯"] | ||
| - path: /usr/bin/gpg | ||
| args: [/usr/bin/gpg, "⋯⋯"] | ||
| - path: /usr/bin/gpg-agent | ||
| args: [/usr/bin/gpg-agent, "⋯⋯"] | ||
| - path: /usr/bin/dash | ||
| args: [/usr/local/bin/gpg-wrapper.sh, "⋯⋯"] | ||
| opens: | ||
| - {path: /app/config/gpg/keys/⋯, flags: [O_WRONLY, O_CREAT, O_EXCL]} | ||
| - {path: /app/config/gpg/keys/.argocd-generated, flags: [O_WRONLY, O_CREAT, O_TRUNC, O_CLOEXEC]} | ||
| - {path: /app/config/gpg/keys/gpg-agent.conf, flags: [O_RDONLY]} | ||
| - {path: /app/config/gpg/keys/gpg.conf, flags: [O_RDONLY]} | ||
| - {path: /app/config/gpg/keys/pubring.gpg, flags: [O_RDONLY]} | ||
| - {path: /app/config/gpg/keys/pubring.kbx, flags: [O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC]} | ||
| - {path: /app/config/gpg/keys/pubring.kbx.lock, flags: [O_RDONLY]} | ||
| - {path: /app/config/gpg/keys/pubring.kbx.tmp, flags: [O_WRONLY, O_CREAT, O_TRUNC]} | ||
| - {path: /app/config/gpg/keys/trustdb.gpg, flags: [O_RDWR, O_WRONLY, O_CREAT, O_TRUNC]} | ||
| - {path: /app/config/gpg/keys/trustdb.gpg.lock, flags: [O_RDONLY]} | ||
| - {path: /app/config/gpg/keys/openpgp-revocs.d/⋯, flags: [O_CREAT, O_TRUNC, O_WRONLY]} | ||
| - {path: /app/config/gpg/keys/private-keys-v1.d/⋯, flags: [O_CREAT, O_EXCL, O_TRUNC, O_RDONLY, O_WRONLY]} | ||
| - {path: /app/config/gpg/source, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /app/config/gpg/source/⋯, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /tmp/⋯, flags: [O_RDWR, O_CREAT, O_EXCL, O_CLOEXEC, O_RDONLY]} | ||
| - {path: /etc/gcrypt/hwf.deny, flags: [O_RDONLY]} | ||
| - {path: /etc/gcrypt/random.conf, flags: [O_RDONLY]} | ||
| - {path: /etc/gnupg/gpg-agent.conf, flags: [O_RDONLY]} | ||
| - {path: /etc/gnupg/gpg.conf, flags: [O_RDONLY]} | ||
| - {path: /dev/urandom, flags: [O_RDONLY]} | ||
| - {path: /dev/null, flags: [O_RDONLY, O_CLOEXEC, O_WRONLY]} | ||
| - {path: /etc/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/apache/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/apache2/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/httpd/conf/mime.types, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/share/mime/globs2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/share/mime/globs2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/ld.so.cache, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/passwd, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/hosts, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/nsswitch.conf, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /etc/resolv.conf, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/share/zoneinfo/Etc/UTC, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /home/argocd, flags: [O_RDONLY, O_NONBLOCK, O_DIRECTORY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libc.so.6, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libm.so.6, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libz.so.1.2.11, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libbz2.so.1.0.4, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libassuan.so.0.8.5, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libgcrypt.so.20.3.4, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libgpg-error.so.0.32.1, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libnpth.so.0.1.2, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libreadline.so.8.1, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/lib/x86_64-linux-gnu/libtinfo.so.6.3, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/bin/argocd, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /usr/local/bin/gpg-wrapper.sh, flags: [O_RDONLY]} | ||
| - {path: /proc/⋯/net/core/somaxconn, flags: [O_RDONLY, O_CLOEXEC]} | ||
| - {path: /proc/⋯/task/1/fd, flags: [O_RDONLY, O_DIRECTORY, O_CLOEXEC]} | ||
| - {path: /proc/⋯/fd, flags: [O_RDONLY, O_NONBLOCK, O_DIRECTORY, O_CLOEXEC]} | ||
| - {path: /sys/kernel/mm/transparent_hugepage/hpage_pmd_size, flags: [O_RDONLY]} | ||
| capabilities: [] | ||
| endpoints: [] | ||
| rulePolicies: | ||
| R0002: | ||
| processAllowed: ["runc:[1:INIT]", "runc:[1:CHILD]", "runc:[2:INIT]", "runc:[3:INIT]"] | ||
| R0004: | ||
| processAllowed: ["runc:[1:INIT]", "runc:[1:CHILD]", "runc:[2:INIT]", "runc:[3:INIT]"] | ||
| matchLabels: | ||
| app.kubernetes.io/name: argocd-repo-server | ||
| ingress: | ||
| - identifier: argocd-grpc-clients | ||
| type: internal | ||
| ports: | ||
| - {name: TCP-8081, port: 8081, protocol: TCP} | ||
| - identifier: metrics-scrape | ||
| type: internal | ||
| ports: | ||
| - {name: TCP-8084, port: 8084, protocol: TCP} | ||
| egress: null |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -373,3 +373,74 @@ attacks: | |||||||||||||||||||||||||
| successIndicators: | ||||||||||||||||||||||||||
| - responseContains: "1" | ||||||||||||||||||||||||||
| expectedDetections: [] | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| # ── Full rule-family sweep (scripts/emit-rule-sweep.py) ───────────────────── | ||||||||||||||||||||||||||
| # Primitives probed on the live container: staging dir, real mount, interpreter. | ||||||||||||||||||||||||||
| # Anything that misses on the dogfood run must be demoted to a probe WITH a reason. | ||||||||||||||||||||||||||
| - name: dns-anomaly-lookup | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["sh", "-c", "getent hosts scanner.evil-c2.example.com >/dev/null 2>&1 && echo dns_resolved || echo dns_attempted"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "dns_" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R0005, ruleName: DNS Anomalies in container, containerName: client } | ||||||||||||||||||||||||||
| - name: sa-token-read | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["sh", "-c", "cat /var/run/secrets/kubernetes.io/serviceaccount/token >/dev/null 2>&1 && echo sa_token_read_done || echo sa_token_absent"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "sa_token_read_done" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R0006, ruleName: Unexpected service account token access, containerName: client, command: cat } | ||||||||||||||||||||||||||
|
Comment on lines
+386
to
+391
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "## Locate files"
fd -a 'mariadb-attacks\.yaml|postgres-attacks\.yaml|.*attacks\.yaml$' . | sed 's#^\./##' | head -100
echo
echo "## mariadb lines around sa-token-read"
if [ -f example/mariadb-attacks.yaml ]; then
wc -l example/mariadb-attacks.yaml
sed -n '360,405p' example/mariadb-attacks.yaml | cat -n
fi
echo
echo "## Search related terms"
rg -n "sa[-_]?token|sa_token_?done|sa_token_absent|dns-anomaly-lookup|dns_|attempt|mounted|Rabbit|PR119" example -g '*.yaml' || true
echo
echo "## postgres candidate excerpt"
if [ -f example/postgres-attacks.yaml ]; then
wc -l example/postgres-attacks.yaml
rg -n -C 6 "rabbit|attempt|mounted|saml|token|dns-" example/postgres-attacks.yaml || true
fiRepository: k8sstormcenter/bob Length of output: 47086 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "## Locate files"
fd -a 'mariadb-attacks\.yaml|postgres-attacks\.yaml|.*attacks\.yaml$' . | sed 's#^\./##' | head -100
echo
echo "## mariadb lines around sa-token-read"
if [ -f example/mariadb-attacks.yaml ]; then
wc -l example/mariadb-attacks.yaml
sed -n '360,405p' example/mariadb-attacks.yaml | cat -n
fi
echo
echo "## Search related terms"
rg -n "sa[-_]?token|sa_token_?done|sa_token_absent|dns-anomaly-lookup|dns_|attempt|mounted|Rabbit|PR119" example -g '*.yaml' || true
echo
echo "## postgres candidate excerpt"
if [ -f example/postgres-attacks.yaml ]; then
wc -l example/postgres-attacks.yaml
rg -n -C 8 "rabbit|attempt|mounted|saml|token|dns-" example/postgres-attacks.yaml || true
fiRepository: k8sstormcenter/bob Length of output: 48498 Accept the absent-SA-token branch for
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| - name: k8s-api-unexpected-call | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["perl", "-e", "use Socket; socket(my $s,PF_INET,SOCK_STREAM,getprotobyname('tcp')); connect($s,sockaddr_in(443,inet_aton('10.43.0.1'))); close($s); print qq{k8s_api_probe_done}"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "k8s_api_probe_done" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R0007, ruleName: Workload uses Kubernetes API unexpectedly, containerName: client } | ||||||||||||||||||||||||||
|
Comment on lines
+392
to
+397
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win Hardcoded cluster IP for the Kubernetes API.
Suggested fix- exec: { command: ["perl", "-e", "use Socket; socket(my $s,PF_INET,SOCK_STREAM,getprotobyname('tcp')); connect($s,sockaddr_in(443,inet_aton('10.43.0.1'))); close($s); print qq{k8s_api_probe_done}"] }
+ exec: { command: ["sh", "-c", "perl -e 'use Socket; socket(my $s,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\")); connect($s,sockaddr_in($ENV{KUBERNETES_SERVICE_PORT},inet_aton($ENV{KUBERNETES_SERVICE_HOST}))); close($s); print qq{k8s_api_probe_done}'"] }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| - name: exec-proc-environ | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["cat", "/proc/1/environ"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "PATH" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R0008, ruleName: Read Environment Variables from procfs, containerName: client, command: cat } | ||||||||||||||||||||||||||
| - name: exec-etc-shadow | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["cat", "/etc/shadow"] } | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R0010, ruleName: Unexpected Sensitive File Access, containerName: client, command: cat } | ||||||||||||||||||||||||||
|
Comment on lines
+404
to
+408
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check bobctl's AttackSuite runner/reporting for how it keys results by attack name.
rg -n "attack.Name" --type=go -C3 -g '!vendor/*' | head -50
rg -n "\bname\b" -g 'pkg/**/*.go' -C2 | rg -i "attack|suite" | head -50Repository: k8sstormcenter/bob Length of output: 156 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Repo files matching attack/suite:"
git ls-files | rg -i 'attack|suite|bobctl|cli|cmd|pkg' | head -200
echo
echo "Find yaml files:"
git ls-files | rg 'yaml$|yml$' | sed -n '1,120p'
echo
echo "Search for name key usage:"
rg -n '\bname\b[:=].*' -g '*.go' -g '*.yaml' -g '*.yml' . | sed -n '1,200p'Repository: k8sstormcenter/bob Length of output: 20979 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "mariadb attack entries with name exec-etc-shadow:"
rg -n -C3 'exec-etc-shadow|cat \"/etc/shadow\"|etc/shadow' example/mariadb-attacks.yaml
echo
echo "Go files under pkg with relevant terms:"
git ls-files pkg | rg '\.go$' | sed -n '1,200p'
echo
echo "Search relevant terms in Go package:"
rg -n 'struct|Attack|Commands|Expected|Results|Name|RuleID|ruleID|cmdinject|func ' pkg --type=go | sed -n '1,260p'Repository: k8sstormcenter/bob Length of output: 1884 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "List repository top-level:"
git ls-files | sed 's#/.*$##' | sort -u
echo
echo "Find files with Attack/Command/Result structs and parsing code:"
rg -n 'Attack|AttackSuite|cmdinject|Command\[|Commands|expectedDetections|RuleID|ruleID|Results|Result|yaml|unmarshal' -g '*.go' . | sed -n '1,300p'
echo
echo "All .go files:"
git ls-files '*.go' | awk -F/ '{print $NF}' | sort | uniq -c | sort -k2 | sed -n '1,100p'
rg -n 'package ' -g '*.go' . | sed -n '1,200p'Repository: k8sstormcenter/bob Length of output: 996 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Parse YAML attack entries in example/mariadb-attacks.yaml:"
python3 - <<'PY'
import re
from pathlib import Path
p = Path('example/mariadb-attacks.yaml')
text = p.read_text()
entries = []
for m in re.finditer(r'^ - name: (.+?)(?:\n|$)', text, flags=re.M):
name = m.group(1).strip()
# Find beginning of this list item and the next top-level list marker.
item_start = m.start()
for n in re.finditer(r'^ - \w*:', text, flags=re.M):
if n.start() > item_start:
item = text[item_start:n.start()]
break
else:
item = text[item_start:]
command = re.search(r'exec:\s*\{\s*command:\s*\[(.*?)\]\s*\}', item, flags=re.S)
commands = [part.strip().strip('"').strip("'") for part in command.group(1).split(',') if part.strip()] if command else []
expected_ruleids = re.findall(r'\bruleID:\s*(\w+)', item)
entries.append((name, commands, expected_ruleids))
seen = {}
for name, commands, ruleids in entries:
key = (commands, tuple(ruleids))
hits = seen.setdefault(key, [])
hits.append(name)
print(f"total entries: {len(entries)}")
dupes = {k: names for k, names in seen.items() if len(names) > 1}
print(f"duplicate (name, commands, ruleIDs): {len(dupes)}")
for names in dupes.values():
print(names)
print("exec-etc-shadow occurrences:")
for name, commands, ruleids in entries:
if name == 'exec-etc-shadow':
print(name, commands, ruleids)
PY
echo
echo "Search unique name keys in mariadb:"
python3 - <<'PY'
import re
from pathlib import Path
names = re.findall(r'^\s*-\s+name:\s*(.+?)(?:\n|$)', Path('example/mariadb-attacks.yaml').read_text(), flags=re.M)
from collections import Counter
for name, count in Counter(names).items():
if count > 1:
print(count, name)
PYRepository: k8sstormcenter/bob Length of output: 324 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
import re
from pathlib import Path
from collections import Counter
text = Path('example/mariadb-attacks.yaml').read_text()
lines = text.splitlines()
names = []
commands_by_name = {}
expected_ruleids_by_name = {}
current = None
for line in lines:
mo = re.match(r'^ - name:\s*(.+?)$', line)
if mo:
current = mo.group(1).strip()
names.append(current)
commands_by_name[current] = []
expected_ruleids_by_name[current] = []
elif current is not None:
for cmd in re.findall(r'command:\s*\[(.*?)]', line):
commands_by_name[current].append([p.strip().strip('"\'') for p in cmd.split(',')])
for rid in re.findall(r'ruleID:\s*(\w+)', line):
expected_ruleids_by_name[current].append(rid)
seen = {}
for name, commands, ruleids in zip(names, [commands_by_name[n] or [[]] for n in names], [expected_ruleids_by_name[n] or [] for n in names]):
key = tuple(tuple(c) for c in commands), tuple(ruleids)
hits = seen.setdefault(key, [])
hits.append(name)
print(f"total attack names: {len(names)}")
print("duplicate names:", [name for name, count in Counter(names).items() if count > 1])
print("duplicate (commands, ruleIDs):")
for names in seen.values():
if len(names) > 1:
print(names)
print("exec-etc-shadow entries:")
for idx, name in enumerate(names):
if name == 'exec-etc-shadow':
print(idx, name, commands_by_name.get(name), expected_ruleids_by_name.get(name))
PY
echo
echo "Check mariadb attack file first lines and outline around full rule-family block:"
sed -n '1,60p; 240,270p; 396,410p' example/mariadb-attacks.yamlRepository: k8sstormcenter/bob Length of output: 4894 Rename the second
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| - name: egress-external-c2 | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["perl", "-e", "use Socket; socket(my $s,PF_INET,SOCK_STREAM,getprotobyname('tcp')); connect($s,sockaddr_in(80,inet_aton('1.1.1.1'))); close($s); print qq{egress_attempted}"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "egress_attempted" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R0011, ruleName: Unexpected Egress Network Traffic, containerName: client } | ||||||||||||||||||||||||||
| - name: drifted-binary-exec | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["sh", "-c", "cp /bin/ls /dev/shm/drifted_bob && printf '\\n#bob-drift' >> /dev/shm/drifted_bob && chmod +x /dev/shm/drifted_bob && /dev/shm/drifted_bob / >/dev/null 2>&1 && echo drift_exec_done; rm -f /dev/shm/drifted_bob"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "drift_exec_done" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R1000, ruleName: Process executed from malicious source, containerName: client } | ||||||||||||||||||||||||||
| - name: exec-from-volume-mount | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["sh", "-c", "cp /bin/echo /var/lib/mysql/mnt_payload && chmod +x /var/lib/mysql/mnt_payload && /var/lib/mysql/mnt_payload mount_exec_done; rm -f /var/lib/mysql/mnt_payload"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "mount_exec_done" }] | ||||||||||||||||||||||||||
| # Verified unreachable on this container: a successful exec from the | ||||||||||||||||||||||||||
| # /var/lib/mysql volume mount fires R0001 only, and an exec from /dev/shm | ||||||||||||||||||||||||||
| # scores as R1000 on this node-agent build. No path to R1004 here. | ||||||||||||||||||||||||||
| expectedDetections: [] | ||||||||||||||||||||||||||
| - name: fileless-memfd-exec | ||||||||||||||||||||||||||
| type: fileless | ||||||||||||||||||||||||||
| exec: { command: ["perl", "-e", "my $n=\"bobfl\\0\"; my $fd=syscall(319,$n,0); die if $fd<0; open(my $m,'>&='.$fd) or die; open(my $s,'<','/bin/echo') or die; binmode $s; binmode $m; local $/; my $d=<$s>; print $m $d; exec(\"/proc/$$/fd/$fd\",\"memfd_exec_done\");"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "memfd_exec_done" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R1005, ruleName: Fileless execution detected, containerName: client } | ||||||||||||||||||||||||||
|
Comment on lines
+429
to
+434
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value Perl Syscall 319 is 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| - name: crypto-mining-dns | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["sh", "-c", "getent hosts xmr.pool.minergate.com >/dev/null 2>&1 && echo miner_dns_ok || echo miner_dns_attempted"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "miner_dns_" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R1008, ruleName: Crypto Mining Domain Communication, containerName: client } | ||||||||||||||||||||||||||
| - name: hardlink-shadow | ||||||||||||||||||||||||||
| type: cmdinject | ||||||||||||||||||||||||||
| exec: { command: ["sh", "-c", "ln /etc/shadow /dev/shm/hl_probe >/dev/null 2>&1 && echo hardlink_done; rm -f /dev/shm/hl_probe"] } | ||||||||||||||||||||||||||
| successIndicators: [{ responseContains: "hardlink_done" }] | ||||||||||||||||||||||||||
| expectedDetections: | ||||||||||||||||||||||||||
| - { ruleID: R1012, ruleName: Hard link created over sensitive file, containerName: client, command: ln } | ||||||||||||||||||||||||||
|
Comment on lines
+441
to
+446
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== Locate example/mariadb-attacks.yaml and relevant lines =="
if [ -f example/mariadb-attacks.yaml ]; then
wc -l example/mariadb-attacks.yaml
sed -n '430,455p' example/mariadb-attacks.yaml
sed -n '620,645p' example/mariadb-attacks.yaml
else
echo "example/mariadb-attacks.yaml not found"
fd -a -i 'mariadb-attacks\.yaml' .
fi
echo
echo "== Search for hardlink-shadow / hl_probe / R1012 =="
rg -n "hardlink-shadow|hl_probe|Hard link created|R1012|dev/shm|/tmp/hl_probe|ln /etc/shadow" .Repository: k8sstormcenter/bob Length of output: 15142 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== Filesystem characteristics on sandbox =="
df -T / /tmp /dev/shm 2>/dev/null || true
stat -f -c 'dev=%t/%T type=%T fstype=%T' / /tmp /dev/shm 2>/dev/null || true
mount | rg '(/tmp|/dev/shm|rootfs|overlay|tmpfs)' || true
echo
echo "== Static filesystem mountpoint in Docker context or container files =="
for f in Dockerfile docker-compose*.yml docker-compose*.yaml example/mariadb-attacks.yaml README.md; do
if [ -f "$f" ]; then
echo "-- $f"
rg -n "/tmp|/dev/shm|shm|tmpfs|volumes:|container_name|environment:" "$f" || true
fi
done
echo
echo "== Check whether /tmp and root are same mount as observed by df =="
python3 - <<'PY'
from pathlib import Path
root = Path('/mnt') if Path('/mnt').exists() else Path('/')
tmp = Path('/tmp')
shm = Path('/dev/shm')
for p in (root, tmp, shm):
try:
print(f"{p}: exists={p.exists()}, stat_dev={p.stat().st_dev}")
except Exception as e:
print(f"{p}: {e}")
PYRepository: k8sstormcenter/bob Length of output: 1452 Use a same-filesystem target for the hard link probe.
Suggested fix- exec: { command: ["sh", "-c", "ln /etc/shadow /dev/shm/hl_probe >/dev/null 2>&1 && echo hardlink_done; rm -f /dev/shm/hl_probe"] }
+ exec: { command: ["sh", "-c", "ln /etc/shadow /tmp/hl_probe >/dev/null 2>&1 && echo hardlink_done; rm -f /tmp/hl_probe"] }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -434,3 +434,62 @@ attacks: | |
| # ═══════════════════════════════════════════════════════════════════════════ | ||
|
|
||
| # (no probes here — see note above) | ||
|
|
||
| # ── Full rule-family sweep (scripts/emit-rule-sweep.py) ───────────────────── | ||
| # Primitives probed on the live container: staging dir, real mount, interpreter. | ||
| # Anything that misses on the dogfood run must be demoted to a probe WITH a reason. | ||
| - name: sa-token-read | ||
| type: cmdinject | ||
| exec: { command: ["sh", "-c", "cat /var/run/secrets/kubernetes.io/serviceaccount/token >/dev/null 2>&1 && echo sa_token_read_done || echo sa_token_absent"] } | ||
| successIndicators: [{ responseContains: "sa_token_read_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R0006, ruleName: Unexpected service account token access, containerName: pg-client, command: cat } | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| - name: k8s-api-unexpected-call | ||
| type: cmdinject | ||
| exec: { command: ["perl", "-e", "use Socket; socket(my $s,PF_INET,SOCK_STREAM,getprotobyname('tcp')); connect($s,sockaddr_in(443,inet_aton('10.43.0.1'))); close($s); print qq{k8s_api_probe_done}"] } | ||
| successIndicators: [{ responseContains: "k8s_api_probe_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R0007, ruleName: Workload uses Kubernetes API unexpectedly, containerName: pg-client } | ||
|
Comment on lines
+451
to
+456
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win Hardcoded cluster IP for the Kubernetes API. Same concern as 🤖 Prompt for AI Agents |
||
| - name: exec-etc-shadow | ||
| type: cmdinject | ||
| exec: { command: ["cat", "/etc/shadow"] } | ||
| expectedDetections: | ||
| - { ruleID: R0010, ruleName: Unexpected Sensitive File Access, containerName: pg-client, command: cat } | ||
|
Comment on lines
+457
to
+461
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== locate file =="
fd -a 'postgres-attacks\.yaml$' . || true
echo "== occurrences of exec-etc-shadow =="
rg -n "exec-etc-shadow|cat /etc/shadow|ruleID: R0001|ruleID: R0010" example/postgres-attacks.yaml example/mariadb-attacks.yaml 2>/dev/null || true
echo "== relevant postgres sections =="
sed -n '150,190p' example/postgres-attacks.yaml 2>/dev/null || true
sed -n '445,462p' example/postgres-attacks.yaml 2>/dev/null || trueRepository: k8sstormcenter/bob Length of output: 4380 Rename the duplicate
🤖 Prompt for AI Agents |
||
| - name: egress-external-c2 | ||
| type: cmdinject | ||
| exec: { command: ["perl", "-e", "use Socket; socket(my $s,PF_INET,SOCK_STREAM,getprotobyname('tcp')); connect($s,sockaddr_in(80,inet_aton('1.1.1.1'))); close($s); print qq{egress_attempted}"] } | ||
| successIndicators: [{ responseContains: "egress_attempted" }] | ||
| expectedDetections: | ||
| - { ruleID: R0011, ruleName: Unexpected Egress Network Traffic, containerName: pg-client } | ||
| - name: drifted-binary-exec | ||
| type: cmdinject | ||
| exec: { command: ["sh", "-c", "cp /bin/ls /dev/shm/drifted_bob && printf '\\n#bob-drift' >> /dev/shm/drifted_bob && chmod +x /dev/shm/drifted_bob && /dev/shm/drifted_bob / >/dev/null 2>&1 && echo drift_exec_done; rm -f /dev/shm/drifted_bob"] } | ||
| successIndicators: [{ responseContains: "drift_exec_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R1000, ruleName: Process executed from malicious source, containerName: pg-client } | ||
| - name: exec-from-volume-mount | ||
| type: cmdinject | ||
| exec: { command: ["sh", "-c", "cp /bin/echo /var/lib/postgresql/data/mnt_payload && chmod +x /var/lib/postgresql/data/mnt_payload && /var/lib/postgresql/data/mnt_payload mount_exec_done; rm -f /var/lib/postgresql/data/mnt_payload"] } | ||
| successIndicators: [{ responseContains: "mount_exec_done" }] | ||
| # Verified unreachable on this container: /var/lib/postgresql/data is not | ||
| # writable from the client, and a successful exec staged on /dev/shm fires | ||
| # R0001 + R1000, never R1004, on this node-agent build. Honest boundary. | ||
| expectedDetections: [] | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - name: fileless-memfd-exec | ||
| type: fileless | ||
| exec: { command: ["perl", "-e", "my $n=\"bobfl\\0\"; my $fd=syscall(319,$n,0); die if $fd<0; open(my $m,'>&='.$fd) or die; open(my $s,'<','/bin/echo') or die; binmode $s; binmode $m; local $/; my $d=<$s>; print $m $d; exec(\"/proc/$$/fd/$fd\",\"memfd_exec_done\");"] } | ||
| successIndicators: [{ responseContains: "memfd_exec_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R1005, ruleName: Fileless execution detected, containerName: pg-client } | ||
|
Comment on lines
+482
to
+487
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value Hardcoded x86_64 Same portability concern as 🤖 Prompt for AI Agents |
||
| - name: symlink-shadow | ||
| type: cmdinject | ||
| exec: { command: ["ln", "-sf", "/etc/shadow", "/dev/shm/softlink_probe"] } | ||
| successIndicators: [{ responseContains: "" }] | ||
| expectedDetections: | ||
| - { ruleID: R1010, ruleName: Soft link created over sensitive file, containerName: pg-client, command: ln } | ||
| - name: hardlink-shadow | ||
| type: cmdinject | ||
| exec: { command: ["sh", "-c", "ln /etc/shadow /dev/shm/hl_probe >/dev/null 2>&1 && echo hardlink_done; rm -f /dev/shm/hl_probe"] } | ||
| successIndicators: [{ responseContains: "hardlink_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R1012, ruleName: Hard link created over sensitive file, containerName: pg-client, command: ln } | ||
|
Comment on lines
+495
to
+499
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== locate relevant yaml files =="
fd -a 'postgres-attacks.yaml|mariadb-attacks.yaml' . || true
echo "== relevant snippets =="
for f in example/postgres-attacks.yaml example/mariadb-attacks.yaml; do
if [ -f "$f" ]; then
echo "--- $f"
nl -ba "$f" | sed -n '430,510p'
fi
done
echo "== search for similar hardlink probe and docker/compose devices context =="
rg -n "hl_probe|/dev/shm|/etc/shadow|link|hard link|docker|devices|mnt|mount" example/postgres-attacks.yaml example/mariadb-attacks.yaml || true
echo "== filesystem semantics probe == "
tmpdir="$(mktemp -d)"
trap ' rm -rf "$tmpdir" ' EXIT
mkdir -p "$tmpdir/a"
printf 'test' > "$tmpdir/a/file"
set +e
ln "$tmpdir/a/file" "$tmpdir/link" >/dev/null 2>&1 && echo same_fs_success || echo same_fs_link_failed
mkfs.vfat -n TEST "$tmpdir/vfat_img" >/dev/null 2>&1 || true
if [ -b /dev/loop0 ] && modprobe loop >/dev/null 2>&1; then
loopdev="$(losetup -f --show "$tmpdir/vfat_img")"
mkdir -p "$tmpdir/mnt"
mount "$loopdev" "$tmpdir/mnt"
set +e
ln "$tmpdir/a/file" "$tmpdir/mnt/link" >/dev/null 2 >& | sed ''
status=$?
set -e
if [ $status -eq 0 ]; then echo cross_fs_success; else echo cross_fs_link_failed
fiRepository: k8sstormcenter/bob Length of output: 385 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== relevant snippets with grep/head/tail =="
for f in example/postgres-attacks.yaml example/mariadb-attacks.yaml; do
if [ -f "$f" ]; then
echo "--- $f"
awk 'NR>=440 && NR<=505 { printf "%6d\t%s\n", NR, $0 }' "$f"
fi
done
echo "== search for hl_probe and container/device context =="
awk '/hl_probe|\/dev\/shm|\/etc\/shadow|Hard link created|docker:|devices:|container:|pg-client|mariadb|command: ln|type: cmdinject/' \
example/postgres-attacks.yaml example/mariadb-attacks.yaml || true
echo "== same-file vs cross-file ln semantics probe =="
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/a"
printf 'test' > "$tmp/a/file"
set +e
ln "$tmp/a/file" "$tmp/a/link" >/tmp/ln_same_fs.err 2>&1
status=$?
set -e
if [ $status -eq 0 ]; then
echo same_filesystem_success
else
echo same_filesystem_failed "$(cat /tmp/ln_same_fs.err)"
fi
python3 - <<'PY'
import os, tempfile, subprocess, textwrap
with tempfile.TemporaryDirectory() as d:
loop_file = os.path.join(d, "vfat.img")
src="src"; dst="other/link"
os.makedirs(os.path.join(d, src))
open(os.path.join(d, src, "file"), "w").close()
# Try to force a different physical device via mountpoint; loop-only fails where loop is unavailable,
# but the expected EXDEV failure is deterministic across filesystems when mount succeeds.
loopdev=None
if subprocess.call(["modprobe", "loop"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)==0:
subprocess.check_call(["mkfs.vfat", "-n", "TEST", loop_file], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
loopdev=subprocess.check_output(["losetup", "-f", "--show", loop_file], text=True).strip()
mountdir=os.path.join(d, "mnt")
os.makedirs(mountdir)
subprocess.check_call(["mount", loopdev, mountdir],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
try:
res=subprocess.run(["ln", os.path.join(d, src, "file"), os.path.join(mountdir, dst)],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
print("cross_filesystem_probe:", res.returncode, "stdout="+res.stdout.strip(), "stderr="+res.stderr.strip())
finally:
subprocess.call(["umount", mountdir], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
print("cross_filesystem_probe: loop unavailable")
if loopdev:
subprocess.call(["losetup", "-d", loopdev], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
PYRepository: k8sstormcenter/bob Length of output: 15006 Use a same-filesystem staging path for the hardlink probe.
🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: k8sstormcenter/bob
Length of output: 50374
🌐 Web query:
Argo CD application-controller connects to repo-server default host argocd-repo-server:8081 repo-server gRPC port 8081💡 Result:
The Argo CD application-controller communicates with the argocd-repo-server via a gRPC API [1][2][3]. The default address for this connection is argocd-repo-server:8081 [4][5], where 8081 is the standard gRPC port used by the repository server [5][6][7]. Key details regarding this connection include: Communication Protocol: The application-controller and other components (such as argocd-server, argocd-applicationset-controller, and argocd-notifications-controller) use gRPC to request repository operations and manifest generation from the repo-server [2][3]. Default Settings: Address: argocd-repo-server:8081 [4][5] Port: 8081 [5][6][7] TLS: By default, the communication uses TLS, but since the repo-server generates a non-persistent, self-signed certificate on startup that cannot be verified by outside consumers, these components typically use a non-validating connection [1][2][8]. Configuration Options: The address can be overridden using the --repo-server flag [9][10]. TLS validation can be enforced by enabling the --repo-server-strict-tls parameter, which requires setting up a persistent, verifiable TLS certificate [1][2][8]. Alternatively, TLS can be disabled entirely for the connection using the --repo-server-plaintext flag [1][2][8]. The repo-server service is defined in the Argo CD manifests to expose this gRPC endpoint on port 8081 [6][7], alongside a metrics port on 8084 [6][7].
Citations:
🌐 Web query:
Argo CD applicationset-controller default repo server address argocd-repo-server:8081💡 Result:
The default repository server address for the Argo CD ApplicationSet controller is argocd-repo-server:8081 [1][2][3]. This address is defined by the constant DefaultRepoServerAddr within the Argo CD codebase [2] and serves as the default value for the --argocd-repo-server command-line flag used by the applicationset-controller [4][1][5]. Configuration Details: - Flag: --argocd-repo-server [1][3] - Environment Variable: ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER [4][5] - Default Value: argocd-repo-server:8081 [1][3] The ApplicationSet controller uses this address to communicate with the Argo CD repository server, which is an internal service responsible for maintaining a local cache of Git repositories and generating Kubernetes manifests [6]. In standard Kubernetes installations of Argo CD, the service argocd-repo-server is typically exposed on port 8081 for gRPC communication [2][7]. If you need to override this, you can provide a different address via the --argocd-repo-server flag or the corresponding environment variable [4][5].
Citations:
Allow controller access to
argocd-repo-server.Apply the repo-server egress to both controllers so they can reach the Argo CD repo-server gRPC endpoint at
argocd-repo-server:8081. The ApplicationSet profile also needs DNS egress because it resolves that in-cluster service name.example/argocd/sbobs/cp-argocd-application-controller.yaml#L53-L72: add internal TCP/8081 egress selected byapp.kubernetes.io/name: argocd-repo-server.example/argocd/sbobs/cp-argocd-applicationset-controller.yaml#L51-L57: add the same repo-server route and UDP/53 egress tok8s-app: kube-dns.📍 Affects 2 files
example/argocd/sbobs/cp-argocd-application-controller.yaml#L53-L72(this comment)example/argocd/sbobs/cp-argocd-applicationset-controller.yaml#L51-L57🤖 Prompt for AI Agents