JFrog Hardening Guide
Artifact management security for repository permissions, Xray policies, and access tokens
Overview
JFrog Artifactory is a universal binary repository supporting 40+ package formats across CI/CD pipelines. CVE-2024-6915 (CVSS 9.3) cache corruption vulnerability and research finding 70 cases of anonymous write permissions demonstrate artifact poisoning risks. As the central artifact repository, compromise enables supply chain attacks through dependency confusion and malicious package injection.
Intended Audience
- Security engineers hardening artifact repositories
- DevOps engineers configuring Artifactory
- GRC professionals assessing supply chain security
- Platform teams managing binary repositories
How to Use This Guide
- L1 (Baseline): Essential controls for all organizations
- L2 (Hardened): Enhanced controls for security-sensitive environments
- L3 (Maximum Security): Strictest controls for regulated industries
Scope
This guide covers JFrog Artifactory security configurations including authentication, repository permissions, Xray integration, and artifact integrity controls.
Table of Contents
- Authentication & Access Controls
- Repository Security
- Artifact Integrity
- Xray Security Scanning
- Monitoring & Detection
- Compliance Quick Reference
1. Authentication & Access Controls
1.1 Enforce SSO with MFA
Profile Level: L1 (Baseline) NIST 800-53: IA-2(1)
Description
Require SAML SSO with MFA for all Artifactory access.
ClickOps Implementation
Step 1: Configure SAML SSO
- Navigate to: Administration → Security → Settings → SSO
- Configure:
- IdP Login URL: Your IdP endpoint
- IdP Certificate: Upload certificate
- Service Provider ID: Artifactory URL
Step 2: Disable Local Authentication
- Navigate to: Administration → Security → Settings
- Disable: Allow anonymous access
- Configure: Require SSO for all users
Step 3: Configure Access Tokens
- Navigate to: Administration → Identity and Access → Access Tokens
- Configure token policies:
- Expiration: 90 days maximum
- Scopes: Minimum required
Code Implementation
Code Pack: Terraform
# Configure SAML SSO for centralized authentication with MFA enforcement
resource "artifactory_saml_settings" "sso" {
enable = true
login_url = var.saml_idp_url
certificate = var.saml_idp_certificate
service_provider_name = var.saml_service_provider_id
allow_user_to_access_profile = false
auto_redirect = true
no_auto_user_creation = false
use_encrypted_assertion = true
}
# Disable anonymous access to force authenticated sessions
resource "artifactory_general_security" "disable_anonymous" {
enable_anonymous_access = false
}
1.2 Implement Permission Targets
Profile Level: L1 (Baseline) NIST 800-53: AC-3, AC-6
Description
Configure granular permissions for repository access.
Rationale
Why This Matters:
- Research found 70 cases of anonymous write permissions
- Write access enables artifact poisoning
- Dependency confusion attacks require upload capability
Attack Scenario: Dependency confusion attack uploads malicious package to internal repository; cache poisoning replaces legitimate artifacts.
ClickOps Implementation
Step 1: Create Permission Targets
- Navigate to: Administration → Identity and Access → Permissions
- Create permission targets:
Production-Read:
- Repositories:
libs-release-local - Actions: Read, Annotate
- Groups: All developers
Production-Write:
- Repositories:
libs-release-local - Actions: Deploy, Delete
- Groups: Release managers only
Build-Upload:
- Repositories:
libs-snapshot-local - Actions: Deploy
- Groups: CI/CD service accounts
Step 2: Disable Anonymous Access
- Navigate to: Administration → Security → Settings
- Disable: Allow anonymous access
- Audit all repositories for anonymous permissions
Step 3: Restrict Admin Access
- Limit admin role to 2-3 users
- Create separate roles for different functions
- Audit admin access quarterly
Code Implementation
Code Pack: Terraform
# Production-Read: Read-only access for developers to release repositories
resource "artifactory_permission_target" "production_read" {
name = "hth-production-read"
repo {
repositories = [var.release_repo_key]
actions {
groups {
name = var.release_readers_group
permissions = ["read", "annotate"]
}
}
}
}
# Production-Write: Deploy access restricted to release managers
resource "artifactory_permission_target" "production_write" {
name = "hth-production-write"
repo {
repositories = [var.release_repo_key]
actions {
groups {
name = var.release_writers_group
permissions = ["read", "annotate", "deploy", "delete"]
}
}
}
}
# Build-Upload: CI/CD service accounts can deploy to snapshot repos only
resource "artifactory_permission_target" "build_upload" {
name = "hth-build-upload"
repo {
repositories = [var.snapshot_repo_key]
actions {
groups {
name = var.ci_cd_group
permissions = ["read", "deploy"]
}
}
}
}
# L3: Strict read-only for all non-admin users on release repos
resource "artifactory_permission_target" "strict_readonly" {
count = var.profile_level >= 3 ? 1 : 0
name = "hth-strict-readonly"
repo {
repositories = [var.release_repo_key]
actions {
groups {
name = var.release_readers_group
permissions = ["read"]
}
}
}
}
1.3 Secure API Keys and Tokens
Profile Level: L1 (Baseline) NIST 800-53: IA-5
Description
Manage API keys and access tokens securely.
ClickOps Implementation
Step 1: Audit Existing Keys
- Navigate to: Administration → Identity and Access → Access Tokens
- Review all active tokens
- Revoke unused tokens
Step 2: Create Scoped Tokens
See the CLI pack below for scoped token creation commands.
Step 3: Rotate Tokens
| Token Type | Rotation Frequency |
|---|---|
| CI/CD tokens | Quarterly |
| User API keys | Semi-annually |
| Admin tokens | Quarterly |
Code Implementation
Code Pack: Terraform
# Create a scoped access token for CI/CD pipelines with limited expiry
resource "artifactory_scoped_token" "ci_cd_token" {
scopes = ["applied-permissions/groups:${var.ci_cd_group}"]
expires_in = var.token_expiry_seconds
description = "HTH: Scoped CI/CD token with ${var.token_expiry_seconds / 86400}-day expiry"
}
# L2: Create a shorter-lived admin token with tighter rotation
resource "artifactory_scoped_token" "admin_token" {
count = var.profile_level >= 2 ? 1 : 0
scopes = ["applied-permissions/admin"]
expires_in = 2592000 # 30 days
description = "HTH: Short-lived admin token (30-day expiry, L2+)"
}
Code Pack: CLI Script
# Create scoped token via CLI
jf rt access-token-create \
--groups readers \
--scope applied-permissions/groups:readers \
--expiry 7776000 # 90 days
2. Repository Security
2.1 Configure Repository Layout Security
Profile Level: L1 (Baseline) NIST 800-53: CM-7
Description
Harden repository configurations to prevent unauthorized access.
ClickOps Implementation
Step 1: Review Repository Settings
- Navigate to: Administration → Repositories
- For each repository, verify:
- Anonymous access: Disabled
- Include/Exclude patterns: Configured
- Allow content browsing: Restricted
Step 2: Configure Virtual Repository Security
- For virtual repositories, configure resolution order:
- Internal repositories first
- Remote repositories second
- This prevents dependency confusion
Step 3: Disable Unused Features
- Disable: File listing for remote repositories
- Disable: Properties search (if not needed)
Code Implementation
Code Pack: Terraform
# Harden local Maven release repository with restricted settings
resource "artifactory_local_maven_repository" "release" {
key = var.release_repo_key
description = "HTH: Hardened release repository - handles releases only"
handle_releases = true
handle_snapshots = false
suppress_pom_consistency_checks = false
xray_index = true
property_sets = ["artifactory"]
}
# Harden local Maven snapshot repository
resource "artifactory_local_maven_repository" "snapshot" {
key = var.snapshot_repo_key
description = "HTH: Hardened snapshot repository - handles snapshots only"
handle_releases = false
handle_snapshots = true
suppress_pom_consistency_checks = false
xray_index = true
max_unique_snapshots = 5
}
2.2 Remote Repository Security
Profile Level: L1 (Baseline) NIST 800-53: SC-7
Description
Secure remote repository (proxy) configurations.
ClickOps Implementation
Step 1: Configure Remote Repository Settings
- Navigate to: Repositories → Remote
- For each remote repository:
- Hard fail: Enable for security artifacts
- Store artifacts locally: Enable
- Block mismatching MIME types: Enable
Step 2: Configure Exclude Patterns
See the CLI pack below for recommended exclude patterns.
Step 3: Enable Checksum Validation
- Configure: Checksum policy: Fail (L2)
- Validate checksums for all downloaded artifacts
Code Implementation
Code Pack: Terraform
# Harden remote Maven repository proxy with security controls
resource "artifactory_remote_maven_repository" "secure_remote" {
key = var.remote_repo_key
url = var.remote_repo_url
description = "HTH: Hardened remote repository proxy"
store_artifacts_locally = true
hard_fail = true
block_mismatching_mime_types = true
excludes_pattern = var.blocked_remote_extensions
xray_index = true
content_synchronisation {
enabled = false
}
}
# L2: Enforce strict checksum validation on remote repositories
resource "artifactory_remote_maven_repository" "strict_checksum_remote" {
count = var.profile_level >= 2 ? 1 : 0
key = "${var.remote_repo_key}-strict"
url = var.remote_repo_url
description = "HTH: Strict checksum remote repository (L2+)"
store_artifacts_locally = true
hard_fail = true
block_mismatching_mime_types = true
excludes_pattern = var.blocked_remote_extensions
xray_index = true
remote_repo_checksum_policy_type = "fail"
content_synchronisation {
enabled = false
}
}
2.3 Prevent Dependency Confusion
Profile Level: L1 (Baseline) NIST 800-53: SI-7
Description
Configure Artifactory to prevent dependency confusion attacks.
Implementation
Step 1: Configure Virtual Repository Priority
See the CLI pack below for virtual repository configuration.
Step 2: Reserve Internal Package Names
- Create placeholder packages in remote proxies
- Block external packages with internal names
Step 3: Enable Priority Resolution
- Navigate to: Virtual Repository → Advanced
- Configure: Priority Resolution: Enabled
- Set internal repositories higher priority
Code Implementation
Code Pack: Terraform
# Virtual repository with internal repos resolved first to prevent
# dependency confusion attacks. Internal repositories take priority
# over external/remote repositories in the resolution order.
resource "artifactory_virtual_maven_repository" "secure_virtual" {
key = var.virtual_repo_key
description = "HTH: Virtual repo with priority resolution to prevent dependency confusion"
repositories = concat(var.internal_repo_keys, var.external_repo_keys)
default_deployment_repo = var.internal_repo_keys[0]
artifactory_requests_can_retrieve_remote_artifacts = true
force_maven_authentication = true
}
# L2: Disable remote artifact retrieval through virtual repos
# to further isolate internal from external dependencies
resource "artifactory_virtual_maven_repository" "isolated_virtual" {
count = var.profile_level >= 2 ? 1 : 0
key = "${var.virtual_repo_key}-isolated"
description = "HTH: Isolated virtual repo - no remote retrieval (L2+)"
repositories = var.internal_repo_keys
default_deployment_repo = var.internal_repo_keys[0]
artifactory_requests_can_retrieve_remote_artifacts = false
force_maven_authentication = true
}
Code Pack: CLI Script
# Virtual repository configuration
virtual_repository:
repositories:
- internal-libs # First priority (internal)
- remote-maven # Second priority (external)
default_deployment_repo: internal-libs
3. Artifact Integrity
3.1 Enable Artifact Signing
Profile Level: L2 (Hardened) NIST 800-53: SI-7
Description
Require artifact signing for production deployments.
Implementation
Step 1: Configure GPG Signing
See the CLI pack below for signing and verification commands.
Step 2: Verify Signatures on Download
See the CLI pack below for download verification commands.
Step 3: Enforce Signing Policy
- Use Xray policies to block unsigned artifacts
- Document signing requirements
Code Implementation
Code Pack: Terraform
# Configure GPG signing key for artifact verification (L2+)
resource "artifactory_keypair" "gpg_signing" {
count = var.profile_level >= 2 ? 1 : 0
pair_name = "hth-artifact-signing"
pair_type = "GPG"
alias = "hth-gpg"
public_key = var.gpg_public_key
passphrase = ""
}
# Associate signing key with release repository for signature enforcement
resource "artifactory_local_maven_repository" "signed_release" {
count = var.profile_level >= 2 ? 1 : 0
key = "${var.release_repo_key}-signed"
description = "HTH: Signed release repository with GPG verification (L2+)"
handle_releases = true
handle_snapshots = false
xray_index = true
primary_keypair_ref = artifactory_keypair.gpg_signing[0].pair_name
}
Code Pack: CLI Script
# Sign artifact during deployment
jf rt upload --gpg-key=/path/to/key.asc artifact.jar libs-release-local/
# Verify artifact signature
jf rt download libs-release-local/artifact.jar --gpg-key=/path/to/public.asc
3.2 Immutable Artifacts
Profile Level: L2 (Hardened) NIST 800-53: SI-7
Description
Make release artifacts immutable to prevent tampering.
ClickOps Implementation
Step 1: Configure Repository Settings
- Navigate to: Repository → Advanced
- Enable: Handle releases (for release repos)
- Disable: Handle snapshots (for release repos)
- Enable: Suppress POM consistency checks: No
Step 2: Create Immutable Policy
- Use release repository for production artifacts
- Block re-deployment of existing versions
- Delete permissions restricted to admins
Code Implementation
Code Pack: Terraform
# Immutable release repository: block re-deployment of existing versions (L2+)
# Once an artifact version is published, it cannot be overwritten.
resource "artifactory_local_maven_repository" "immutable_release" {
count = var.profile_level >= 2 ? 1 : 0
key = "${var.release_repo_key}-immutable"
description = "HTH: Immutable release repository - no redeployment (L2+)"
handle_releases = true
handle_snapshots = false
suppress_pom_consistency_checks = false
xray_index = true
# Block re-deployment to enforce immutability
# Users cannot overwrite existing artifact versions
}
# L3: Restrict delete permissions to prevent artifact removal
resource "artifactory_permission_target" "immutable_no_delete" {
count = var.profile_level >= 3 ? 1 : 0
name = "hth-immutable-no-delete"
repo {
repositories = ["${var.release_repo_key}-immutable"]
actions {
groups {
name = var.release_readers_group
permissions = ["read"]
}
groups {
name = var.release_writers_group
permissions = ["read", "annotate", "deploy"]
}
}
}
}
4. Xray Security Scanning
4.1 Configure Xray Policies
Profile Level: L1 (Baseline) NIST 800-53: RA-5
Description
Configure JFrog Xray for vulnerability and license scanning.
ClickOps Implementation
Step 1: Create Security Policy
- Navigate to: Xray → Policies → New Policy
- Configure:
- Type: Security
- Rules:
- Critical CVE: Block download
- High CVE: Warn
- Actions: Block release, notify
Step 2: Create Watch
- Navigate to: Xray → Watches → New Watch
- Configure:
- Resources: Production repositories
- Policy: Security policy created above
Step 3: Enable Automatic Scanning
- Enable scanning on upload
- Configure periodic rescanning
- Set up notifications
4.2 CVE Remediation Workflow
Profile Level: L1 (Baseline)
Implementation
Step 1: Monitor CVE Alerts
- Configure Xray notifications
- Integrate with ticketing system
- Assign remediation owners
Step 2: Block Vulnerable Artifacts
See the CLI pack below for Xray policy configuration.
Code Implementation
Code Pack: CLI Script
# Xray policy - Block critical vulnerabilities
policy:
name: block-critical-cves
type: security
rules:
- name: critical-cve-block
criteria:
min_severity: critical
actions:
block_download:
active: true
fail_build: true
5. Monitoring & Detection
5.1 Audit Logging
Profile Level: L1 (Baseline) NIST 800-53: AU-2, AU-3
Description
Configure comprehensive audit logging.
ClickOps Implementation
Step 1: Enable Audit Log
- Navigate to: Administration → Security → Settings
- Enable: Audit log
- Configure retention
Step 2: Export to SIEM
- Configure log shipping to SIEM
- Parse Artifactory access logs
Detection Queries
See the DB pack below for SIEM detection queries.
Code Implementation
Code Pack: Terraform
# Webhook for forwarding deployment events to SIEM
resource "artifactory_webhook" "deploy_events" {
count = var.audit_webhook_url != "" ? 1 : 0
key = "hth-deploy-audit"
description = "HTH: Forward artifact deploy events to SIEM"
event_types = ["deployed", "deleted", "moved", "copied"]
url = var.audit_webhook_url
enabled = true
criteria {
any_local = true
any_remote = false
}
}
# L2: Webhook for permission and access control change events
resource "artifactory_webhook" "access_events" {
count = var.profile_level >= 2 && var.audit_webhook_url != "" ? 1 : 0
key = "hth-access-audit"
description = "HTH: Forward access control events to SIEM (L2+)"
event_types = ["deployed", "deleted", "moved", "copied", "downloaded"]
url = var.audit_webhook_url
enabled = true
criteria {
any_local = true
any_remote = true
}
}
# L3: Comprehensive download audit for all repository access
resource "artifactory_webhook" "download_audit" {
count = var.profile_level >= 3 && var.audit_webhook_url != "" ? 1 : 0
key = "hth-download-audit"
description = "HTH: Audit all artifact downloads (L3)"
event_types = ["downloaded"]
url = var.audit_webhook_url
enabled = true
criteria {
any_local = true
any_remote = true
}
}
6. Compliance Quick Reference
SOC 2 Mapping
| Control ID | Artifactory Control | Guide Section |
|---|---|---|
| CC6.1 | SSO enforcement | 1.1 |
| CC6.2 | Permission targets | 1.2 |
| CC8.1 | Artifact integrity | 3.1 |
Supply Chain Security (SLSA)
| Level | Requirements | Artifactory Controls |
|---|---|---|
| SLSA 1 | Build provenance | Build info capture |
| SLSA 2 | Signed provenance | GPG signing |
| SLSA 3 | Security controls | Xray scanning, access control |
Appendix A: Edition Compatibility
| Control | OSS | Pro | Enterprise |
|---|---|---|---|
| SSO (SAML) | ❌ | ✅ | ✅ |
| Access Tokens | Basic | ✅ | ✅ |
| Xray | ❌ | Add-on | ✅ |
| Audit Log | Basic | ✅ | ✅ |
| HA/DR | ❌ | ❌ | ✅ |
Appendix B: References
Official JFrog Documentation:
- JFrog Trust Center
- JFrog Help Center
- Security Best Practices
- Security Configuration
- Access Control
- Xray Documentation
- JFrog Security Advisories
API & Developer Resources:
Compliance Frameworks:
- SOC 2 Type II, ISO 27001, ISO 27017, ISO 27701 – via JFrog Trust Center
Security Incidents:
- CVE-2024-6915 (CVSS 9.3): Cache poisoning vulnerability in JFrog Artifactory allowing attackers to corrupt cached artifacts in the software supply chain. Affects versions below 7.90.6 and corresponding LTS releases. Cloud environments were patched automatically; on-premise instances require manual upgrade.
Changelog
| Date | Version | Maturity | Changes | Author |
|---|---|---|---|---|
| 2025-12-14 | 0.1.0 | draft | Initial JFrog Artifactory hardening guide | Claude Code (Opus 4.5) |