T09 · Insecure Skill Coding Practices
- Location
org-post.mjs:25- Finding
Hard-Coded Production Account Identifiers and Unsafe Default Organization Posting
- Content
View full analysis
Vulnerability Details
File Location:
org-post.mjs, lines 25–52
Vulnerability Type: Hard-coded account configuration and unsafe credential-backed action defaults
Risk Level: MediumVulnerable 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
--userand--orgarguments can modify two identifiers, but the autho ...[truncated 2409 chars]- Remediation
View remediation
Remediation Suggestions
- Remove all real user, organization, and authorization-provision identifiers from source control.
- Require the caller to supply
--org,--user, and an account or authorization reference explicitly, or load them from a protected per-user configuration file. - Reject execution when any required identity field is absent instead of using production defaults.
- Validate that the selected authorization provision belongs to the selected external user and is authorized to administer the requested organization.
- Add a confirmation step that displays the target organization, acting identity, and complete post content before publication. Provide a separate explicit
--yesoption for controlled automation. - 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" - Restrict supported organization IDs through an allowlist maintained outside the repository.
- Protect
~/.config/pdauth/config.jsonwith least-privilege filesystem permissions, such as owner-only read and write access. - Avoid logging sensitive post content by default, particularly in shared CI/CD logs.
- Remove or redact the corresponding personal member URN, Telegram identifier, organization identifier, and authorization-provision identifier documented in
SKILL.md.
