Back to skill

Security audit

Linux Security Scanner

Security checks for vulnerabilities and agentic risk

Overview

This Linux audit skill mostly does what it says, but its script can turn crafted SSH configuration values into shell commands, which is risky if run as root.

Install only if you are comfortable reviewing and fixing the shell script first. The audit checks are coherent and local, but do not run this as sudo/root on systems where SSH configuration content might be attacker-controlled; replace the dynamic bash -c SSH summary with fixed printf-style handling before privileged use.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/security-audit.sh:61
Finding
Command Injection Through Dynamically Constructed SSH Configuration Summary<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security-audit.sh`, lines 61-99 **Vulnerability Type**: OS command injection through `bash -c` **Risk Level**: High ### Vulnerable Code ```bash local permit_root="$(echo "$sshd_config" | grep -iE '^\s*PermitRootLogin\s' | awk '{print $2}')" if [[ "$permit_root" == "yes" || "$permit_root" == "prohibit-password" || "$permit_root" == "without-password" ]]; then warn "PermitRootLogin is set to '$permit_root' (consider 'no')" elif [[ "$permit_root" == "no" ]]; then pass "PermitRootLogin is 'no'" else info "PermitRootLogin not explicitly set (default may allow root)" fi local password_auth="$(echo "$sshd_config" | grep -iE '^\s*PasswordAuthentication\s' | awk '{print $2}')" if [[ "$password_auth" == "yes" || -z "$password_auth" ]]; then warn "PasswordAuthentication is enabled or not set (consider key-only auth)" elif [[ "$password_auth" == "no" ]]; then pass "PasswordAuthentication is disabled" fi local port="$(echo "$sshd_config" | grep -iE '^\s*Port\s' | awk '{print $2}')" if [[ -n "$port" ]]; then info "SSH is listening on port $port" else info "SSH is on default port 22" fi local protocol="$(echo "$sshd_config" | grep -iE '^\s*Protocol\s' | awk '{print $2}')" if [[ -n "$protocol" && "$protocol" != "2" ]]; then fail "Protocol is '$protocol' (should be 2)" fi gather_section "SSH Configuration Summary" bash -c "echo 'PermitRootLogin: ${permit_root:-not set}'; echo 'PasswordAuthentication: ${password_auth:-not set}'; echo 'Port: ${port:-22}'" ``` ### Technical Analysis The script reads values from `/etc/ssh/sshd_config` and `/etc/ssh/sshd_config.d/*.conf`, extracts selected fields, and interpolates them directly into a command string passed to `bash -c`. Although the generated `echo` arguments use single quotes, the configuration values themselves are not shell-escaped. An attacker-controlled value containing a single quote can terminate the intended quoted argument ...[truncated 2306 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove the dynamically generated `bash -c` invocation. These values do not require shell evaluation and should be appended to the report as plain data. A safe replacement is: ```bash gather_ssh_summary() { printf 'PermitRootLogin: %s\n' "${permit_root:-not set}" printf 'PasswordAuthentication: %s\n' "${password_auth:-not set}" printf 'Port: %s\n' "${port:-22}" } gather_section "SSH Configuration Summary" gather_ssh_summary ``` Alternatively, pass values as positional arguments to a fixed command rather than interpolating them into shell source: ```bash gather_section "SSH Configuration Summary" \ bash -c 'printf "PermitRootLogin: %s\nPasswordAuthentication: %s\nPort: %s\n" "$1" "$2" "$3"' \ _ "${permit_root:-not set}" "${password_auth:-not set}" "${port:-22}" ``` The first approach is preferred because it eliminates the unnecessary nested shell entirely. Additional hardening measures: - Treat every value read from system configuration as untrusted data. - Avoid `eval`, dynamically generated shell commands, and interpolated `bash -c` strings. - Validate extracted values against strict allowlists. For example, require `Port` to be numeric and within the valid TCP port range. - Parse only effective, syntactically valid SSH configuration where possible, such as by using `sshd -T` under controlled conditions. - Ensure `/etc/ssh/sshd_config` and configuration fragments are owned by root and are not writable by unprivileged users or groups. - Add regression tests containing quotes, semicolons, command substitutions, and redirection characters to confirm that configuration values are always handled as data. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (26)

Ae1

High
Category
analysis-evasion
Content
`scripts/security-audit.sh` — the single entry point for all checks.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
`scripts/security-audit.sh` — the single entry point for all checks.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
`scripts/security-audit.sh` — the single entry point for all checks.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
`scripts/security-audit.sh` — the single entry point for all checks.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
`scripts/security-audit.sh` — the single entry point for all checks.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

YARA rule 'privilege_escalation_tools': Privilege escalation tools and techniques [hacktools]

High
Category
YARA Match
Content
ed directories"
    else
        warn "World-writable files found — review the list above"
    fi

    gather_section "World-Writable Files" bash -c "for d in /etc /tmp /var /home /opt; do [ -d \"\$d\" ] && find \"\$d\" -maxdepth 3 -type f -perm -0002 2>/dev/null; done | head -50"
}

check_suid() {
    section "SUID Binaries"

    echo "Finding SUID bit set on binaries..."
    local suid_list=$(find / -perm -4000 -type f 2>/dev/null | sort)

    if [[ -z "$suid_list" ]]; then
        info "No SUID binaries found"
        return
    fi

    echo "$suid_list"
    echo ""

    local known_risky=("pkexec" "passwd" "sudo" "su" "mount" "umount" "chsh" "chfn" "newgrp" "gpasswd")
    local risky_found=()

    for bin in $suid_list; do
        local name=$(basename "$bin")
        for risky in "${known_risky[@]}"; do
            if [[ "$name" == "$risky" ]]; then
                risky_found+=("$bin")
                break
            fi
        done
    done

    if [[ ${#risky_found[@]} -gt
Confidence
75% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Unsafe Defaults

Medium
Category
Tool Misuse
Content
---
name: linux-security-scanner
description: Linux security auditing tool that checks SSH configuration, open/listening ports, firewall rules (ufw/iptables/nftables), failed login attempts, sudoers permissions, world-writable files, and SUID binaries. Use when a user needs a security posture assessment, hardening audit, or compliance check on a Linux host — run individual checks or a full comprehensive audit with a formatted report.
---

# Linux Security Scanner
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
---
name: linux-security-scanner
description: Linux security auditing tool that checks SSH configuration, open/listening ports, firewall rules (ufw/iptables/nftables), failed login attempts, sudoers permissions, world-writable files, and SUID binaries. Use when a user needs a security posture assessment, hardening audit, or compliance check on a Linux host — run individual checks or a full comprehensive audit with a formatted report.
---

# Linux Security Scanner
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
---
name: linux-security-scanner
description: Linux security auditing tool that checks SSH configuration, open/listening ports, firewall rules (ufw/iptables/nftables), failed login attempts, sudoers permissions, world-writable files, and SUID binaries. Use when a user needs a security posture assessment, hardening audit, or compliance check on a Linux host — run individual checks or a full comprehensive audit with a formatted report.
---

# Linux Security Scanner
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
---
name: linux-security-scanner
description: Linux security auditing tool that checks SSH configuration, open/listening ports, firewall rules (ufw/iptables/nftables), failed login attempts, sudoers permissions, world-writable files, and SUID binaries. Use when a user needs a security posture assessment, hardening audit, or compliance check on a Linux host — run individual checks or a full comprehensive audit with a formatted report.
---

# Linux Security Scanner
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
---
name: linux-security-scanner
description: Linux security auditing tool that checks SSH configuration, open/listening ports, firewall rules (ufw/iptables/nftables), failed login attempts, sudoers permissions, world-writable files, and SUID binaries. Use when a user needs a security posture assessment, hardening audit, or compliance check on a Linux host — run individual checks or a full comprehensive audit with a formatted report.
---

# Linux Security Scanner
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
---
name: linux-security-scanner
description: Linux security auditing tool that checks SSH configuration, open/listening ports, firewall rules (ufw/iptables/nftables), failed login attempts, sudoers permissions, world-writable files, and SUID binaries. Use when a user needs a security posture assessment, hardening audit, or compliance check on a Linux host — run individual checks or a full comprehensive audit with a formatted report.
---

# Linux Security Scanner
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| `--ports` | Listening TCP ports (ss or netstat) |
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| `--ports` | Listening TCP ports (ss or netstat) |
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| `--ports` | Listening TCP ports (ss or netstat) |
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
| `--ports` | Listening TCP ports (ss or netstat) |
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |

Example:
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |

Example:
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
| `--firewall` | ufw status, iptables filter rules, nftables ruleset |
| `--failed-logins` | lastb output and journalctl SSH auth failures (last 24h) |
| `--sudoers` | Sudoers file permissions (must be 440), files present, NOPASSWD entries, full sudo access grants |
| `--world-writable` | World-writable files in /etc, /tmp, /var, /home, /opt (depth 3) |
| `--suid` | All SUID binaries, risk assessment, unusual path detection |

Example:
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
gather_section "Sudoers Audit" bash -c "echo 'Files:'; find /etc/sudoers /etc/sudoers.d -type f 2>/dev/null; echo '---'; echo 'NOPASSWD:'; grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d 2>/dev/null || echo 'none'; echo 'Full sudo:'; grep -r 'ALL=(ALL:ALL) ALL' /etc/sudoers /etc/sudoers.d 2>/dev/null || echo 'none'"
}

check_world_writable() {
    section "World-Writable Files"

    local dirs=("/etc" "/tmp" "/var" "/home" "/opt")
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
gather_section "Sudoers Audit" bash -c "echo 'Files:'; find /etc/sudoers /etc/sudoers.d -type f 2>/dev/null; echo '---'; echo 'NOPASSWD:'; grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d 2>/dev/null || echo 'none'; echo 'Full sudo:'; grep -r 'ALL=(ALL:ALL) ALL' /etc/sudoers /etc/sudoers.d 2>/dev/null || echo 'none'"
}

check_world_writable() {
    section "World-Writable Files"

    local dirs=("/etc" "/tmp" "/var" "/home" "/opt")
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
gather_section "Sudoers Audit" bash -c "echo 'Files:'; find /etc/sudoers /etc/sudoers.d -type f 2>/dev/null; echo '---'; echo 'NOPASSWD:'; grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d 2>/dev/null || echo 'none'; echo 'Full sudo:'; grep -r 'ALL=(ALL:ALL) ALL' /etc/sudoers /etc/sudoers.d 2>/dev/null || echo 'none'"
}

check_world_writable() {
    section "World-Writable Files"

    local dirs=("/etc" "/tmp" "/var" "/home" "/opt")
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
}

check_world_writable() {
    section "World-Writable Files"

    local dirs=("/etc" "/tmp" "/var" "/home" "/opt")
    local found=0
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
}

check_world_writable() {
    section "World-Writable Files"

    local dirs=("/etc" "/tmp" "/var" "/home" "/opt")
    local found=0
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The manifest says the skill can run a full audit with a formatted report, and the script builds a REPORT variable throughout execution. However, at the end it only states that raw audit data is stored in the shell variable and does not print, save, or otherwise return the formatted report, so the documented/reporting intent diverges from actual behavior.

Static analysis

No suspicious patterns detected.