T09 · Insecure Skill Coding Practices
- Location
scripts/idrac.sh:76- Finding
TLS Certificate Verification Disabled for Authenticated iDRAC Requests
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
Review recommended: this skill is for Dell iDRAC server management, but it handles powerful credentials with unsafe TLS and persistent plaintext caching.
Install only if you understand it will access out-of-band server management APIs. Prefer a least-privileged iDRAC account, avoid production use with curl -k, use trusted certificates or pinning, do not cache 1Password or environment credentials into plaintext files, and inspect the config file because it is executed as shell code.
scripts/idrac.sh:76TLS Certificate Verification Disabled for Authenticated iDRAC Requests
scripts/idrac.sh:39Environment and 1Password Credentials Persisted in a Plaintext Cache
scripts/idrac.sh:7Arbitrary Shell Execution Through Sourced Configuration File
The workflow permits direct curl access to a management API using Basic Auth or session tokens, and the skill supports destructive operations like power control. Without strict parameter validation and hard-coded endpoint/method allowlisting, a prompt-influenced agent could be steered into issuing unintended Redfish actions, exposing credentials to subprocess context, or performing unauthorized state changes on infrastructure.
3. **Determine operation type:**
- **Read-only** (status, health, logs, inventory) → Execute directly
- **Destructive** (power off, restart, BIOS changes) → Confirm with user first
4. **Query Redfish API** via curl + Basic Auth (or session token for batch ops)
5. **Parse JSON** with jq
6. **Surface findings** to user in natural language
7. **Never expose credentials** in responses
Using curl with -k disables TLS certificate verification, allowing a man-in-the-middle attacker on the network to intercept or modify Redfish API traffic. Because these examples also use Basic Auth credentials, an attacker could steal administrator credentials or inject malicious responses while the operator believes they are communicating with the real iDRAC.
All examples use the helper script's api_get pattern. For raw curl:
curl -k -s -u "$(cat "$CREDS_FILE")" "https://${IDRAC_IP}/redfish/v1${ENDPOINT}"
The session-creation request sends administrator credentials over HTTPS with certificate validation disabled via -k. That makes the authentication exchange vulnerable to interception by an active network attacker, who could capture the username/password and obtain a valid session token to control the server out-of-band.
# Create session (returns X-Auth-Token in headers)
SESSION_RESPONSE=$(curl -k -i -X POST \
-H "Content-Type: application/json" \
-d "{\"UserName\":\"${IDRAC_USER}\",\"Password\":\"${IDRAC_PASS}\"}" \
"https://${IDRAC_IP}/redfish/v1/SessionService/Sessions")
Using -k on authenticated follow-up requests means the session token is transmitted to any endpoint an attacker can impersonate, enabling session hijacking. An active attacker could also tamper with API responses, misleading operators about system health or inventory and potentially influencing later administrative actions.
SESSION_TOKEN=$(echo "$SESSION_RESPONSE" | grep -i "X-Auth-Token:" | awk '{print $2}' | tr -d '\r')
# Use session token for subsequent calls
curl -k -H "X-Auth-Token: $SESSION_TOKEN" \
"https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1" | jq
# Delete session when done
Deleting the session with -k still transmits the active session token without server authentication, so a man-in-the-middle could capture the token even during cleanup. While the delete call itself is less sensitive than login, the insecure transport keeps the management session vulnerable until fully terminated.
SESSION_URI=$(echo "$SESSION_RESPONSE" | grep -i "Location:" | awk '{print $2}' | tr -d '\r') curl -k -X DELETE -H "X-Auth-Token: $SESSION_TOKEN" "${SESSION_URI}"
## Power Operations
This power-control example combines a highly sensitive management action with disabled TLS verification and Basic Auth credentials. A network attacker could intercept credentials or alter the request in transit, potentially causing unauthorized power state changes to production servers and creating outage or recovery scenarios.
api_get "/Systems/System.Embedded.1" | jq -r '.PowerState'
# Power on (if off)
curl -k -s -u "$(cat "$CREDS_FILE")" \
-X POST -H "Content-Type: application/json" \
-d '{"ResetType":"On"}' \
"https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"
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).
echo "Error: IDRAC_USER and IDRAC_PASS must be set for CREDS_SOURCE=env" >&2
exit 1
fi
# Write ephemeral creds file for curl
echo "${IDRAC_USER}:${IDRAC_PASS}" > "$CREDS_FILE"
chmod 600 "$CREDS_FILE"
;;
The script uses curl -k, disabling TLS certificate verification when connecting to the iDRAC endpoint. In a management-plane tool that handles administrator credentials and can query sensitive hardware state, this allows man-in-the-middle interception or spoofing of the remote host, especially on shared or untrusted networks.
# Test 1: Network connectivity
echo -n "1. Network connectivity... "
if curl -k -s --connect-timeout 5 "https://${IDRAC_IP}/redfish/v1/" > /dev/null 2>&1; then
echo "✅ OK"
else
echo "❌ FAILED (cannot reach ${IDRAC_IP})"
The skill exposes shell-based operational capability but does not declare an explicit tool scope or permission boundary. That increases the risk that an agent invokes shell commands more broadly than intended, especially because the skill can perform both read-only and destructive management actions against remote hardware.
The skill directs the user to create persistent local configuration under ~/.config/idrac-skill/config, which establishes durable state for future executions. Persistent state is not inherently malicious, but in a security-sensitive skill it can be abused if altered by another local process or used to silently retain sensitive connection targets and behavior across sessions.
Create a config file at ~/.config/idrac-skill/config:
mkdir -p ~/.config/idrac-skill
The skill instructs users to store username:password persistently in ~/.idrac-credentials. Even with mode 600, plaintext credential caching materially increases the impact of local compromise, accidental backup/sync leakage, or reuse by other processes, especially since these credentials control remote server management interfaces.
# OP_ITEM="<1password-item-name>"
#
# For CREDS_SOURCE="file":
# Create ~/.idrac-credentials with contents: username:password
# chmod 600 ~/.idrac-credentials
#
# For CREDS_SOURCE="env":
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Create session (returns X-Auth-Token in headers)
SESSION_RESPONSE=$(curl -k -i -X POST \
-H "Content-Type: application/json" \
-d "{\"UserName\":\"${IDRAC_USER}\",\"Password\":\"${IDRAC_PASS}\"}" \
"https://${IDRAC_IP}/redfish/v1/SessionService/Sessions")
This markdown file includes commands for powering on, shutting down, and force restarting a server, which can affect system availability and running workloads. The section labels describe the actions, but there is no explicit warning or caution advising users that these commands are disruptive or potentially service-impacting.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
api_get "/Systems/System.Embedded.1" | jq -r '.PowerState'
# Power on (if off)
curl -k -s -u "$(cat "$CREDS_FILE")" \
-X POST -H "Content-Type: application/json" \
-d '{"ResetType":"On"}' \
"https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
load_config() {
if [ ! -f "$CONFIG_FILE" ]; then
echo "Error: Config not found at $CONFIG_FILE" >&2
echo "Create it with:" >&2
echo " mkdir -p ~/.config/idrac-skill" >&2
echo " cat > ~/.config/idrac-skill/config <<EOF" >&2
echo ' IDRAC_IP="<your-idrac-ip>"' >&2
Credentials retrieved from 1Password are cached into ~/.idrac-credentials and reused indefinitely until manually removed. This weakens the security benefit of using a secret manager by converting managed secrets into a persistent local plaintext credential file.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
echo "Hydrating credentials from 1Password ($op_item)..." >&2
op item get "$op_item" --fields username,password --format json | \
jq -r '"\(.[0].value):\(.[1].value)"' > "$CREDS_FILE"
chmod 600 "$CREDS_FILE"
fi
;;
env)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
echo "Hydrating credentials from 1Password ($op_item)..." >&2
op item get "$op_item" --fields username,password --format json | \
jq -r '"\(.[0].value):\(.[1].value)"' > "$CREDS_FILE"
chmod 600 "$CREDS_FILE"
fi
;;
env)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
echo "Hydrating credentials from 1Password ($op_item)..." >&2
op item get "$op_item" --fields username,password --format json | \
jq -r '"\(.[0].value):\(.[1].value)"' > "$CREDS_FILE"
chmod 600 "$CREDS_FILE"
fi
;;
env)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
echo "Hydrating credentials from 1Password ($op_item)..." >&2
op item get "$op_item" --fields username,password --format json | \
jq -r '"\(.[0].value):\(.[1].value)"' > "$CREDS_FILE"
chmod 600 "$CREDS_FILE"
fi
;;
env)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
echo "Hydrating credentials from 1Password ($op_item)..." >&2
op item get "$op_item" --fields username,password --format json | \
jq -r '"\(.[0].value):\(.[1].value)"' > "$CREDS_FILE"
chmod 600 "$CREDS_FILE"
fi
;;
env)
When CREDS_SOURCE=env, the script writes IDRAC_USER and IDRAC_PASS into ~/.idrac-credentials on disk. Even with mode 600, this creates unnecessary secret persistence, increasing exposure through backups, endpoint compromise, or later local access by the same account.
The markdown shows creating a session by sending username and password and then extracting and reusing an authentication token. While this is expected for the task, the documentation does not warn users that credentials and tokens are sensitive and should be handled carefully, especially when captured in shell variables or command history.
No suspicious patterns detected.