Security checks for vulnerabilities and agentic risk
Overview
This skill is purpose-aligned for LinkedIn Ads reporting, but it needs Review because it uses LinkedIn credentials, can retrieve lead submissions, and asks users to install an unpinned global npm package.
Review before installing. Prefer a pinned, reviewed, local installation of `linkedin-ads-cli`; grant only the LinkedIn OAuth scopes needed for the task; keep tokens out of chat and logs; and retrieve raw lead-form responses only when authorized and necessary, since they may contain personal data.
If the CLI is not installed, install it:
```bash
npm install -g linkedin-ads-cli
text
### Technical Analysis
The Skill instructs the Agent to install `linkedin-ads-cli` globally from the npm registry without specifying a reviewed version, integrity hash, lockfile, or provenance requirement. Consequently, the installed code can change independently of the audited Skill.
npm packages may execute lifecycle scripts during installation. Because the command uses global installation, package code and lifecycle scripts execute with the permissions of the user running the Agent. The implementation of this package is not included in the audited project, so its installation behavior and runtime handling of credentials cannot be verified from the supplied artifact.
This installation is relevant to the Skill's functionality, but it exceeds the minimum safe approach because it implicitly trusts the latest registry release and modifies the user's global package environment. The dependency also handles a LinkedIn OAuth token resolved from `LINKEDIN_ADS_ACCESS_TOKEN`, an explicit credentials path, or `~/.config/linkedin-ads-cli/credentials.json`, increasing the potential consequences of a compromised release.
### Attack Path
1. An attacker compromises the npm package, its publisher account, or its upstream release process.
2. The attacker publishes a malicious release under the expected `linkedin-ads-cli` package name.
3. An Agent follows `SKILL.md` and runs `npm install -g linkedin-ads-cli`.
4. npm downloads the latest attacker-controlled release because no version or integrity value is pinned.
5. Malicious code executes through an npm lifecycle script during installation or when the CLI is subsequently invoked.
6. The code operates with
...[truncated 1040 chars]
Remediation
View remediation
Remediation Suggestions
Pin the dependency to a specific, security-reviewed version instead of installing the latest release:
bash
Verify the selected release's registry provenance, publisher identity, source repository, integrity metadata, and published package contents before approving it.
Use a lockfile or independently maintained checksum where the installation workflow supports it.
Prefer a project-local installation in an isolated environment over modifying the user's global npm environment.
Disable npm lifecycle scripts during installation where compatible:
bash
Any required lifecycle behavior should be separately reviewed before being enabled.
Run the CLI under a dedicated, least-privileged account or sandbox with access only to the required credential and output locations.
Grant the LinkedIn token only the OAuth scopes required for the requested operation and avoid exposing the token to unrelated processes, logs, or command output.
Require restrictive filesystem permissions on ~/.config/linkedin-ads-cli/credentials.json and avoid storing tokens in broadly inherited environments.
Document a trusted upgrade and re-audit process so dependency versions are changed only after review.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Content
Scanner excerpt · SKILL.md (reported line 45)May include surrounding context.
md
1. `--credentials <path>` flag (per-command)
2. Environment variable: `LINKEDIN_ADS_ACCESS_TOKEN`
3. Auto-detected file: `~/.config/linkedin-ads-cli/credentials.json`
Required OAuth scopes depend on the commands used:
- `r_ads` -- read ad accounts and campaigns
Credential Access
High
Category
Privilege Escalation
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Content
Scanner excerpt · SKILL.md (reported line 349)May include surrounding context.
md
1. `--credentials <path>` flag (per-command)
2. Environment variable: `LINKEDIN_ADS_ACCESS_TOKEN`
3. Auto-detected file: `~/.config/linkedin-ads-cli/credentials.json`
Required OAuth scopes depend on the commands used:
- `r_ads` -- read ad accounts and campaigns
Credential Access
High
Category
Privilege Escalation
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Content
Scanner excerpt · SKILL.md (reported line 348)May include surrounding context.
md
## Error handling
- **Authentication errors** -- ask the user to verify their access token and OAuth scopes
- **"No credentials found"** -- the user needs to set `LINKEDIN_ADS_ACCESS_TOKEN`, use `--credentials`, or place credentials at `~/.config/linkedin-ads-cli/credentials.json`
- **Empty analytics** -- check the date range, ensure the account had active campaigns in the period, and verify the pivot dimension is appropriate
- **Permission errors** -- different commands require different scopes (`r_ads`, `r_ads_reporting`, `r_organization_social`); check the required scopes list above
Description-Behavior Mismatch
Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding
The skill repeatedly describes the CLI as 'read-only,' but it also explicitly supports retrieving lead form submissions, which commonly contain personally identifiable information such as names, emails, and other submitted data. That mismatch can cause operators to underestimate the sensitivity of the data being accessed and disclose or process personal data without appropriate caution.
Content
No source excerpt is available for this finding.
Missing User Warnings
Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding
The documentation promotes retrieval of lead form submissions without any privacy notice, minimization guidance, or warning that the output may include personal data. In a skill context, this increases the chance that an agent will fetch and expose sensitive lead information in chat or logs without the user's informed intent.
Content
No source excerpt is available for this finding.
Missing User Warnings
Low
Category
Not specified by scanner
Confidence
84% confidence
Finding
The authentication section instructs users to provide OAuth bearer tokens through environment variables or credential files but does not warn that these secrets must not be pasted into chat, logs, or shared transcripts. While common operational guidance, omission of safe-handling instructions in an agent-facing skill can lead to accidental credential exposure.
Content
No source excerpt is available for this finding.
Scope Creep
Low
Category
Excessive Agency
Confidence
88% confidence
Finding
The skill states that --fields and --pivot are passed directly to the LinkedIn API without validation and that additional undocumented values may be available. This expands the accessible data surface beyond what the skill documents, increasing the risk of over-collection, unexpected sensitive fields, or bypass of intended constraints through agent-supplied parameters.
Content
Scanner excerpt · SKILL.md (reported line 217)May include surrounding context.
md
Default metric fields (when `--fields` is not specified): `impressions`, `clicks`, `costInLocalCurrency`, `costInUsd`, `externalWebsiteConversions`, `likes`, `comments`, `shares`, `follows`, `videoViews`
The CLI passes `--fields` and `--pivot` values directly to the LinkedIn API without validation. Additional fields and pivot values beyond the documented defaults may be available. Refer to the [LinkedIn Ad Analytics API docs](https://learn.microsoft.com/en-us/linkedin/marketing/integrations/ads-reporting/ads-reporting) for the full list.
### Audiences & targeting