T09 · Insecure Skill Coding Practices
- Location
assets/backend/app.py:23- Finding
Unrestricted API Destination Can Disclose Uploaded Images and API Credentials
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill matches an AI image editor, but its template can expose private photos and API keys unless reviewed and hardened.
Install only after review or hardening. At minimum, allowlist the StepFun API hosts, keep the API key server-side, disable Flask debug mode, add upload size and rate limits, authenticate or expire image URLs, delete originals when no longer needed, disclose third-party image processing to users, and update or lock dependencies.
assets/backend/app.py:23Unrestricted API Destination Can Disclose Uploaded Images and API Credentials
assets/backend/app.py:198Uploaded and Generated Images Are Persistently Exposed Without Authentication
assets/backend/app.py:127Unbounded Image Upload and Processing Permit Resource-Exhaustion Attacks
assets/backend/app.py:208Flask Interactive Debug Mode Is Enabled by Default
assets/frontend/package.json:11Frontend Dependencies Are Not Reproducibly Locked
The endpoint used for the outbound request is derived from an environment variable without validation or allowlisting. If an attacker can influence deployment configuration, they can redirect uploaded images and the bearer token to an arbitrary host, creating a server-side exfiltration/SSRF-style risk beyond the intended StepFun service.
}
try:
resp = requests.post(STEPFUN_EDIT_URL, json=payload, headers=headers, timeout=120)
resp.raise_for_status()
data = resp.json()
Flask-CORS is pinned to a version with multiple known CORS-handling flaws, including case-sensitivity, regex path matching, and inconsistent origin matching issues. For a React frontend talking to a Flask backend, CORS policy is security-critical; bypasses or inconsistent matching can let unintended origins access authenticated API responses or perform cross-origin interactions.
Pillow is pinned to a version with numerous advisories affecting image parsing and related functionality. Because this skill is specifically for AI-powered image editing and will likely process untrusted user-uploaded images, any image library vulnerability is especially dangerous and could lead to denial of service, memory issues, or worse depending on the specific code paths reached.
The skill describes capabilities that require environment-variable access and outbound network access, but it does not declare any tool scope or permissions boundaries. This creates a governance gap where an agent may use broader capabilities than the user expects, increasing the chance of unauthorized secret access or unintended external requests during skill execution.
The skill instructs users to upload images for AI editing but does not clearly warn that those images are transmitted to StepFun, a third-party external API, for processing. This can expose sensitive personal or confidential images without informed consent, especially in a photo-editing context where portraits and private media are common.
This section directs configuration of an external API endpoint and API key, confirming that image data and credentials will be used for outbound transmission to a third party. In this skill context, external transmission is expected, but it remains security-relevant because sensitive user images may leave the local environment and API keys must be protected.
STEPFUN_API_KEY=<user's actual api key>
STEPFUN_BASE_URL=https://api.stepfun.com/v1
If using Step Plan subscription, change base URL to https://api.stepfun.com/step_plan/v1 instead.
The alternate Step Plan base URL is another explicit instruction to send requests to an external service, so the same data-exposure and third-party trust risks apply. Although this is part of the intended architecture, users still need clear notice and controls because uploaded content may contain sensitive imagery.
STEPFUN_BASE_URL=https://api.stepfun.com/v1
If using Step Plan subscription, change base URL to `https://api.stepfun.com/step_plan/v1` instead.
### 3. Install Dependencies
Using npx vite without pinning a version allows resolution of whatever package version is current at execution time, which weakens supply-chain integrity and reproducibility. If a malicious or compromised upstream package version is served, the developer could install and execute untrusted code.
The documented POST https://api.stepfun.com/v1/images/edit endpoint confirms direct external transmission of user-provided image content to a third-party processor. In an image-editing skill, this is functionally necessary, but it is still a real security/privacy concern because personal photos, metadata-bearing images, or confidential media could be exposed outside the user's system.
POST https://api.stepfun.com/v1/images/edit
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
os.makedirs(RESULT_DIR, exist_ok=True)
STEPFUN_API_KEY = os.getenv("STEPFUN_API_KEY", "")
STEPFUN_BASE_URL = os.getenv("STEPFUN_BASE_URL", "https://api.stepfun.com/v1")
STEPFUN_EDIT_URL = f"{STEPFUN_BASE_URL}/images/edit"
FEATURE_PROMPTS = {
This code sends user-uploaded images to an external third-party API for processing, but there is no visible consent, disclosure, or privacy gating in the backend flow. For photo-editing applications, uploads often contain sensitive personal data, so undisclosed transmission can create privacy, compliance, and trust issues even if the transmission is functionally required.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
try:
resp = requests.post(STEPFUN_EDIT_URL, json=payload, headers=headers, timeout=120)
resp.raise_for_status()
data = resp.json()
The requirements file pins Flask to a version identified by the scanner as having multiple known security advisories, including session/signing and caching-related issues. In a web application backend for an image editing service, Flask is directly exposed to user traffic, so shipping a known vulnerable framework version increases the chance of exploitable session or response-handling weaknesses.
Requests is pinned to a version with known advisories, including a .netrc credential leak scenario and other unsafe behaviors in edge-case utilities. This skill integrates with external APIs and may fetch remote resources, so using a vulnerable HTTP client can expose credentials or create unsafe file/network handling paths if attacker-controlled URLs are processed.
python-dotenv is pinned to a version with a known arbitrary file overwrite/symlink-following issue in set_key-related behavior. While .env handling is often limited to development or deployment workflows, if any administrative or automated runtime path modifies environment files, this dependency could be abused for filesystem impact.
The HTML document declares lang="zh-CN", which fixes the interface locale to Simplified Chinese. In this file there is no indication of user opt-in, locale selection, or a documented region-specific reason, so this appears to violate the language/locale policy requirement.
This code sends the user-selected image via a POST request to /api/edit, which is a network operation involving user data. The UI shows upload and processing controls, but there is no visible notice, confirmation, or inline disclosure near the action indicating that the image will be sent to a backend service.
This line states that all prompts must be in English for best results, which imposes a language constraint in the skill guidance. The file does not present this as an option, ask for user preference, or document a policy justification for forcing English.
User-facing strings and descriptions in this file are presented in Chinese only, with no visible option to choose another language or locale. That can violate language/locale policy when a skill imposes a single language experience without explicit user choice or documented regional justification.
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.3.12",
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4",
"vite": "^6.0.0"
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
},
"devDependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4",
"vite": "^6.0.0"
}