T09 · Insecure Skill Coding Practices
- Location
scripts/qlik-search.sh:21- Finding
Arbitrary Python Code Execution Through Unsafe Argument Interpolation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Qlik Cloud skill mostly matches its stated purpose, but it needs review because its scripts can expose the API key or run unintended local code if inputs or tenant settings are unsafe.
Install only after reviewing and preferably fixing the shell scripts. Use a minimally scoped Qlik API key, set QLIK_TENANT only to the exact HTTPS Qlik Cloud tenant you control, avoid storing long-lived keys in broadly readable files, and do not expose these scripts to untrusted queries or IDs until Python interpolation and temporary-file handling are hardened.
scripts/qlik-search.sh:21Arbitrary Python Code Execution Through Unsafe Argument Interpolation
scripts/qlik-health.sh:15Bearer Token Disclosure Through Unvalidated or Plaintext Tenant URLs
scripts/qlik-app-delete.sh:24Predictable Temporary File Enables Symlink Overwrite and Response Tampering
The supplied code implements a narrow app-listing function only. It authenticates with QLIK_TENANT and QLIK_API_KEY, calls Qlik Cloud app/item listing endpoints, optionally filters by space, and formats the returned app metadata. There is no evidence in this code chunk of the many other declared capabilities such as health checks, app management beyond listing, reload execution, Insight Advisor queries, automations, AutoML, Qlik Answers AI, alerts, user/license management, file handling, or lineage. This is a material description-versus-behavior mismatch because the declared purpose describes a broad 37-tool integration, while the actual code chunk performs just one limited listing operation.
The supplied code implements one narrow Qlik Cloud app-auditing utility: it reads tenant/API key environment variables, calls the apps listing endpoint, and analyzes duplicate app names. This fits only a small slice of 'app management' or health/audit behavior. It does not implement the vast majority of the declared capabilities, such as search, reload operations, natural-language analytics, automations, AutoML, Qlik Answers AI, alerts, spaces, users, licenses, data files, or lineage. The description therefore materially overstates and misrepresents the actual behavior and primary purpose of this code chunk.
The description claims a comprehensive Qlik Cloud integration with many operational and analytics features, but the code chunk only checks connectivity and fetches the current user profile from Qlik Cloud. While health checks are one declared feature, the supplied code does not substantiate the broader declared purpose and instead represents a much narrower skill. This is a material description-versus-behavior mismatch due to the substantially overstated scope and primary capability set.
The supplied code only performs one specific reload-related function: fetch reload status for a provided reload ID using Qlik tenant and API key credentials. While this behavior is within the broad declared domain of Qlik Cloud and reloads, the declared description claims a complete 37-tool integration spanning many unrelated capabilities that are not present here. This is a material description-versus-behavior mismatch because the actual code chunk has a much narrower primary purpose than the declared functionality.
The code chunk has a narrow, specific function: POST to the Qlik Cloud reloads API to trigger an app reload and report the result. The declared description presents a much broader skill with many capabilities across the Qlik platform. While app reloads are one listed capability, this code alone does not accurately represent the declared scope and primary purpose. There is no evidence of unrelated or dangerous undeclared behavior, but there is a substantial description-to-behavior mismatch because the implementation is far more limited than advertised.
The supplied code is narrowly focused on searching Qlik Cloud items via the /api/v1/items endpoint and formatting the results. It does not implement the wide range of capabilities claimed in the description, such as management operations, reloads, AI features, lineage, or user/license handling. While search is one of the declared capabilities, the declared description presents the skill as a complete multi-tool Qlik integration, whereas this code chunk represents only a small subset of that functionality. Therefore the description does not accurately represent what this specific code chunk actually does.
The description presents a comprehensive Qlik Cloud integration with many operational and analytics capabilities. The actual code only retrieves current-user and tenant-related information from a single Qlik API endpoint. While this behavior is within the general Qlik Cloud domain, it does not substantiate the declared breadth or primary purpose of the skill. This is a material description-to-behavior mismatch because the code chunk supports only a small subset of the claimed functionality.
Referenced artifact was not completely inspected
| **Actual data values** (KPIs, numbers, trends) | `qlik-insight.sh` | "what is total sales", "which store has lowest stock" |
Referenced artifact was not completely inspected
| **Actual data values** (KPIs, numbers, trends) | `qlik-insight.sh` | "what is total sales", "which store has lowest stock" |
Referenced artifact was not completely inspected
| **Actual data values** (KPIs, numbers, trends) | `qlik-insight.sh` | "what is total sales", "which store has lowest stock" |
Referenced artifact was not completely inspected
| **Actual data values** (KPIs, numbers, trends) | `qlik-insight.sh` | "what is total sales", "which store has lowest stock" |
Referenced artifact was not completely inspected
| **Actual data values** (KPIs, numbers, trends) | `qlik-insight.sh` | "what is total sales", "which store has lowest stock" |
Referenced artifact was not completely inspected
| **Actual data values** (KPIs, numbers, trends) | `qlik-insight.sh` | "what is total sales", "which store has lowest stock" |
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
TENANT="${QLIK_TENANT%/}"
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/data-alerts/${ALERT_ID}" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
TENANT="${QLIK_TENANT%/}"
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
curl -sL -X POST \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/data-alerts/${ALERT_ID}/actions/evaluate" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
TENANT="${QLIK_TENANT%/}"
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/data-alerts?limit=${LIMIT}" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# If no thread ID, create one first
if [[ -z "$THREAD_ID" ]]; then
THREAD_NAME="Conversation: ${TIMESTAMP}"
THREAD_RESPONSE=$(curl -sL -X POST \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"name\": \"${THREAD_NAME}\"}" \
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
fi
# Invoke the question on the thread
RESPONSE=$(curl -sL -X POST \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"input\":{\"prompt\":$(echo "$QUESTION" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read().strip()))'),\"promptType\":\"thread\",\"includeText\":true}}" \
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
TENANT="${QLIK_TENANT%/}"
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/assistants?limit=${LIMIT}" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
fi
BODY="$BODY}}"
curl -sL -X POST \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
-d "$BODY" \
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
# Get app metadata which includes table/field info
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/apps/${APP_ID}/data/metadata" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
TENANT="${QLIK_TENANT%/}"
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/apps/${APP_ID}" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
TENANT="${QLIK_TENANT%/}"
[[ "$TENANT" != http* ]] && TENANT="https://$TENANT"
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/apps/${APP_ID}/data/lineage" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# Use /items API for space filtering (personal or specific space)
URL="${TENANT}/api/v1/items?resourceType=app&spaceId=${SPACE}&limit=${LIMIT}"
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"$URL" | python3 -c "
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
"
else
# Use /apps API for all apps (no space filter)
curl -sL \
-H "Authorization: Bearer ${QLIK_API_KEY}" \
-H "Content-Type: application/json" \
"${TENANT}/api/v1/apps?limit=${LIMIT}" | python3 -c "
No suspicious patterns detected.