Back to skill

Security audit

Arc Sentinel

Security checks for vulnerabilities and agentic risk

Overview

This security-monitoring skill is mostly coherent, but it needs Review because some scripts inspect local credential stores and one JSON mode can print secret values into logs.

Review before installing. Use it only if you are comfortable with local security-audit scripts reading credential metadata and selected credential files under your home directory. Avoid secret-scanner.sh --format=json until matches are masked or removed, and treat any generated reports or logs as sensitive. Prefer running individual scripts for the exact scope you intend instead of full-audit.sh when auditing only one repository.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/secret-scanner.sh:79
Finding
Secret Scanner Discloses Detected Credentials in JSON Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/secret-scanner.sh`, lines 79-83 **Vulnerability Type**: Sensitive information exposure through diagnostic output **Risk Level**: High ### Vulnerable Code ```bash if [[ "$OUTPUT_FORMAT" == "json" ]]; then local escaped_match escaped_match=$(echo "$match" | sed 's/"/\\"/g' | head -c 120) printf '{"severity":"%s","file":"%s","line":%s,"pattern":"%s","match":"%s"}\n' \ "$severity" "$file" "$line" "$pattern" "$escaped_match" ``` ### Technical Analysis The scanner stores the complete matching source line in the `match` argument and includes up to 120 characters of that value in JSON output. Because the scanner searches for API keys, passwords, authentication tokens, and private-key markers, this output can contain complete live credentials. The human-readable format avoids printing the matching value, but JSON mode explicitly returns it. JSON output is particularly likely to be consumed by CI pipelines, report collectors, agent logs, or security-information systems, expanding the number of locations in which a credential may persist. The manual quote substitution is also not sufficient JSON escaping. Backslashes, newlines, control characters, and other JSON-sensitive content are not safely encoded, potentially creating malformed output or allowing a matched line to inject misleading JSON content. ### Attack Path 1. A repository or workspace contains a live credential matching one of the scanner's regular expressions. 2. A user, agent, or CI pipeline runs: ```bash scripts/secret-scanner.sh --format=json /path/to/repository ``` 3. The matching source line is passed to `emit_finding`. 4. Up to 120 characters of the line, potentially including the complete credential, are printed under the `match` property. 5. The output is retained in CI logs, agent conversation history, audit artifacts, terminal history, or centralized logging. 6. Anyone able to read those secondary recor ...[truncated 534 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `match` value from all output formats. Report only: - Relative file path - Line number - Secret type - Severity 2. If correlation is necessary, calculate a one-way fingerprint from the matched credential and expose only a short fingerprint, never the credential itself. 3. If masking is required, retain no more than a small non-sensitive suffix, such as the final four characters. 4. Generate JSON with a real JSON serializer rather than manual string interpolation. 5. Prevent audit reports from being written with permissive filesystem modes. Use a restrictive `umask`, such as: ```bash umask 077 ``` 6. Add tests confirming that known sample tokens never appear in human-readable output, JSON output, combined reports, or error messages. 7. Document that old audit logs generated by the vulnerable version should be searched, securely deleted where appropriate, and treated as potentially containing exposed credentials. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/token-watchdog.sh:98
Finding
Full Audit Automatically Reads Account-Wide Credential and Private-Key Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/token-watchdog.sh`, lines 98-127 **Vulnerability Type**: Excessive access to sensitive credential material **Risk Level**: Medium ### Vulnerable Code ```bash FULCRA_TOKEN="$HOME/.config/fulcra/token.json" if [[ -f "$FULCRA_TOKEN" ]]; then # Try to parse expiry expiry="" if command -v python3 &>/dev/null; then expiry=$(python3 -c " import json, sys try: with open('$FULCRA_TOKEN') as f: d = json.load(f) # Check common expiry field names for key in ['expires_at', 'expiry', 'exp', 'expiresAt', 'expires']: if key in d: print(d[key]) sys.exit(0) # Try to decode JWT access_token for key in ['access_token', 'token', 'id_token']: if key in d: import base64 parts = d[key].split('.') if len(parts) >= 2: payload = parts[1] + '==' # pad decoded = json.loads(base64.urlsafe_b64decode(payload)) if 'exp' in decoded: print(decoded['exp']) sys.exit(0) print('unknown') except Exception as e: print('error') " 2>/dev/null) || expiry="error" fi ``` Related sensitive reads also occur at: - `scripts/token-watchdog.sh:177-188` — Docker credential configuration - `scripts/token-watchdog.sh:200-219` — npm and AWS credential files - `scripts/token-watchdog.sh:228-254` — Kubernetes configuration and private SSH-key headers ### Technical Analysis Running `scripts/full-audit.sh` invokes the token watchdog automatically and without source-specific consent. The watchdog opens credential-bearing files under the user's home directory even when the requested audit target is only a repository. The Fulcra check parses the complete token JSON and reads access tokens to decode their JWT payloads. Additional checks inspect Docker authentication configuration, npm configuration, AWS credentials, Kubernetes configura ...[truncated 1970 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Separate repository scanning from host credential auditing. A repository-focused full audit should not inspect `$HOME` by default. 2. Require explicit opt-in flags for each source, for example: ```bash token-watchdog.sh --check-fulcra --check-aws --check-ssh ``` 3. Present a clear list of sensitive paths before reading them and require user confirmation in interactive use. 4. Support a metadata-only mode that checks file existence and permissions without parsing credential contents. 5. Avoid opening private SSH keys. Where key inspection is explicitly requested, use a dedicated cryptographic utility and do not copy key contents into shell variables or output. 6. Run credential checks in a restricted process with: - A sanitized environment - No unnecessary network access - Restrictive temporary-file and output permissions 7. Ensure failures and exceptions never print parsed credential structures. 8. Document the exact credential locations accessed by `full-audit.sh` and provide a configuration allowlist. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/permission-auditor.sh:91
Finding
Platform-Specific Permission Commands Can Cause Incorrect Security Results<![CDATA[ ## Vulnerability Details **File Location**: `scripts/permission-auditor.sh`, lines 91-105 **Vulnerability Type**: Fail-open and non-portable security validation **Risk Level**: Medium ### Vulnerable Code ```bash ssh_perms=$(stat -f '%Lp' "$SSH_DIR" 2>/dev/null) || true if [[ -n "$ssh_perms" && "$ssh_perms" != "700" ]]; then emit_finding "CRITICAL" "SSH Directory" "$SSH_DIR has permissions $ssh_perms (should be 700)" else emit_finding "INFO" "SSH Directory" "$SSH_DIR permissions OK (700)" fi # Check individual key files for keyfile in "$SSH_DIR"/id_* "$SSH_DIR"/*.pem; do [[ -f "$keyfile" ]] || continue # Skip public keys [[ "$keyfile" == *.pub ]] && continue perms=$(stat -f '%Lp' "$keyfile" 2>/dev/null) || true if [[ -n "$perms" && "$perms" != "600" && "$perms" != "400" ]]; then emit_finding "CRITICAL" "SSH Key" "$keyfile has permissions $perms (should be 600 or 400)" fi done ``` A related portability issue occurs at line 175: ```bash world_writable=$(find "$HOME" -maxdepth 2 -type f -perm +002 2>/dev/null | head -20) || true ``` ### Technical Analysis The permission auditor uses BSD/macOS-specific command syntax without first detecting the operating system or command implementation. In particular, `stat -f '%Lp'` is not equivalent to GNU `stat` permission formatting, and `find -perm +002` is unsupported or deprecated in common GNU environments. Errors are redirected to `/dev/null`, and `|| true` suppresses command failures. Empty or invalid values can therefore skip checks or be interpreted incorrectly. The SSH-directory branch is especially unsafe because an empty result reaches the `else` branch and reports that permissions are acceptable. A security auditor must fail closed when it cannot determine a permission value. Reporting success after a failed check creates false assurance. ### Attack Path 1. The auditor is run on a host whose `stat` or `find` implementation does not support the assumed macOS ...[truncated 920 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Detect the platform and select the appropriate command syntax: ```bash if stat -f '%Lp' "$path" >/dev/null 2>&1; then perms=$(stat -f '%Lp' "$path") elif stat -c '%a' "$path" >/dev/null 2>&1; then perms=$(stat -c '%a' "$path") else emit_finding "WARNING" "Permission Check" "Unable to determine permissions for $path" continue fi ``` 2. Use portable GNU-compatible world-writable matching where appropriate: ```bash find "$HOME" -maxdepth 2 -type f -perm -0002 ``` 3. Never report an `INFO` or `OK` result when the permission command returns an empty or invalid value. 4. Remove blanket `2>/dev/null || true` handling around security-critical checks. Capture errors and emit an explicit warning. 5. Validate that permission output contains only the expected octal format before comparing it. 6. Add automated tests for at least: - macOS/BSD - GNU/Linux - Missing `stat` - Permission-denied conditions 7. Ensure an incomplete audit produces a nonzero exit code distinct from a confirmed clean result. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/git-hygiene.sh:251
Finding
Tracked Sensitive Files Do Not Affect Git Hygiene Exit Status<![CDATA[ ## Vulnerability Details **File Location**: `scripts/git-hygiene.sh`, lines 251-258 **Vulnerability Type**: Subshell state-loss causing a fail-open security verdict **Risk Level**: High ### Vulnerable Code ```bash git ls-files 2>/dev/null | while IFS= read -r f; do case "$f" in *.env|*.env.*|*.pem|*.key|*.p12|*.pfx|*id_rsa|*id_ed25519|*.keystore|*credentials.json|*.secret) emit_finding "CRITICAL" "Tracked Sensitive File" "$f should not be in version control" tracked_sensitive=$((tracked_sensitive + 1)) ;; esac done || true ``` The final verdict is calculated later from the parent shell's counters: ```bash if [[ $CRITICAL -gt 0 ]]; then exit 2 elif [[ $WARNING -gt 0 ]]; then exit 1 else exit 0 fi ``` ### Technical Analysis In Bash, a loop on the right side of a pipeline normally executes in a subshell. The `emit_finding` function increments `FINDINGS` and `CRITICAL`, but those changes occur only in the pipeline subshell and are discarded when the loop ends. Consequently, the script can print a critical finding for a tracked `.env`, private key, credential file, or similar artifact while the parent shell retains its earlier counter values. If no other warning or critical finding exists, the script can subsequently exit with status `0`. This creates a discrepancy between visible output and machine-readable status. CI pipelines and agent orchestration commonly rely on exit codes rather than parsing all terminal output, making the defect directly security-relevant. ### Attack Path 1. A repository contains a tracked file matching one of the sensitive patterns, such as: ```text production.env deploy.key id_rsa credentials.json ``` 2. The user or CI system runs: ```bash scripts/git-hygiene.sh /path/to/repository ``` 3. `git ls-files` returns the sensitive path. 4. The pipeline subshell calls `emit_finding`, which increments `CRITICAL` only inside that subshell. ...[truncated 827 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the pipeline with process substitution so the loop executes in the current shell: ```bash while IFS= read -r f; do case "$f" in *.env|*.env.*|*.pem|*.key|*.p12|*.pfx|*id_rsa|*id_ed25519|*.keystore|*credentials.json|*.secret) emit_finding "CRITICAL" "Tracked Sensitive File" \ "$f should not be in version control" tracked_sensitive=$((tracked_sensitive + 1)) ;; esac done < <(git ls-files 2>/dev/null) ``` 2. Check and report failure of `git ls-files` rather than suppressing it with `|| true`. 3. Add a final invariant ensuring `tracked_sensitive > 0` forces `CRITICAL > 0` and exit status `2`. 4. Add regression tests that create repositories with tracked `.env`, `.pem`, `id_rsa`, and `credentials.json` files and verify: - A critical finding is emitted. - The critical counter is incremented. - The process exits with status `2`. 5. Have `full-audit.sh` preserve scanner exit statuses directly rather than relying only on regular-expression counting of scanner output. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (60)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
This finding indicates the documented primary purpose differs from the actual effective capability, with the real emphasis reportedly being auditing installed skills rather than the infrastructure checks advertised. Such mismatch is dangerous because it can both hide undeclared inspection behavior and cause defenders to rely on nonexistent protections, leading to misconfiguration and missed incidents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This finding indicates the documented primary purpose differs from the actual effective capability, with the real emphasis reportedly being auditing installed skills rather than the infrastructure checks advertised. Such mismatch is dangerous because it can both hide undeclared inspection behavior and cause defenders to rely on nonexistent protections, leading to misconfiguration and missed incidents.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This finding indicates the documented primary purpose differs from the actual effective capability, with the real emphasis reportedly being auditing installed skills rather than the infrastructure checks advertised. Such mismatch is dangerous because it can both hide undeclared inspection behavior and cause defenders to rely on nonexistent protections, leading to misconfiguration and missed incidents.

Credential Access

High
Category
Privilege Escalation
Content
echo -e "${BOLD}Checking .gitignore completeness...${RESET}"

REQUIRED_PATTERNS=(
    ".env"
    ".env.*"
    "*.key"
    "*.pem"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
echo -e "${BOLD}Checking .gitignore completeness...${RESET}"

REQUIRED_PATTERNS=(
    ".env"
    ".env.*"
    "*.key"
    "*.pem"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
echo -e "${BOLD}Checking .gitignore completeness...${RESET}"

REQUIRED_PATTERNS=(
    ".env"
    ".env.*"
    "*.key"
    "*.pem"
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"*.keystore"
    "id_rsa"
    "id_ed25519"
    "credentials.json"
    "token.json"
    "*.secret"
)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"*.keystore"
    "id_rsa"
    "id_ed25519"
    "credentials.json"
    "token.json"
    "*.secret"
)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"*.keystore"
    "id_rsa"
    "id_ed25519"
    "credentials.json"
    "token.json"
    "*.secret"
)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"*.keystore"
    "id_rsa"
    "id_ed25519"
    "credentials.json"
    "token.json"
    "*.secret"
)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
SENSITIVE_PATHS=(
    "$HOME/.config/fulcra/token.json"
    "$HOME/.config/gh/hosts.yml"
    "$HOME/.netrc"
    "$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.config/fulcra/token.json"
    "$HOME/.config/gh/hosts.yml"
    "$HOME/.netrc"
    "$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.config/fulcra/token.json"
    "$HOME/.config/gh/hosts.yml"
    "$HOME/.netrc"
    "$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.netrc"
    "$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.netrc"
    "$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
    "$HOME/.gnupg"
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.npmrc"
    "$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
    "$HOME/.gnupg"
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
    "$HOME/.gnupg"
    "$HOME/.secrets"
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.pypirc"
    "$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
    "$HOME/.gnupg"
    "$HOME/.secrets"
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"$HOME/.docker/config.json"
    "$HOME/.kube/config"
    "$HOME/.aws/credentials"
    "$HOME/.aws/config"
    "$HOME/.gnupg"
    "$HOME/.secrets"
    "$HOME/.env"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Check group readable for very sensitive files
            group_perms=${perms:(-2):1}
            case "$spath" in
                *credentials*|*token*|*.netrc|*.pypirc|*hosts.yml)
                    if [[ "$group_perms" =~ [4567] ]]; then
                        emit_finding "WARNING" "Group-Readable" "$spath is group-readable (perms: $perms)"
                    fi
Confidence
80% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
--include='*.go' --include='*.rs' --include='*.java' --include='*.sh' \
    --include='*.bash' --include='*.zsh' --include='*.yml' --include='*.yaml' \
    --include='*.json' --include='*.xml' --include='*.toml' --include='*.ini' \
    --include='*.cfg' --include='*.conf' --include='*.config' --include='*.env' \
    --include='*.env.*' --include='*.properties' --include='*.tf' \
    --include='*.md' --include='*.txt' --include='*.html' --include='*.css' \
    --include='*.dockerfile' --include='Dockerfile' --include='*.csv' \
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
--include='*.go' --include='*.rs' --include='*.java' --include='*.sh' \
    --include='*.bash' --include='*.zsh' --include='*.yml' --include='*.yaml' \
    --include='*.json' --include='*.xml' --include='*.toml' --include='*.ini' \
    --include='*.cfg' --include='*.conf' --include='*.config' --include='*.env' \
    --include='*.env.*' --include='*.properties' --include='*.tf' \
    --include='*.md' --include='*.txt' --include='*.html' --include='*.css' \
    --include='*.dockerfile' --include='Dockerfile' --include='*.csv' \
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
fi
        fi

        # Check for chmod 777 or overly permissive operations
        bad_chmod=$(echo "$content" | grep -noE 'chmod\s+(777|666|a\+[rwx])' 2>/dev/null | head -3) || true
        if [[ -n "$bad_chmod" ]]; then
            while IFS= read -r match; do
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Credential Access

High
Category
Privilege Escalation
Content
NPMRC="$HOME/.npmrc"
if [[ -f "$NPMRC" ]]; then
    if grep -q '_authToken' "$NPMRC" 2>/dev/null; then
        emit_token "INFO" "NPM" "Auth token present in ~/.npmrc"
    else
        emit_token "MISSING" "NPM" "No auth token in ~/.npmrc"
    fi
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.