# Signing Solution Packages

> Digitally sign automation solution packages during the pack operation using the CLI.

## Signing Solution Packages

UiPath CLI 25.10 introduces the ability to digitally sign automation solution packages during the pack operation. Package signing provides authenticity verification and ensures that solution packages have not been tampered with after creation, enhancing security in your CI/CD pipeline.

When you sign a solution package, the CLI:
1. Creates the solution `.zip` package file
2. Applies a digital signature using your certificate to all Nuget packages inside the `.zip` file.
3. Optionally timestamps the signature for long-term validity

### Supported certificate types

The CLI supports PKCS#12 (.pfx) certificate format.

:::important
The certificate must:
- Include a private key for signing
- Be valid (not expired)
- Have code signing capabilities
:::

### Parameters

The `solution pack` command supports the following signing parameters:

| Parameter | Description | Required |
|-----------|-------------|----------|
| `--certificatePath` | Path to the certificate file (.pfx) | Yes (if signing) |
| `--certificatePassword` | Password for the certificate file | No |
| `--timestampServerUrl` | URL of the RFC 3161 timestamp server | No |

### Usage examples

#### Basic signing with certificate

```bash
# Windows
uipcli solution pack "C:\Solutions\MyAutomationSolution" `
  -v "1.0.0" `
  -o "C:\Packages" `
  --certificatePath "C:\Certificates\codesign.pfx" `
  --certificatePassword "YourPassword123"

# Linux/macOS
uipcli solution pack "./MyAutomationSolution" \
  -v "1.0.0" \
  -o "./packages" \
  --certificatePath "./certificates/codesign.pfx" \
  --certificatePassword "YourPassword123"
```

## Signing with timestamp server

Adding a timestamp ensures the signature remains valid even after the certificate expires.

```bash
uipcli solution pack "./MyAutomationSolution" \
  -v "1.0.0" \
  -o "./packages" \
  --certificatePath "./certificates/codesign.pfx" \
  --certificatePassword "YourPassword123" \
  --timestampServerUrl "http://timestamp.digicert.com"
```

## Signing with Orchestrator library dependencies

```bash
uipcli solution pack "./MyAutomationSolution" \
  -v "1.0.0" \
  -o "./packages" \
  --libraryOrchestratorUrl "https://cloud.uipath.com/" \
  --libraryOrchestratorTenant "Default" \
  -A "myorg" \
  -I "becc663c-8f1e-409a-a75f-c00330d80bc8" \
  -S '********' \
  --libraryOrchestratorApplicationScope "OR.Folders OR.Execution" \
  --libraryOrchestratorFolder "Shared" \
  --certificatePath "./certificates/codesign.pfx" \
  --certificatePassword "YourPassword123" \
  --timestampServerUrl "http://timestamp.digicert.com"
```

## Signing with passwordless certificate

```bash
uipcli solution pack "./MyAutomationSolution" \
  -v "1.0.0" \
  -o "./packages" \
  --certificatePath "./certificates/codesign.pfx"
```

## CI/CD pipeline example (GitHub Actions)

```yaml
- name: Pack and sign solution package
  env:
    CERT_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
    APP_SECRET: ${{ secrets.UIPATH_APP_SECRET }}
  run: |
    uipcli solution pack "./src/MyAutomationSolution" \
      -v "1.0.${{ github.run_number }}" \
      -o "./output" \
      --libraryOrchestratorUrl "https://cloud.uipath.com/" \
      --libraryOrchestratorTenant "Default" \
      -A "myorg" \
      -I "becc663c-8f1e-409a-a75f-c00330d80bc8" \
      -S "$APP_SECRET" \
      --libraryOrchestratorApplicationScope "OR.Folders OR.Execution" \
      --certificatePath "./certs/codesign.pfx" \
      --certificatePassword "$CERT_PASSWORD" \
      --timestampServerUrl "http://timestamp.digicert.com"
```

## Azure DevOps pipeline example

```yaml
- task: PowerShell@2
  displayName: 'Pack and Sign Solution'
  env:
    CERT_PASSWORD: $(CertificatePassword)
    APP_SECRET: $(UiPathAppSecret)
  inputs:
    targetType: 'inline'
    script: |
      uipcli solution pack "$(Build.SourcesDirectory)\MyAutomationSolution" `
        -v "$(Build.BuildNumber)" `
        -o "$(Build.ArtifactStagingDirectory)" `
        --libraryOrchestratorUrl "https://cloud.uipath.com/" `
        --libraryOrchestratorTenant "Default" `
        -A "myorg" `
        -I "becc663c-8f1e-409a-a75f-c00330d80bc8" `
        -S "$env:APP_SECRET" `
        --libraryOrchestratorApplicationScope "OR.Folders OR.Execution" `
        --certificatePath "$(Build.SourcesDirectory)\certs\codesign.pfx" `
        --certificatePassword "$env:CERT_PASSWORD" `
        --timestampServerUrl "http://timestamp.digicert.com"
```

## Recommended timestamp servers

Using a timestamp server is recommended to ensure signatures remain valid after certificate expiration:

- `http://timestamp.digicert.com` - DigiCert
- `http://timestamp.comodoca.com` - Sectigo (Comodo)
- `http://timestamp.globalsign.com` - GlobalSign
- `http://timestamp.sectigo.com` - Sectigo

## Best practices

### Secure certificate storage

- Never commit certificates to version control
- Use secure storage solutions:
  - Azure Key Vault
  - AWS Secrets Manager
  - HashiCorp Vault
  - GitHub Secrets / Azure DevOps Secure Files
  - CI/CD platform secret management

### Timestamp usage

- Always use a timestamp server in production environments
- Timestamps ensure signature validity beyond certificate expiration

### Certificate management

- Use dedicated code signing certificates
- Rotate certificates before expiration
- Maintain certificate backups securely
