# Chainsaw vs JFrog Xray | Keep Artifactory. Move the refusal.

> Xray inspects what's already cached. Chainsaw refuses before the cache. Coexist 90 days, decommission Xray's policy surface on a ladder. Artifactory storage untouched.

Source: https://chain305.com/vs-jfrog-xray/

---

Positioning

# Keep Artifactory. Move the refusal.

Xray inspects what Artifactory has already cached. Chainsaw refuses on the install path, before the cache.

[See the 90-day migration arc →](https://chain305.com/migrate/from-jfrog-xray/)

Peer framing

## What stays. What moves.

Chainsaw replaces one layer: the policy seam in front of Artifactory. Storage stays.

1.  01 · Developer or CI
    
    `npm install`

3.  02 · Chainsaw (new, in front)
    
    -   refuses on the install path
    -   writes a signed audit row

5.   Refused
    
    never cached
    
     Allowed
    
    fetched into Artifactory (unchanged), served on the same URL
    

Structural diff

## Where the two products draw the line

Capability

JFrog Xray Policy layer on cached artifacts

Chainsaw Install-path refusal

Enforcement point

After the artifact reaches the cache.

Before the cache. A refused artifact is never resident.

Signal coverage

CVE feeds, license metadata, operational-risk heuristics.

CVE + license + 25 supply-chain signals.

Federation model

Per Artifactory instance; cross-BU consolidation is operational.

One org-wide policy set, repository-scoped rules, one audit stream.

Kubernetes admission

Separate Gatekeeper / OPA integration.

Same Rego at the PR check, install, publish, K8s admission, runtime. The PR check reads a dependency diff, so byte-level rules apply from install on.

AI coding-agent path

No native MCP surface.

MCP server exposes refusal + the Billy approval queue.

Air-gapped intel bundle

Manual feed updates.

Signed Sigstore bundle, hot-swappable.

False-positive loop

Manual policy edit; ticket round-trip.

Billy approval queue captures the override.

Named signals

## Supply-chain signals beyond CVE and license

Named by registry ID, so they can be argued with.

Install script fetches remote content

The install or postinstall script pulls remote content at install time. `sc.install_script_fetches_remote`

Encoded eval in install script

An obfuscated or encoded payload decoded and executed during install. `sc.install_script_eval_encoded`

Publisher changed

The maintainer set differs from the previous version: the common shape of account takeover. `sc.publisher_changed`

Young maintainer account

The youngest maintainer account is under 90 days old. `sc.maintainer_account_young`

Shell access appeared

This version spawns a shell and the previous scanned version did not. `sc.shell_access_appeared`

Hidden Unicode

Invisible or bidirectional Unicode that can hide code from review. `sc.hidden_unicode`

Typosquat

The name is highly similar to a popular package. `sc.typosquat_high`

Publish-velocity anomaly

A publisher set pushed unusually many releases in 24 hours: the Shai-Hulud worm shape. `sc.publish_velocity_anomaly`

Manifest confusion

The registry's package.json and the tarball's package.json disagree. `sc.manifest_confusion`

Repo ownership mismatch

The advertised source repo belongs to a different account than the publisher. `sc.repo_ownership_mismatch`

Transitive malware

A package deeper in the dependency closure is on the known-malicious index. `sc.transitive_malware`

Provenance and signature

Verifiable Sigstore/SLSA provenance, and a signature checked against an independent trust root. `sc.provenance_verified · sc.signature_verified`

Dangerous pickle opcode

Model weights reference os, subprocess or eval. Loading the file runs code. `ai.dangerous_pickle_opcode`

Unverified MCP server

Declares an MCP server without provenance or a verified source repo. `ai.mcp_server_unverified`

Unpinned Action ref

A GitHub Action referenced by branch or tag instead of a commit SHA. `action.unpinned_ref`

Very new package

Under 30 days old, with few versions. `maint.very_new_package`

Where Xray still wins

## Keep Xray for these.

Build promotion

Deeply integrated with the Artifactory artifact lifecycle.

Artifact lifecycle depth

Retention, staging and release-bundle plumbing.

JFrog Distribution

Edge replication for binary distribution at scale.

Generic-repo coverage

Generic binary repos beyond language packages.

Just renewed Xray?

## You do not have to rip it out.

Xray policies stay live through a 90-day side-by-side, then come off one watch at a time. Artifactory storage untouched.

[Book architecture review](https://chain305.com/chainsaw/signup) [Read the 90-day migration arc →](https://chain305.com/migrate/from-jfrog-xray/)

---

## Long form

The full text behind this page, including detail the page itself leaves out.

Positioning

### Keep Artifactory. Move the refusal.

Artifactory does artifact storage, identity, build promotion, and replication well. Xray inspects what is already cached. Chainsaw refuses on the install path — before the cache — using the same Rego at the PR check, install, publish, Kubernetes admission, and runtime. The PR check reads a dependency diff, so rules that need the package bytes take effect from the install path on.

[See the 90-day migration arc →](https://chain305.com/migrate/from-jfrog-xray/)

Peer framing

#### What stays. What moves.

Artifactory does artifact storage, identity, build promotion, and replication. Those stay. Existing repos keep serving on the same URLs, existing build promotion flows keep running, and the storage layer is not touched by a Chainsaw rollout.

Chainsaw replaces one layer: the policy and enforcement seam on the install path. Xray evaluates packages after Artifactory has already cached them. Chainsaw evaluates them before, on the request itself, and refuses on the path. The verdict is written as a signed audit row and re-used at Kubernetes admission and runtime through the same signed policy bundle.

Structural diff

#### Where the two products draw the line

Capability

JFrog Xray Policy layer on cached artifacts

Chainsaw Install-path refusal

Enforcement point Where in the install path the policy decision happens.

After the artifact reaches the cache. Xray scans what Artifactory has already stored.

Before the cache. The proxy refuses on the install path, so a refused artifact is never resident.

Signal coverage What the policy can reason about.

CVE feeds, license metadata, operational-risk heuristics.

CVE + license + 25 supply-chain signals (install-script behavior, maintainer takeover, worm bursts, hidden Unicode, typosquat, publish-velocity, reserved namespaces, AI capability signals, compound rules).

Federation model How policy reaches multiple business units.

Policies are configured per Artifactory instance; cross-BU consolidation is operational.

One org-wide policy set, repository-scoped rules, one audit stream.

Kubernetes admission Same rule at install and at deploy.

Separate Gatekeeper / OPA integration with its own policy surface.

Same Rego evaluated at the PR check, install, publish, K8s admission, and runtime.

AI coding-agent path How autonomous agents inherit your policy.

No native MCP surface for AI agents.

MCP server exposes refusal + Billy approval queue to coding agents.

Air-gapped intel bundle How the signal feed reaches a disconnected site.

Manual feed updates; bespoke for air-gapped sites.

Signed Sigstore bundle, hot-swappable; one binary across SaaS, VPC, air-gapped.

Pricing shape What the line item maps to.

Per-Artifactory-tier, seat-loaded.

Per-decision on the install path.

False-positive loop How a wrong refusal gets corrected.

Manual policy edit; ticket round-trip.

Billy approval queue captures the override; Bayesian tuning narrows the rule.

Named signals

#### 25 supply-chain signals beyond CVE + license

Xray's policy surface is built around CVE feeds and license metadata. Chainsaw carries those plus 25 supply-chain signals. Named, so they can be argued with.

-   Install-script exfiltration PhantomRaven-class postinstall network egress patterns.
-   Maintainer-account takeover Axios-pattern: sudden publisher change + diff shape mismatch.
-   Worm bursts Shai-Hulud-class self-propagating npm package waves.
-   Hidden Unicode GlassWorm / Trojan Source bidi and zero-width payloads in source.
-   Reserved-namespace confusion Birsan-pattern dependency confusion across public/private scopes.
-   Typosquat across 15 ecosystems Edit-distance + popularity-skew across npm, PyPI, Maven, Gradle, Docker, NuGet, RubyGems, Cargo, Go, Swift, CocoaPods, Composer, Hugging Face, pub, GitHub Actions.
-   Publish-velocity anomalies Burst publishes against historical baseline for that maintainer.
-   Reserved-username squat New publisher whose name shadows a high-trust maintainer.
-   AI capability signals Pickle ops, arbitrary-eval surfaces, MCP server provenance.
-   Compound takeover signature Multiple weak signals combining into a high-confidence verdict.
-   Postinstall obfuscation Base64 / hex / eval chains in lifecycle scripts.
-   Outbound network classes DNS-tunnel and rare-TLD heuristics on install-time egress.
-   Tag/version replay Re-published version with diverged content hash.
-   Source/dist drift GitHub source vs published tarball mismatch.
-   Lockfile injection Lock-only dependency added without manifest update.
-   Scoped-namespace impersonation Unscoped package masquerading as an @org member.
-   Cross-ecosystem name collisions Same name registered on multiple registries with different owners.
-   Suspect license combinations License metadata at odds with declared file headers.
-   Dormant-package wake Years-quiet package suddenly publishing.
-   First-publish risk Newly registered package with credential-adjacent capability.
-   Build-script reach Native gyp / setup.py callouts to network or filesystem.
-   Embedded binary risk Pre-built native binaries with no reproducible source.
-   Telemetry beacons Install-time pings to attacker-controlled collectors.
-   Org-policy compound rule Customer-authored Rego combining any of the above.
-   Signed-attestation gaps Missing or mismatched in-toto / Sigstore attestations.

Where Xray still wins

#### Honest section.

-   **Build promotion.** The promotion workflow inside Artifactory + Xray is deeply integrated with the artifact lifecycle. If that is your primary control point, Xray owns it.
-   **Artifact lifecycle depth.** Retention, staging, and release-bundle plumbing that ride on Artifactory metadata.
-   **JFrog Distribution.** Edge replication for binary distribution at scale.
-   **Generic-repo coverage.** The broader storage ecosystem — generic binary repos beyond language packages — sits on JFrog.

Stating where Xray wins earns the right to claim where Chainsaw does. The recommendation is coexistence, not replacement of the storage tier.

Coexistence story

#### Run both for 90 days. Then ladder Xray's policy surface off.

Chainsaw sits in front of Artifactory in monitor mode. A side-by-side decision diff dashboard shows where Xray and Chainsaw agree and where they don't. The Billy approval queue absorbs false positives. Watches migrate one BU at a time. Artifactory storage stays.

[Read the 90-day migration arc →](https://chain305.com/migrate/from-jfrog-xray/)

Just renewed Xray?

#### You do not have to rip it out.

Chainsaw runs in front of Artifactory. Xray policies stay live through a 90-day side-by-side. Decommission Xray's policy surface on a ladder, one watch at a time. Artifactory storage untouched.

[Book architecture review](https://chain305.com/chainsaw/signup) [Read the 90-day migration arc →](https://chain305.com/migrate/from-jfrog-xray/)
