T09 · Insecure Skill Coding Practices
Warning
- Location
- org-post.mjs:25
- Finding
- Hard-Coded Production Account Identifiers and Unsafe Default Organization Posting## Vulnerability Details **File Location**: `org-post.mjs`, lines 25–52 **Vulnerability Type**: Hard-coded account configuration and unsafe credential-backed action defaults **Risk Level**: Medium ### Vulnerable Code ```javascript // Defaults - customize as needed const DEFAULTS = { userId: 'telegram:5439689035', orgId: '105382747', // Versatly authProvisionId: 'apn_4vhLGx4', // LinkedIn account }; const client = new PipedreamClient({ projectEnvironment: config.environment || 'development', clientId: config.clientId, clientSecret: config.clientSecret, projectId: config.projectId, }); async function postAsOrg(text, options = {}) { const { orgId = DEFAULTS.orgId, userId = DEFAULTS.userId, authProvisionId = DEFAULTS.authProvisionId } = options; console.log(`📝 Posting to organization ${orgId}...`); console.log(` User: ${userId}`); console.log(` Text: ${text.substring(0, 100)}${text.length > 100 ? '...' : ''}`); try { const result = await client.actions.run({ id: 'linkedin-create-text-post-organization', externalUserId: userId, configuredProps: { linkedin: { authProvisionId }, organizationId: orgId, text: text, }, }); ``` ### Technical Analysis The script embeds identifiers for a specific Telegram user, LinkedIn organization, and OAuth authorization provision. It then uses these identifiers as automatic defaults for a credential-backed external action. Running the script with only post text is sufficient to attempt publication to the hard-coded organization. The script does not require the operator to explicitly select an organization, verify that the authorization provision belongs to the selected user, display the complete pending request for approval, or confirm publication before invoking `client.actions.run()`. The `--user` and `--org` arguments can modify two identifiers, but the autho ...[truncated 2409 chars]
- Remediation
- ## Remediation Suggestions 1. Remove all real user, organization, and authorization-provision identifiers from source control. 2. Require the caller to supply `--org`, `--user`, and an account or authorization reference explicitly, or load them from a protected per-user configuration file. 3. Reject execution when any required identity field is absent instead of using production defaults. 4. Validate that the selected authorization provision belongs to the selected external user and is authorized to administer the requested organization. 5. Add a confirmation step that displays the target organization, acting identity, and complete post content before publication. Provide a separate explicit `--yes` option for controlled automation. 6. Implement a dry-run mode and make it the default: ```bash node org-post.mjs --org ORG_ID --user USER_ID --dry-run "Post content" ``` 7. Restrict supported organization IDs through an allowlist maintained outside the repository. 8. Protect `~/.config/pdauth/config.json` with least-privilege filesystem permissions, such as owner-only read and write access. 9. Avoid logging sensitive post content by default, particularly in shared CI/CD logs. 10. Remove or redact the corresponding personal member URN, Telegram identifier, organization identifier, and authorization-provision identifier documented in `SKILL.md`.
