T09 · Insecure Skill Coding Practices
- Location
scripts/freedcamp.mjs:176- Finding
Plaintext Session Cache Created Without Explicitly Restrictive Permissions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real Freedcamp automation skill, but it caches reusable session credentials insecurely and exposes broad live-write capabilities that need review before installation.
Install only if you are comfortable giving the skill access to your Freedcamp workspace and allowing it to create or modify tasks, comments, and notification state. Avoid running the demo in a workspace with a shared .env file, restrict the Freedcamp API credentials to the minimum needed account, treat the local session cache as sensitive, and remove cached credentials when no longer needed.
scripts/freedcamp.mjs:176Plaintext Session Cache Created Without Explicitly Restrictive Permissions
scripts/demo.mjs:17Demo Loads Unrelated Secrets from a Parent Workspace Environment File
README.md:45Setup Documentation Encourages Printing Stored API Credentials
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
*
* Usage: node skill/scripts/demo.mjs
*
* Loads .env from project root automatically if env vars aren't set.
*/
import { execFileSync } from "node:child_process";
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
*
* Usage: node skill/scripts/demo.mjs
*
* Loads .env from project root automatically if env vars aren't set.
*/
import { execFileSync } from "node:child_process";
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// Load .env if needed
function loadEnv() {
if (process.env.FREEDCAMP_API_KEY && process.env.FREEDCAMP_API_SECRET) return;
const envFile = path.join(ROOT, ".env");
if (!fs.existsSync(envFile)) return;
for (const line of fs.readFileSync(envFile, "utf-8").split("\n")) {
const match = line.match(/^(?:export\s+)?(\w+)=(.+)$/);
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.
node scripts/freedcamp.mjs task <task_id>
### 5) Create a task
```bash
node scripts/freedcamp.mjs create-task --project <project_id> --title "New task"
The README prominently documents commands that create tasks, update tasks, add comments, and mark notifications as read, but it does not clearly warn that these operations affect live Freedcamp data. In an agent-tooling context, users or agents may treat examples as safe exploratory commands, increasing the chance of unintended writes to production workspaces.
The skill requires environment secrets and makes network calls, but it does not declare an explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where an agent or reviewer cannot easily constrain what capabilities the skill is expected to use, increasing the chance of unintended secret access or outbound requests beyond user expectations.
The skill documents multiple state-changing operations such as creating tasks, updating tasks, adding comments, and marking notifications as read without an explicit warning or confirmation boundary. In an agent setting, this increases the risk of unintended remote modifications to production project data from ambiguous prompts or automation mistakes.
The skill is presented as project-management automation, but the documentation enables commenting across broader app domains including CRM, Passwords, Files, Wikis, and Calendar. This widens the reachable data surface and could let an agent modify or inject content into sensitive or unrelated areas, especially the Passwords app, beyond what a user may reasonably expect from the skill description.
The manifest description says the skill can create, update, and organize tasks, projects, groups, comments, notifications, and task lists. In the implementation, projects and groups are only enumerated via session data, and task lists are only listed; no commands create, update, or reorganize those resource types.
The manifest describes project-management automation against Freedcamp's API, but this demo additionally reads arbitrary environment-style secrets from a local .env file and injects them into process.env. While this may be convenient for local testing, local credential-file access is not part of the stated business purpose and is an extra capability beyond interacting with Freedcamp itself.
The code can add comments, fetch notifications, and mark notifications read, but it does not implement general create/update/organize behavior for notifications or task lists as implied by the manifest's broad wording. This is a semantic overstatement of skill behavior rather than an implementation detail.