Back to skill

Security audit

CI-CD

Security checks for vulnerabilities and agentic risk

Overview

The skill is documentation-only and relevant to CI/CD, but its reusable workflow examples include unsafe deployment patterns that merit review before installation.

Review and harden any workflow before copying it into a repository. In particular, pin third-party actions to reviewed commits, avoid exposing secrets to pull-request jobs, add minimal permissions and environment approvals, restrict deployment keys and sudo rights, and confirm whether Docker images or mobile artifacts will be published automatically.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T08 · Insecure Dependencies

Warning
Location
mobile.md:13
Finding
Unpinned Fastlane Installation Exposes the Build Environment to Supply-Chain Risk<![CDATA[ ## Vulnerability Details **File Location**: `mobile.md`, line 13 **Vulnerability Type**: Unpinned executable dependency **Risk Level**: Medium ### Vulnerable Code ```bash # Install Fastlane gem install fastlane ``` ### Technical Analysis The documented installation command retrieves and installs the latest available Fastlane package without a version constraint or a lockfile. Consequently, the code executed by developers or CI systems can change between installations without any modification to the reviewed project. If the upstream package, publishing account, or dependency chain is compromised, a malicious release could execute during package installation or later Fastlane invocations. The absence of deterministic dependency resolution also prevents reliable review and reproducible builds. ### Attack Path 1. An attacker compromises the Fastlane package publication process or an upstream dependency. 2. The attacker publishes a malicious version that is selected as the latest compatible release. 3. A developer or CI job follows the documented `gem install fastlane` command. 4. The compromised package is installed and executed with the permissions of the developer or CI runner. 5. The malicious package accesses files, environment variables, signing credentials, or other secrets available to that process. ### Impact Assessment Successful exploitation provides code execution with the privileges of the account running the installation or subsequent Fastlane commands. In a mobile release pipeline, the exposed scope may include source code, CI credentials, Apple signing certificates, provisioning profiles, repository credentials, and application-release capabilities. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Manage Fastlane through a committed `Gemfile` and `Gemfile.lock`. - Pin Fastlane to an explicitly reviewed version or appropriately constrained version range. - Install dependencies with Bundler and invoke Fastlane through Bundler: ```bash bundle config set path vendor/bundle bundle install --deployment bundle exec fastlane match appstore --readonly ``` - Review lockfile changes as security-sensitive dependency updates. - Use automated dependency monitoring while requiring review before accepting new releases. - Restrict CI token permissions and isolate signing credentials so a compromised package cannot access unrelated secrets. ]]>

T08 · Insecure Dependencies

Warning
Location
mobile.md:91
Finding
Flutter CI Action Is Referenced Through a Mutable Version Tag<![CDATA[ ## Vulnerability Details **File Location**: `mobile.md`, lines 91-94 **Vulnerability Type**: Mutable third-party CI dependency **Risk Level**: Medium ### Vulnerable Code ```yaml - uses: subosito/flutter-action@v2 with: flutter-version: '3.24' cache: true ``` ### Technical Analysis The workflow references the third-party `subosito/flutter-action` action by the mutable `v2` tag rather than an immutable commit SHA. Repository maintainers can move a tag to different code without requiring any change to the consuming workflow. GitHub Actions execute on the CI runner and can ordinarily access the checked-out repository, workspace files, environment information, and any credentials made available to the job. Pinning the Flutter SDK version does not pin the implementation of the action responsible for installing it. ### Attack Path 1. An attacker compromises the third-party action repository or a maintainer account. 2. The attacker changes the code referenced by the `v2` tag or moves that tag to a malicious commit. 3. The mobile workflow runs without any change to the audited workflow configuration. 4. GitHub downloads and executes the malicious action on the runner. 5. The action accesses source code, modifies build output, or uses any tokens and secrets available to the job. ### Impact Assessment Exploitation permits arbitrary code execution within the Flutter CI job. The direct scope shown includes source code and generated mobile artifacts. If the job is later extended with signing or publication credentials, those credentials and the resulting release artifacts could also be compromised. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the action to a reviewed full commit SHA: ```yaml - uses: subosito/flutter-action@FULL_REVIEWED_COMMIT_SHA with: flutter-version: '3.24' cache: true ``` - Preserve the release tag in a comment for maintainability. - Use dependency update tooling to propose SHA updates, but require review before merging. - Set explicit minimal workflow permissions, such as read-only repository access where sufficient. - Keep signing and publication credentials in separate jobs that only run after trusted events and reviewed artifacts. ]]>

T08 · Insecure Dependencies

Error
Location
web.md:96
Finding
Mutable Third-Party Deployment Actions Receive Production SSH Credentials<![CDATA[ ## Vulnerability Details **File Location**: `web.md`, lines 96-113 **Vulnerability Type**: Mutable privileged CI dependencies **Risk Level**: High ### Vulnerable Code ```yaml - name: Deploy via SSH uses: appleboy/scp-action@v0.1.7 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} key: ${{ secrets.SSH_KEY }} source: "dist/*" target: "/var/www/app" - name: Restart service uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} key: ${{ secrets.SSH_KEY }} script: sudo systemctl restart myapp ``` ### Technical Analysis Both deployment actions are third-party components referenced by version tags rather than immutable commit SHAs. Even though the tags appear version-specific, Git tags can be deleted or moved to different commits. These actions receive a private SSH key and production connection details. The second action also invokes a command through an account permitted to run `sudo systemctl restart myapp`. A compromised action could read the supplied inputs, transmit the SSH key externally, alter deployed files, or issue commands other than the documented restart operation. ### Attack Path 1. An attacker compromises either action repository, its release process, or a maintainer account. 2. The attacker moves the referenced tag to malicious action code. 3. A deployment workflow runs on the main branch. 4. The runner downloads and executes the altered action. 5. The malicious action captures `SSH_HOST`, `SSH_USER`, and `SSH_KEY`. 6. The attacker uses the stolen key to connect to the deployment server, modify the application, and exercise the remote permissions granted to the deployment account. ### Impact Assessment Successful exploitation can compromise the CI runner and the target deployment server. The attacker may replace production web content, introduce a backdoor into deployed artifacts, steal the reusable SSH private key, disrupt ...[truncated 260 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin both actions to reviewed full commit SHAs rather than tags: ```yaml uses: appleboy/scp-action@FULL_REVIEWED_COMMIT_SHA ``` ```yaml uses: appleboy/ssh-action@FULL_REVIEWED_COMMIT_SHA ``` - Use a dedicated deployment key restricted to the target host and application. - Configure the server-side `authorized_keys` entry with appropriate restrictions where compatible with the deployment process. - Limit the deployment account to `/var/www/app` and grant only the exact service-management command required through sudo. - Prefer short-lived deployment credentials or an authenticated deployment service over a reusable private key. - Separate build and deployment jobs so deployment credentials are only exposed after trusted-branch and environment-approval checks. - Apply minimal GitHub Actions permissions and protect the production environment with required reviewers. - Rotate the SSH key immediately if compromise of an action or runner is suspected. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
web.md:57
Finding
Pull-Request Branch Name Is Interpolated Directly into Shell Source<![CDATA[ ## Vulnerability Details **File Location**: `web.md`, lines 57-63 **Vulnerability Type**: Shell command injection through GitHub Actions expression interpolation **Risk Level**: High ### Vulnerable Code ```yaml deploy-preview: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - name: Deploy to preview run: | BRANCH_SLUG=$(echo "${{ github.head_ref }}" | sed 's/[^a-z0-9]/-/g') # Deploy to https://${BRANCH_SLUG}.preview.yoursite.com ``` ### Technical Analysis `github.head_ref` is influenced by the source branch of a pull request. GitHub evaluates `${{ ... }}` expressions before sending the resulting script to the shell. The branch name is therefore inserted into shell source code rather than passed to the shell as a data-only environment variable. Shell quoting visible in the template does not provide a reliable trust boundary because malicious characters are introduced before parsing begins. If a crafted branch name contains shell-significant syntax accepted by the hosting platform and event path, it may terminate or alter the intended command and cause additional commands to execute. The subsequent `sed` sanitization occurs too late because the shell must first parse and execute the generated command. ### Attack Path 1. An attacker creates a branch with a name containing shell-significant syntax. 2. The attacker opens a pull request that triggers the preview deployment job. 3. GitHub substitutes the attacker-controlled `github.head_ref` value directly into the multiline script. 4. The runner's shell parses the substituted text as part of the command. 5. Injected shell syntax executes with the permissions and environment of the preview job. 6. The attacker modifies artifacts, accesses available credentials, or attacks preview deployment infrastructure. ### Impact Assessment Successful exploitation provides arbitrary command execution on the GitHub-hosted runner under the workflow's permissions ...[truncated 505 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Pass the GitHub context value through an environment variable and treat it strictly as quoted data: ```yaml deploy-preview: if: github.event_name == 'pull_request' runs-on: ubuntu-latest permissions: contents: read steps: - name: Deploy to preview env: HEAD_REF: ${{ github.head_ref }} run: | BRANCH_SLUG=$(printf '%s' "$HEAD_REF" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g') printf 'Preview slug: %s\n' "$BRANCH_SLUG" ``` Additional hardening should include: - Validate the final slug against a strict length and character policy before using it. - Avoid constructing shell commands dynamically from branch names. - Do not expose deployment secrets to workflows triggered by untrusted pull requests. - Set explicit minimal workflow permissions. - Separate untrusted pull-request builds from privileged preview deployment jobs. - Require an approval gate or trusted maintainer action before deploying code from external contributors. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (4)

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger list contains broad, common phrases such as 'build failing' and 'deploy automatically' that can match many ordinary developer conversations. This increases the chance of unintended skill activation, which can cause the agent to apply CI/CD-specific guidance in the wrong context or too eagerly in adjacent tasks.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
| Stack | Recommended | Why |
|-------|-------------|-----|
| Web (Next.js, Nuxt, static) | Vercel, Netlify | Zero-config, auto-deploys, preview URLs |
| Mobile (iOS/Android/Flutter) | Codemagic, Bitrise + Fastlane | Pre-configured signing, app store upload |
| Backend/Docker | GitHub Actions, GitLab CI | Full control, self-hosted runners option |
| Monorepo | Nx/Turborepo + GHA | Affected detection, build caching |
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The Docker template includes an authenticated login and unconditionally pushes built images to a remote registry on pushes to main, but does not clearly warn users that it will publish artifacts externally using repository-scoped credentials. In a copy-paste template skill, that omission can cause accidental public or organizational image publication, potentially exposing proprietary code, configuration, or sensitive build outputs.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USER }}
        key: ${{ secrets.SSH_KEY }}
        script: sudo systemctl restart myapp
```

## Common Issues
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.