# Welcome to Seal Security

The remediation platform for open-source vulnerabilities.

<figure><img src="/files/SMhpq4kR9EnerKEEF8ri" alt=""><figcaption></figcaption></figure>

Seal Security is a remediation platform for open-source vulnerabilities. It produces **sealed packages**: drop-in replacements for the public versions you already use, with security fixes backported in. A sealed package is **fully compatible** with the version it replaces and **free of high and critical vulnerabilities** (lower severities, on request). You get the fixes you need without any of the breaking changes that come with an upgrade.

These docs cover the full scope of the Seal Platform: connecting your environment, discovering what is vulnerable, integrating the Seal CLI into your CI/CD pipeline, and operating Seal day to day. That includes the Seal AI Agent for natural-language interaction with the platform, the Seal Engineer for autonomous workflows, enterprise-grade reporting through the Reports Manager, and the integrations with your existing security stack.

## Where to start

Pick the path that matches what you are trying to do.

| You want to...                           | Start here                                                            |
| ---------------------------------------- | --------------------------------------------------------------------- |
| Run an end-to-end Proof of Value         | [Your first Proof of Value](/getting-started/proof-of-value)          |
| Understand what Seal is and how it works | [What is Seal Security](/introduction/what-is-seal)                   |
| See the full structure of these docs     | [What you will find in these docs](/introduction/navigating-the-docs) |
| Find a specific term                     | [Glossary](/introduction/glossary)                                    |

## What Seal protects

Seal supports five products at the same level. Each addresses a different layer of your stack.

* **Seal Apps**: your application's third-party open-source dependencies (npm, pip, Maven, Gradle, Go modules, Composer, Bundler, NuGet, and more).
* **Seal OS**: Linux/OS-level packages, including EOL distributions.
* **Seal Base Images**: clean container base images derived from existing public images.
* **Seal My Container**: your existing private container images, sealed and pushed back to your own registry.
* **Seal Vendor Apps**: open-source dependencies and language runtimes inside vendor-supplied containers you run, such as a Kafka image.

For one page per product, see [The Seal product family](/introduction/product-family).

## Trust by default

Every artifact Seal produces is cryptographically signed and ships with an attestation listing exactly which vulnerabilities have been fixed. You can view the code diff for any sealed package against its origin version, validate the signatures yourself, and download Software Bill of Materials (SBOM) files for sealed images.

For the full transparency stack, see [Trust, transparency & compliance](/trust/why-this-matters).


# Introduction and core concepts

What Seal is, the remediation problem it solves, and the vocabulary you'll see across these docs.

This section is the orientation layer. Read it once and the rest of the documentation makes more sense; skip it and you'll keep bumping into terms whose definitions live here.

## What's in this section

* [What is Seal Security](/introduction/what-is-seal): the one-page summary of what Seal does, what it covers, and how it works alongside your existing tools.
* [What you will find in these docs](/introduction/navigating-the-docs): the section map and role-based starting points.
* [The remediation problem](/introduction/remediation-problem): why patching open-source vulnerabilities is harder than it looks.
* [The Seal approach](/introduction/seal-approach): how sealed packages work as drop-in replacements rather than upgrades.
* [The Seal product family](/introduction/product-family): one page per product across the five.
* [Architecture overview](/introduction/architecture): the named components, how they connect, and where your data lives.
* [Your first hour with Seal, by role](/introduction/audience-guides): role-based entry points (security leader, DevOps engineer, developer, security analyst).
* [Glossary](/introduction/glossary): the full vocabulary used across the docs.


# What is Seal Security

What Seal does, what it covers, and how it works alongside your existing tools.

<figure><img src="/files/cQwdtYZxHvtHc5pW0OxI" alt="Seal Security covers a wide range of language and OS package ecosystems"><figcaption><p>Seal covers a wide range of language and OS package ecosystems.</p></figcaption></figure>

Seal Security is a platform that **remediates open-source vulnerabilities by replacing the affected packages with sealed versions**. A sealed version is built from the same origin version, with security fixes backported in. Two properties make a sealed package useful:

1. It is **fully compatible** with the version it replaces. The public release's API, behavior, and dependencies are preserved. No new features, no breaking changes, no migration burden.
2. It is **free of high and critical vulnerabilities**. Coverage of medium and low severity vulnerabilities is available through your Seal account team.

Drop a sealed package in. Your build keeps working. The vulnerabilities are gone.

## What Seal covers

The platform supports five products at the same level. Each addresses a different layer of your stack.

* **Seal Apps** remediates vulnerabilities in your application's third-party open-source dependencies (npm, pip, Maven, Gradle, Go modules, Composer, Bundler, NuGet, and more).
* **Seal OS** remediates vulnerabilities in OS-level packages and language runtimes (Node.js, Python, JVM, .NET, and others) on your servers and inside your containers, including EOL distributions.
* **Seal Base Images** delivers clean container base images derived from existing public images, with the underlying OS-level packages and language runtimes already remediated.
* **Seal My Container** produces a sealed copy of your existing private container images that you push back to your own registry.
* **Seal Vendor Apps** remediates vulnerabilities in the open-source dependencies and language runtime of vendor-supplied container images you run, such as a Kafka image.

Seal Apps covers the layer of open-source dependencies that your code pulls in. The other four products cover the layers below: language runtimes and OS-level packages. They differ in how the fix is delivered:

* **Seal OS** applies fixes in place via the Seal CLI on your servers and inside your containers.
* **Seal Base Images** delivers a clean base container image you build on top of.
* **Seal My Container** produces a sealed copy of your existing private container images.
* **Seal Vendor Apps** runs like Seal OS, applying fixes in place inside vendor-supplied containers in your environment.

See [The Seal product family](/introduction/product-family) for one page per product.

## What is in scope

Seal builds sealed packages and base images covering these ecosystems:

* **Application package ecosystems**: JavaScript, Java, Python, Go, Ruby, C/C++, C#, PHP.
* **OS package ecosystems**: APK, DEB, RPM.
* **Container images**: Alpine, Debian, Ubuntu, CentOS, Red Hat, and other major Linux distributions, including out-of-support releases.

By default, Seal backports fixes for **critical** and **high** severity vulnerabilities. Coverage of medium and low severity vulnerabilities is available through your Seal account team.

## What is not in scope

Seal does not build sealed versions for ecosystems beyond those listed above. Seal does not modify your application code or your infrastructure without your explicit instruction. Depending on the deployment method, that instruction takes a different form: a Sealing Rule, a CLI flag, or a manifest change you make yourself.

## How Seal works alongside your existing tools

Seal includes its own scanning capability for identifying vulnerable packages in your environment, and you can use it as your primary scanner. If you already use a vulnerability scanner like **Snyk**, **Black Duck**, **GitHub Advanced Security**, or **Ox Security**, Seal synchronizes its remediation findings into theirs so your existing dashboards stay accurate.

For external scanners that customers of yours run against your products (**Trivy**, **Wiz**, and others), Seal publishes a vulnerability feed and Vulnerability Exploitability eXchange (VEX) records that those tools can consume directly. For scanners that do not consume the feed, Seal supports a renaming feature. A renamed sealed package presents a different package name in your manifests, so the scanner does not find a matching entry in its vulnerability database and raises no warning.

## How Seal fits into your environment

Seal connects through one of four [package discovery modes](/discovering/package-discovery-mode): integrating the Seal CLI into your CI/CD pipeline, connecting Seal directly to your source control (GitHub, GitLab, or Azure DevOps), configuring the Seal Artifact Server as a remote, or uploading a manifest one-shot. The deepest integrations (CLI in CI/CD or source-control connection) give Seal the most accurate view of your packages and the smoothest day-to-day experience.

**Seal can operate without any access to your source code.** If your organization restricts source access for privacy or compliance reasons, the Seal CLI in CI/CD is the right path. The CLI runs inside your build, sees your dependencies there, and reports back to the Seal Platform without any source-repository connection.

Once Seal can see your packages, you decide what gets remediated. The most common path is to create Sealing Rules in the platform: instructions for which packages to replace and with which sealed versions. The Seal CLI applies those rules on your next CI/CD run. Other deployment methods apply fixes through different mechanisms: full-automatic replacement when the CLI runs in **all mode**, manifest pinning when the Seal Artifact Server is your remote, or manual download from the Repository page.

For the deeper "why patches over upgrades" framing, see [The remediation problem](/introduction/remediation-problem). For the conceptual model, see [The Seal approach](/introduction/seal-approach).


# What you will find in these docs

The section map, role-based starting points, and key terms.

These docs are organized into ten sections, ordered roughly from "what is this?" to "look up the exact flag I need."

## The section map

* [**Introduction**](/) (you are here): what Seal is, how it works, who it is for, and the vocabulary used throughout the docs.
* [**Getting started**](/getting-started/sign-up-and-sign-in): sign-in, user management, tokens, your first Seal Project, and an end-to-end Proof of Value walkthrough.
* [**Discovering vulnerabilities**](/discovering/how-seal-discovers-your-packages): how Seal finds your packages and how to navigate the platform to triage findings, including the Protection page, package states, and the Repository page.
* [**Using the Seal Platform**](/using-platform/working-with-the-platform): the day-to-day operating manual. Sealing Rules, working with each of the five products, the Seal AI Agent, the Seal Engineer, the Notification Center, the Reports Manager, and the Usage page.
* [**Application and OS setup**](/setup-apps-os/choosing-deployment-method): day-1 setup guides for Seal Apps and Seal OS, including the Seal CLI in CI/CD, the Seal Artifact Server, and standalone on-prem environments.
* [**Container and image setup**](/setup-containers/seal-base-images): day-1 setup guides for Seal Base Images, Seal My Container, and Seal Vendor Apps.
* [**Integrations**](/integrations/internal-scanners): connecting Seal to internal SCA scanners, external scanner feeds, JFrog Artifactory, GitHub, and the package renaming feature.
* [**Trust & compliance**](/trust/why-this-matters): code diff transparency, attestations, cryptographic signing, the 72-hour SLA, and supported compliance frameworks.
* [**Reference**](/reference/cli): CLI commands and flags, Public API, naming and versioning conventions, and network requirements.
* [**FAQ & disclosure**](/faq-and-disclosure/faq): frequently asked questions and the vulnerability disclosure policy.

## Find your starting point by role

| Role                 | Focus                                                           | Start here                                                                     |
| -------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **Security leader**  | Evaluating Seal; reviewing the Dashboard and reports            | [If you're a security leader](/introduction/audience-guides/security-leader)   |
| **DevOps engineer**  | Setting up integrations; operating the platform side day to day | [If you're a DevOps engineer](/introduction/audience-guides/devops-engineer)   |
| **Developer**        | Integrating the Seal CLI; applying Sealing Rules                | [If you're a developer](/introduction/audience-guides/developer)               |
| **Security analyst** | Day-to-day triage, notifications, and reports for leadership    | [If you're a security analyst](/introduction/audience-guides/security-analyst) |

The DevOps guide also covers DevSecOps and platform engineers; everyone responsible for the platform side of operating Seal in your organization.

## Key terms

Seal uses a precise vocabulary across these docs. The most common terms you will encounter:

* A **sealed package** is a drop-in replacement for a public package version, with security fixes backported in.
* A **Sealing Rule** tells Seal which package to replace and with which sealed version.
* A **Seal Project** is the entity inside the Seal Platform that represents one of your codebases or build pipelines.
* The **package discovery mode** of a Seal Project determines how Seal sees your packages: source code, CLI, artifact server, or imported manifest.
* A **deployment method** is how Seal is integrated into your environment, for example the Seal CLI in CI/CD, or the Seal Artifact Server as a configured remote.
* The **CLI fix mode** is the mode the Seal CLI runs in: **local** mode (rules from a `.seal-actions.yml` file in your source), **remote** mode (rules from the Seal Platform UI), or **all** mode (every vulnerable package replaced automatically).

The full vocabulary is in the [Glossary](/introduction/glossary).


# The remediation problem

Why remediating open-source vulnerabilities is hard, and what the cost of chasing upgrades does to a team.

Open-source vulnerabilities are reported every day. The hard part is not knowing they exist. The hard part is **remediating** them.

The traditional remediation path is to upgrade the affected package. On paper, that is straightforward: a CVE is published, the maintainer ships a fix, you take the new version. In practice, every layer adds friction. Direct dependencies you do not own. Transitive dependencies you cannot easily change. Frameworks that bundle unrelated breaking changes with every release. Components from before the original authors moved on. Code bases that keep growing while engineering capacity stays roughly fixed.

Teams that try to chase every CVE through an upgrade hit the same set of obstacles every quarter, accumulate exceptions for the cases they cannot fix, and watch the open-vulnerability inventory grow regardless.

This section explains why.

* [Why remediation is hard](/introduction/remediation-problem/why-remediation-is-hard): the upgrade cascade, transitive dependencies, hard-versus-trivial upgrades, the cases where there is no upgrade path, container patching, and EOL components.
* [The cost of chasing upgrades](/introduction/remediation-problem/the-cost-of-chasing-upgrades): off-cadence interruptions, the hard-upgrade tail, lost knowledge of legacy components, code bases that grow faster than developers can patch, and the deferred-exception pile that compliance ultimately has to face.

If you already know the problem and want the Seal answer, jump to [The Seal approach](/introduction/seal-approach).


# Why remediation is hard

The upgrade cascade, transitive dependencies, hard-versus-trivial upgrades, no-upgrade-path cases, container patching, and EOL components.

Remediating an open-source vulnerability almost always means upgrading the affected package to a newer version. That sounds simple. It is rarely simple.

## Direct versus transitive dependencies

Most CVEs in your security report are not in code your team chose. They are in code your team's code chose.

Direct dependencies are visible in your manifest (`package.json`, `requirements.txt`, `pom.xml`). You can upgrade them directly. **Transitive dependencies** are pulled in indirectly by your direct dependencies, often several levels deep. You cannot upgrade a transitive dependency on its own. You have to upgrade the direct dependency that pulls it in, or another package along the chain, to a version that pulls in a fixed copy.

When the direct dependency is a small, well-maintained package, this works. When the direct dependency is a large framework, things get expensive.

## The upgrade cascade

A small transitive dependency with a CVE in a code path your application does not even touch can force you to upgrade a much larger framework. The framework's new version comes with a list of unrelated breaking changes (new APIs, removed APIs, changed defaults), bumps for several of its own dependencies, and sometimes implicit version requirements on packages elsewhere in your build that did not formally depend on it.

A two-line CVE turns into a multi-week upgrade project: read the framework's changelog, update the manifest, fix call sites, chase down newly incompatible dependencies, run the test suite repeatedly, validate behavior in pre-production, coordinate the release. The vulnerability you set out to fix may have been a missing length check on a parser you never call.

## Trivial versus hard upgrades

Some upgrades are routine: a patch bump on a small package, no behavioral change, the build keeps working. A meaningful share of CVEs can be remediated this way without much engineering effort.

The remaining upgrades are the ones that consume the team's time. A major-version bump on a framework. A CVE in a transitive dependency that requires the upgrade cascade above. A patch that depends on a feature your runtime does not have. Any of these can take days to weeks of developer time, introduce regressions, break existing call sites, or take down a production environment after a release.

The trivial-versus-hard split is what makes "we'll just upgrade everything" not work as a strategy. The trivial cases are not the bottleneck. The hard cases are, and the team only has so many of them in flight at once.

## When there is no upgrade path

Some CVEs cannot be remediated by upgrading at all. The chain of dependencies that pulls in the vulnerable package may not have a version combination that resolves cleanly. A package somewhere in the chain may no longer be actively maintained, so there is no future version to pin against.

Major SCA scanners report this situation as **unfixable**. Sometimes "unfixable" really means "unfixable through upgrades". Other times it means "the upgrade exists but the cost of taking it (a major framework bump, or a rewrite of the dependent code) is more than the team can absorb." Either way, the result is the same: the vulnerability sits open, and the team writes an exception.

## Container patching

A vulnerability in an OS-level package or a language runtime inside a container image generally takes coordination across more than one team. Someone publishes a new base image with the patch, someone rebuilds the application's container against it, someone validates the new build. Each handoff costs calendar time, even when no one is dragging their feet.

## EOL components

Some vulnerable software has no fix coming. The Linux distribution is past its support window. The maintainer of the package archived the repository. The vendor of the runtime no longer ships security updates for the version you depend on.

Migrating off an EOL component is a multi-quarter project. Staying on it means the CVE list grows month over month with nothing your team can do about it.

[The Seal approach](/introduction/seal-approach) is built to address each of these cases without requiring an upgrade.


# The cost of chasing upgrades

Off-cadence interruptions, the hard-upgrade tail, lost knowledge, code base growth, and the deferred-exception pile.

Upgrading is the most labor-intensive way to remediate a vulnerability. It is slow, painstaking, and error-prone, and the people doing the work are developers, among the most expensive employees in any organization. The cost is not just the engineering hours spent on a given CVE. It is the way that work compounds across an inbound stream that does not slow down.

## Off-cadence interruptions

Vulnerabilities are not disclosed on your team's sprint calendar. They land when they land, often with an SLA attached: 7 days for critical, 30 days for high, however your compliance posture has it written. When an SLA clock starts, planned engineering work pauses while someone investigates the CVE, decides on a fix, and pushes it through.

Each of these is a context switch on a developer. The work that gets interrupted does not pick up where it left off; it absorbs the cost of being put down and picked back up. The interrupting work itself is rushed because of the SLA, which is exactly the situation in which mistakes get into production. And because the SLA does not look at exploitability, teams sometimes spend a developer for a day to fix a vulnerability with no realistic security impact, just to keep the dashboard green.

## The hard-upgrade tail

Some upgrades are trivial: a patch bump on a small package, no behavioral change, the build keeps working. The team can ship those without much fuss.

The remaining upgrades are the ones that consume the team's time. A hard upgrade can sit on a developer's desk for days or weeks: cascading dependency conflicts, broken call sites, regressions that only show up under load, behavioral changes in transitive packages that the original CVE was not even about. The team that wrote the upgrade typically does not own all the code that depends on it. Test coverage is rarely complete enough to catch every regression. Hard upgrades are the most common source of "small dependency bump took down production for an hour" stories in any sufficiently large engineering organization.

Forced upgrades to fix vulnerabilities sometimes ship more bugs into production than the original vulnerability ever did.

## Lost knowledge of older components

In a long-lived organization, the developer who originally wrote the code that depends on a vulnerable package may have moved on years ago. The team that owns the component today may not know how to build it locally, may not have a working test suite, and may not be sure whether the application even uses the vulnerable functionality.

Legacy components are the worst case: old packages, sparse documentation, brittle build processes, and the smallest number of people who understand them. They are the easiest things to break and the hardest to get working again. And often the team correctly judges that it does not make sense to invest weeks of developer time on an upgrade for a component scheduled for deprecation, so the CVE goes onto the exception list.

## Code growing faster than the team can patch

Engineering headcount on any given team is roughly fixed quarter over quarter. Code bases are not. Every quarter, the team ships new features that pull in new dependencies. Every quarter, more CVEs land on those dependencies. The code the team is responsible for does not just grow in size; it ages, and the people who originally wrote large parts of it move on. Maintenance gets harder over time, not easier.

AI-assisted development has accelerated this. Tools that generate code per-prompt have raised the rate at which application code (and the dependencies it pulls in) grows, sometimes dramatically. The work of remediating vulnerabilities in those dependencies has not been similarly accelerated; AI tooling that writes new code does not, today, take on the multi-week effort of chasing third-party CVEs through their upgrade graphs. The maintenance backlog grows; the headcount available to absorb it does not.

## The deferred-exception pile

Given the cost above, the unstated bargain teams strike is to defer most of the patching. Some vulnerabilities are tagged "unfixable" by scanners. Some are tagged that way by the team because the upgrade path is too painful, even when one technically exists. Some are accepted exceptions because the underlying component is deprecated and not worth investing in. Whatever the label, the result is the same: the open-vulnerability inventory in most large organizations is measured in hundreds or thousands.

The compliance side of this is not the audit paperwork. Auditors generally accept exception documentation at face value if it is filed correctly. What is much harder to explain to an auditor, a regulator, or a customer is a scanner report that shows hundreds of unresolved high and critical vulnerabilities sitting in your environment for months. Compliance frameworks that include a remediation-speed standard (DORA, PCI DSS 4.0, FedRAMP) make this worse, not better, when the only remediation tool available is "upgrade and hope".

[The Seal approach](/introduction/seal-approach) addresses this by removing the upgrade requirement entirely. A sealed package replaces the vulnerable version without changing any of the surrounding code, so the upgrade project does not need to happen.


# The Seal approach

Drop-in replacements, sealed packages, sealing approaches, and the trust posture that ships with every artifact.

If [the remediation problem](/introduction/remediation-problem) is "upgrades are expensive and frequently impossible", the Seal answer is to remove the upgrade requirement.

Seal builds **sealed packages**: drop-in replacements for the public versions you already use, with security fixes backported in. The version stays the same. The API stays the same. The dependencies stay the same. Only the vulnerable code changes.

The four pages below explain the model, the package, the delivery mechanics, and the trust posture.

* [Drop-in replacements, not upgrades](/introduction/seal-approach/drop-in-replacements): the mental model.
* [What a sealed package is](/introduction/seal-approach/sealed-packages): origin versions, backported fixes, the `-sp[N]` iteration, what is covered by default, and what an open vulnerability means.
* [How sealed packages are delivered](/introduction/seal-approach/sealing-approaches): build-time dependency sealing versus post-build artifact sealing, and when each applies.
* [Trust by default](/introduction/seal-approach/trust-by-default): code diff, attestations, and signing. Deeper material in [Trust, transparency & compliance](/trust/why-this-matters).


# Drop-in replacements, not upgrades

A sealed package replaces a vulnerable version without changing your code.

A sealed package is a **drop-in replacement** for the public version you already use. You replace the vulnerable version with the sealed version. Nothing else changes.

## What stays the same

A sealed package preserves everything an upgrade would put at risk:

* **The version number.** `ejs@2.7.4` becomes `ejs@2.7.4-sp1`. The major, minor, and patch numbers do not change. (The exact suffix format depends on the ecosystem; see [Naming and versioning conventions](/reference/naming-and-versioning).)
* **The public API.** The functions, types, and method signatures the package exposes are untouched. Code that calls into the package keeps compiling.
* **Behavior.** Default settings, return values, error cases, and side effects all match the origin version. Backwards compatibility is a guarantee.
* **The dependencies.** A sealed package depends on exactly the same packages, at exactly the same version ranges, as the origin version.

## What changes

Only the vulnerable code path. Seal applies the smallest patch that resolves the vulnerability while preserving backwards compatibility. Code that was not exploiting the vulnerability behaves exactly as it did in the origin version.

## A replacement, not an upgrade

The distinction is operational, not pedantic. An upgrade is an engineering project: read the changelog, fix call sites, run the test suite, coordinate the release. A replacement is a swap: the sealed version takes the slot the vulnerable version had, and the project that depended on it carries on.

If using a sealed package required the same engineering project that an upgrade does, it would not solve [the remediation problem](/introduction/remediation-problem). The reason a sealed package is useful is that the work an upgrade demands is exactly the work it does not need.


# What a sealed package is

How a sealed version is built, the sealed-version suffix, what is covered by default, and what an open vulnerability means.

A sealed package is a version of an open-source package that Seal has built from the public source code of a specific release, with security fixes backported into it.

## Built from the origin version

The starting point is the **origin version**: the public release the customer is currently using. Seal pulls the source for that release, applies a targeted patch for each vulnerability in scope, and rebuilds the package. The diff against the origin version is published; see the [code diff](/trust/code-diff) page.

Backporting means taking a fix from a newer release (or, when no upstream patch exists, writing one) and applying it to the older codebase, without bringing in the rest of the newer release. The sealed version is, in practice, a fork of one specific release with targeted security patches applied.

## The sealed-version suffix

A sealed version's identifier is the origin version with a sealed-version suffix. The exact form of the suffix depends on the ecosystem's versioning rules.

For npm, the first sealed build of `ejs@2.7.4` is `ejs@2.7.4-sp1`. If a new vulnerability is later disclosed and Seal ships a fix for it, the next sealed version is `ejs@2.7.4-sp2`, which contains every fix from `-sp1` plus the new one. Each iteration is cumulative.

Other ecosystems use different separators (`+sp1` for Maven and PyPi, for example) and Alpine uses a different scheme entirely. The full table is in [Naming and versioning conventions](/reference/naming-and-versioning).

## The safest version

The **safest version** for a given origin version is the most recent sealed version released for that origin. Each origin version has its own safest counterpart; cumulative fixes flow into the same line.

Seal calls this "safest" rather than "latest" because, in package-manager parlance, "latest" usually refers to the most recent upstream public release of the package, which is a completely different concept. The safest version of `ejs@2.7.4` is the most current sealed counterpart of `ejs@2.7.4`, not a newer upstream release of `ejs`.

## What is covered by default

Seal backports fixes for **critical** and **high** severity vulnerabilities by default. Coverage of medium and low severities is available on request through your Seal account team. Once a fix is built for any customer, it ships in the same sealed-version line and is available to every customer using that package.

A sealed package can carry **open vulnerabilities**: vulnerabilities that have not been remediated in the current sealed version. There are several reasons:

* The severity is below the default scope (medium or low) and no customer has requested a fix.
* The vulnerability was disclosed after the current sealed version shipped; the next iteration will address it.
* The vulnerability's severity, or even its validity as a vulnerability, is disputed.
* The vulnerability cannot be remediated without a behavioral change that would break compatibility. These cases are addressed by [private versions](/discovering/private-versions). A private version is not perfectly backwards compatible with the origin version, but the difference is usually small and often does not affect the customer's actual use of the package. Seal walks each customer through the change so they understand it, then selectively enables the private version for the Seal Projects where it applies.

The Protection page shows which vulnerabilities are sealed and which remain open in each sealed package.

## Related

* [Drop-in replacements, not upgrades](/introduction/seal-approach/drop-in-replacements): the mental model.
* [How sealed packages are delivered](/introduction/seal-approach/sealing-approaches): the technical model.
* [Naming and versioning conventions](/reference/naming-and-versioning): the full version-suffix grammar across ecosystems.


# How sealed packages are delivered

Build-time dependency sealing versus post-build artifact sealing, and when each applies.

Seal delivers a sealed package in one of two technical ways, called **sealing approaches**. Both involve Seal building from source. They differ in where the artifact lands in your workflow.

## Build-time dependency sealing

The customer's build picks up the sealed dependency at build time. The build proceeds normally: the dependency manifest resolves to a sealed version, the code compiles against it, and the artifact your team ships incorporates it.

This is the path for application-dependency ecosystems: npm, pip, Maven, Gradle, Go modules, Composer, Bundler, NuGet.

## Post-build artifact sealing

Seal produces a fully built artifact that replaces an existing one in a built environment. There is no rebuild on the customer side. The sealed artifact takes the slot the vulnerable artifact had; nothing else changes in the surrounding image or filesystem.

This is the approach when a rebuild is not available or not practical. The most common cases are pre-built JARs and Python wheels inside containers, where the source for the build is not at hand or the build itself happened far upstream of the deployment.

## Which one applies

Seal Apps uses build-time dependency sealing.

Seal Vendor Apps and Seal My Container use post-build artifact sealing for pre-built artifacts inside container images (typically JARs and Python wheels).

## Related

* [The Seal product family](/introduction/product-family): which products use which approach.
* [Working with Seal Apps](/using-platform/working-with-seal-apps): the day-2 view of build-time dependency sealing in the application context.


# Trust by default

Code diff, attestations, and signing. A short overview.

Every artifact Seal ships is accompanied by mechanisms that let you, your auditors, and your customers verify what was changed, who built it, and whether it has been tampered with. The full set of mechanisms is covered under [Trust, transparency & compliance](/trust/why-this-matters). A short overview here.

## Code diff

For every sealed version, Seal publishes the diff against the origin version. The change is a targeted patch that fixes the vulnerability. You can read the change, in source, before you accept the sealed package. See the [code diff](/trust/code-diff) page.

## Attestations

Each sealed artifact ships with an attestation listing exactly which vulnerabilities have been remediated. Two formats are produced for every artifact: a **PDF attestation** for human review, and a **VEX record** for machine consumption (Trivy, Wiz, and other scanners). Per-package and bulk download are both supported. See [Attestations](/trust/attestations).

## Cryptographic signing

Every sealed artifact is cryptographically signed before publication. The Seal CLI validates signatures automatically before installing a sealed package. Hashes are published for independent verification. See [Cryptographic signing and hash verification](/trust/signing).

## Patch validation prompt

For each sealed patch, Seal generates a prompt you can paste into an LLM to independently validate that the patch is minimal, scope-correct, and free of unrelated changes. This complements the static code diff and the signed attestations: the diff lets you read what changed, the attestation signs the claim, and the validation prompt lets you re-derive the assessment yourself.


# The Seal product family

Five products covering your stack, all built on the same sealing approach.

<figure><img src="/files/rwpjGZ5LliXIKnzSEOwN" alt="The five Seal products radiating from the Seal Platform: Seal Apps, Seal OS, Seal My Container, Seal Base Images, and Seal Vendor Apps"><figcaption><p>The five Seal products.</p></figcaption></figure>

Seal has five products that together cover your stack. They all use the same underlying [sealing approach](/introduction/seal-approach): a sealed package replaces a vulnerable origin version without changing your code. They differ in **what** they secure and in **how** the fix reaches your environment.

| Product                                                                 | What it secures                                                                                               | Delivery                                                                               |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [**Seal Apps**](/introduction/product-family/seal-apps)                 | Application open-source dependencies (npm, pip, Maven, Gradle, ...)                                           | Sealed dependencies pulled in during your CI/CD build, or via the Seal Artifact Server |
| [**Seal OS**](/introduction/product-family/seal-os)                     | OS-level packages and language runtimes on Linux servers and in containers, including EOL distributions       | Sealed packages installed by the Seal CLI, in place                                    |
| [**Seal Base Images**](/introduction/product-family/seal-base-images)   | OS-level packages and language runtimes inside container base images                                          | Clean base image, pulled from a Seal-hosted registry                                   |
| [**Seal My Container**](/introduction/product-family/seal-my-container) | OS-level packages, language runtimes, and embedded open-source artifacts inside your private container images | Sealed copy of your container image, pushed back to your registry                      |
| [**Seal Vendor Apps**](/introduction/product-family/seal-vendor-apps)   | OS-level packages, language runtimes, and embedded open-source artifacts inside vendor-supplied containers    | Seal CLI applies fixes in place inside the vendor's container in your environment      |

The pages below cover each product in turn. For day-1 setup, see [Application and OS setup](/setup-apps-os/choosing-deployment-method) or [Container and image setup](/setup-containers). For the day-to-day operating view, see [Using the Seal Platform](/using-platform/working-with-the-platform).


# Seal Apps

Sealed packages for your application's third-party open-source dependencies.

**Seal Apps** remediates vulnerabilities in your application's third-party open-source dependencies. The packages your code pulls in directly, and the packages those packages pull in transitively, are replaced with sealed versions of the same origin versions.

<figure><img src="/files/U9HS5hhThLYVrtpPoOTq" alt="Some of the language ecosystems Seal Apps covers: JavaScript, Python, Java, Go, Ruby"><figcaption></figcaption></figure>

## What it covers

Application-dependency ecosystems:

* **JavaScript:** npm, Yarn, pnpm
* **Python:** pip, Poetry
* **Java:** Maven, Gradle
* **Go:** Go modules
* **PHP:** Composer
* **Ruby:** Bundler
* **.NET:** NuGet

Seal Apps does not cover language runtimes themselves (the Node.js binary, the Python interpreter, the JVM, the .NET CLR). Those are handled by [Seal OS](/introduction/product-family/seal-os) when installed via OS package managers, or by [Seal Base Images](/introduction/product-family/seal-base-images), [Seal My Container](/introduction/product-family/seal-my-container), or [Seal Vendor Apps](/introduction/product-family/seal-vendor-apps) when bundled in container images.

## How it is delivered

Seal Apps uses [build-time dependency sealing](/introduction/seal-approach/sealing-approaches). It supports several deployment methods:

* The **Seal CLI in your CI/CD pipeline** (recommended). The CLI ensures that sealed versions are used in place of vulnerable origin versions; your build proceeds as before, and the artifact you ship incorporates the sealed dependencies.
* The **Seal Artifact Server** as a configured remote (or as an additional remote) in your package manager.
* **Manual download** of sealed versions directly from the Repository page.

## Related

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): day-1 setup options for Seal Apps.
* [Working with Seal Apps](/using-platform/working-with-seal-apps): the day-to-day workflow.


# Seal OS

Sealed APK, DEB, and RPM packages for Linux servers and containers, including EOL distributions.

**Seal OS** remediates vulnerabilities in OS-level packages and language runtimes (Node.js, Python, JVM, and others) on your Linux servers and inside your containers. It covers the system layer that sits below your application code.

<figure><img src="/files/YfwNefcdPKZEEuj2ARzj" alt="Seal OS covers Alpine, Debian, Ubuntu, CentOS, Red Hat, RHEL, Fedora, and Amazon Linux"><figcaption><p>Seal OS covers the major Linux distributions and their package families.</p></figcaption></figure>

## What it covers

OS package ecosystems:

* **APK** (Alpine)
* **DEB** (Debian, Ubuntu)
* **RPM** (Red Hat, CentOS, RHEL, Fedora, Amazon Linux)

Open-source language runtimes installed via the OS package manager are also covered, including Node.js, Python, and the JVM.

Seal OS supports **EOL distributions**. When the upstream distribution maintainer has stopped releasing security updates, Seal continues to ship sealed package versions for the affected components.

## How it is delivered

Seal OS applies fixes via the Seal CLI, in place. The CLI runs on your Linux servers, inside your container builds, or in standalone environments, and installs sealed versions of the affected packages where they live.

## Related

* [Setting up Seal OS](/setup-apps-os/seal-os-cicd): day-1 setup.
* [Working with Seal OS](/using-platform/working-with-seal-os): the day-to-day workflow.


# Seal Base Images

Sealed replacements for the public container base images you build on top of.

**Seal Base Images** are sealed versions of the public container base images your team builds on top of: language runtime images, server images, database images, and the OS-distribution images they tend to be derived from. You pull a Seal base image instead of the public one, and your application is built on top of it. The vulnerabilities in the underlying packages are already remediated when you pull.

## What it covers

Public base images that ship without licensing restrictions on redistribution. Anything you would normally pull from a public registry like Docker Hub falls into this category if the upstream allows redistribution: language runtimes, web servers, databases, and the OS images they sit on top of.

For containers where the vendor's licensing prevents Seal from distributing a sealed copy of the image, the equivalent role is filled by [Seal Vendor Apps](/introduction/product-family/seal-vendor-apps), which seals the open-source content of vendor containers in place rather than redistributing them.

## How it is delivered

A Seal base image is published as a regular container image to a Seal-hosted registry. Your `Dockerfile` or build pipeline pulls from that registry. You can also mirror Seal base images into your internal registry.

## Related

* [Setting up Seal Base Images](/setup-containers/seal-base-images): day-1 setup.
* [Working with Seal Base Images](/using-platform/working-with-seal-base-images): the day-to-day workflow.


# Seal My Container

Container-to-container sealing of your private container images.

**Seal My Container** produces a sealed copy of your existing private container images. You feed Seal an image; Seal returns a sealed image that you push to your own registry. Vulnerable open-source packages, runtimes, and embedded artifacts inside the image are replaced with sealed versions; your own first-party application code is not touched.

## What it covers

Inside the input container image:

* OS-level packages, across the same Linux distributions as [Seal OS](/introduction/product-family/seal-os): APK (Alpine), DEB (Debian, Ubuntu), and RPM (RHEL, and others).
* Language runtimes installed in the image.
* Open-source dependencies bundled as standalone artifacts (typically JAR files and Python wheels).

Seal My Container does not modify your own first-party application code.

## How it is delivered

Seal My Container runs as a Seal CLI command, typically from a centralized re-seal pipeline that processes a list of your container images. The output is a new container image you push to your registry under a name you choose. This pattern, container-to-container sealing, makes "fix the open-source software in every image we build" a single pipeline step instead of a per-image project.

For pre-built open-source artifacts inside the image (JARs, Python wheels), Seal My Container uses [post-build artifact sealing](/introduction/seal-approach/sealing-approaches).

## Related

* [Setting up Seal My Container](/setup-containers/seal-my-container): day-1 setup.
* [Working with Seal My Container](/using-platform/working-with-seal-my-container): the day-to-day workflow.


# Seal Vendor Apps

Open-source remediation inside containers shipped by your vendors.

**Seal Vendor Apps** remediates vulnerabilities in vendor-supplied container images you run, such as a Kafka image, a database image, or any third-party application that ships as a container.

## What it covers

Inside the vendor's container image:

* OS-level packages.
* Language runtimes.
* Open-source dependencies bundled as standalone artifacts (typically JAR files and Python wheels).

Seal Vendor Apps does not modify the vendor's own application code.

## How it is delivered

Seal Vendor Apps runs in place inside the vendor's container in your environment, similar to [Seal OS](/introduction/product-family/seal-os). The Seal CLI applies fixes to the open-source packages, runtime, and embedded artifacts where they live in the image; the vendor's code is untouched.

## Related

* [Setting up Seal Vendor Apps](/setup-containers/seal-vendor-apps): day-1 setup.
* [Working with Seal Vendor Apps](/using-platform/working-with-seal-vendor-apps): the day-to-day workflow.


# Architecture overview

The Seal components, how they fit together, and where your data lives.

The Seal Platform is composed of a small number of named components, accessed through several customer-facing interfaces (the CLI, the UI, the GitHub App, Slack, the Public API). This chapter covers what those components are, how they connect, and what data flows through them.

* [Components](/introduction/architecture/components): the named components.
* [How the pieces fit together](/introduction/architecture/how-pieces-fit-together): a single diagram of the most common data flows.
* [Where your data lives](/introduction/architecture/where-your-data-lives): what Seal sees in each package discovery mode and what it never sees.


# Components

The named components that make up the Seal Platform.

## Seal Platform

The backend that holds your tenant's state: discovered packages, vulnerabilities, Sealing Rules, Seal Projects, users, tokens, and the operational data that the UI and the CLI both work against.

## Seal Artifact Server

The package registry that hosts every sealed package Seal has built. The Seal CLI fetches sealed packages from it, and customers can also configure their package managers to point at it directly.

## Seal UI

The web application for viewing discovered packages, creating Sealing Rules, managing Seal Projects, configuring tenant settings, and operating the AI features.

## Seal CLI

The command-line tool customers run to apply sealed packages or report on what is discovered. The recommended deployment is the CLI in your CI/CD pipeline; it also runs on developer laptops or anywhere with network access to the Seal Platform.

## Seal Public API

The programmable REST API for integrating Seal with external tooling.

## Seal GitHub App

The GitHub-hosted application that connects a customer's GitHub repositories to Seal. It reads dependency manifests, opens automatic pull requests for fixes, and reports findings back to the Seal Platform.

## Seal GitHub Action

A wrapper around the Seal CLI that runs as a GitHub Actions step. Functionally equivalent to running the CLI directly; convenient for customers whose CI/CD is GitHub Actions.


# How the pieces fit together

One diagram of how the Seal components connect.

```mermaid
graph LR
    CI[Your CI/CD] --> CLI[Seal CLI]
    CLI --> AS[Seal Artifact Server]
    CLI <--> Plat[Seal Platform]
    CLI --> Scanner[Your SCA scanner]
    Browser[Your browser] --> UI[Seal UI]
    UI <--> Plat
    SCM[Source control] <--> Plat
    Slack[Your Slack] <--> Plat
    Clients[External clients] --> API[Seal Public API]
    API <--> Plat
```

The Seal Platform is the hub. Every other component either communicates with the platform or carries data toward it.

The Seal CLI runs in your CI/CD pipeline or on a developer laptop. It pulls sealed packages from the Seal Artifact Server when applying fixes, reports discovered packages and fix results back to the platform, and (when configured) calls the APIs of your internal SCA scanners (Snyk, Black Duck, GitHub Advanced Security, Ox Security) to inform them which vulnerabilities have been remediated in which packages, so the scanners' dashboards stay accurate.

Your browser loads the Seal UI, which is a single-page application that talks to the platform.

The Seal GitHub App lives in GitHub. It reads your dependency manifests there, reports findings to the platform, and opens automatic pull requests when configured. GitLab and Azure DevOps integrations exist; they read manifests through the source control system's own API rather than via a hosted app, and they do not open pull requests.

The Seal AI Agent and the Seal Engineer are two Seal Platform features. The Seal AI Agent is the chatbot in the Seal UI: you talk to it. The Seal Engineer runs flows on a schedule and posts results back to a Slack channel; the Slack workspace install lives inside the Seal Engineer configuration. You schedule the Seal Engineer. The Seal AI Agent does not connect to Slack.

External tooling integrates programmatically through the Seal Public API.


# Where your data lives

What Seal sees in each package discovery mode, and what it never sees.

Seal stores the operational state of your tenant on the Seal Platform: the packages it has discovered, the vulnerabilities associated with them, the Sealing Rules you have created, your Seal Projects' configuration, your tenant's users and tokens. This is the data the UI displays, the CLI works against, and the API exposes.

What Seal sees varies with the [package discovery mode](/discovering/package-discovery-mode) of each Seal Project.

## Source code mode

Seal connects to your source control (GitHub, GitLab, or Azure DevOps), reads dependency manifests directly, and uses the resolved dependency graph to record the packages discovered for that Seal Project. Seal does not retain your source code; it parses manifests for the package list and stores that.

For GitHub, the Seal GitHub App may also open automatic pull requests against your repositories when configured. Those PRs are written into your repository like any other PR.

## CLI mode

Seal sees only what the Seal CLI reports during a CI/CD run. The CLI inspects your build's dependency tree, sends the package list to the platform, and applies sealing actions. **The platform does not receive your source code; it receives only the package list and fix-result telemetry the CLI reports.**

This is the path most often chosen by source-restricted organizations. Seal can fully operate without read access to your source code.

## Artifact server mode

Seal sees only the sealed packages your build pulls from the Seal Artifact Server. There is no upfront record of what is in your project; the platform's view fills in over time as your CI/CD pulls artifacts.

## Imported manifest mode

You upload a manifest file or SBOM once; Seal parses it and records the discovered packages. There is no ongoing connection between Seal and the source of the manifest; the result is a snapshot at the time of upload.

## What Seal never sees

In any package discovery mode, Seal does not see:

* Your application's source code (other than what is required to parse manifests in source code mode).
* Your customer data or production traffic.
* Your secrets, credentials, or environment variables.
* Anything outside the dependency graph.

The only data Seal retains about your environment is the discovered-package list and what you create in the platform (Sealing Rules, Scanner Exclusions, and so on).


# Your first hour with Seal, by role

Role-based starting points. Pick the page that matches what you do.

These docs cover a lot of ground; what's relevant to you depends on what you do day-to-day. Pick the page below that matches your role; each one points at the chapters you'll spend the most time on and skips the rest.

* [If you're a security leader](/introduction/audience-guides/security-leader): evaluating Seal, reviewing the Dashboard, producing executive reports.
* [If you're a DevOps engineer](/introduction/audience-guides/devops-engineer): deployment, integrations, the container-side products.
* [If you're a developer](/introduction/audience-guides/developer): the CLI, Sealing Rules, Protection page triage for the Seal Projects you own.
* [If you're a security analyst](/introduction/audience-guides/security-analyst): day-to-day triage, notifications, reports.


# If you're a security leader

How to navigate the Seal docs as a security leader.

This guide is for security leaders evaluating Seal or operating it at the executive level: heads of AppSec, CISOs, and the directors who answer to them. Your concerns are the vulnerability posture across your organization, the risk picture you present to executive stakeholders, and the audit-readiness story you present to compliance.

## Where to start

* [The remediation problem](/introduction/remediation-problem): the case for sealed packages over upgrades, in language that doesn't assume you're a developer.
* [The Seal approach](/introduction/seal-approach): how sealed packages work and why they don't break your build.
* [The Dashboard](/discovering/dashboard): the screen you'll come back to most. Aggregate counts of discovered packages, sealed packages, and trend information.
* [Reports Manager](/using-platform/reports-manager): how to produce executive briefings, including the ROI report.
* [Trust, transparency & compliance](/trust/why-this-matters): the artifacts and certifications that back Seal's claims (code diff, attestations, signing, SOC 2, ISO 27001, framework support).

<figure><img src="/files/JidOD4wpKmky3T4NBojd" alt="The Seal Dashboard showing aggregate metrics"><figcaption><p>The Dashboard, the screen security leaders revisit most often.</p></figcaption></figure>


# If you're a DevOps engineer

How to navigate the Seal docs as a DevOps, DevSecOps, or platform engineer.

This guide is for DevOps engineers, DevSecOps engineers, and platform engineers operating Seal in your organization. You will own the deployment, the integrations between Seal and the rest of your stack, and the day-2 of the container-side products and Seal OS.

## Where to start

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): pick the right path for your environment.
* [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd): the recommended deployment, step by step.
* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): how Seal sees what you have, with or without source-control access.
* [Working with Seal Base Images](/using-platform/working-with-seal-base-images), [Seal My Container](/using-platform/working-with-seal-my-container), and [Seal Vendor Apps](/using-platform/working-with-seal-vendor-apps): day-2 for the container side.
* [Internal SCA scanners](/integrations/internal-scanners): connecting Seal to Snyk, Black Duck, GitHub Advanced Security, or Ox Security.
* [The Seal GitHub App](/integrations/github/github-app): more visibility into your codebase, with the option to open automatic pull requests for fixes.

<figure><img src="/files/UjOT4YFY2MigfJ8k4468" alt="The Projects page showing several Seal Projects"><figcaption><p>The Projects page, where DevOps engineers manage Seal Projects across the tenant.</p></figcaption></figure>


# If you're a developer

How to navigate the Seal docs as a developer.

This guide is for developers who interact with Seal as part of their day job: integrating the Seal CLI into a CI/CD pipeline, creating or applying Sealing Rules for the codebases you own, and reading Seal's output in your build logs.

## Where to start

* [Your first Proof of Value](/getting-started/proof-of-value): an end-to-end walkthrough you can run in an afternoon.
* [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd): the integration step by step.
* [Sealing Rules](/using-platform/sealing-rules): the model and the UI flow. Sealing Rules are used in CLI deployments; they do not apply to artifact-server or manual-download deployments.
* [The Protection page](/discovering/protection-page): where you check on what is pending action for the Seal Projects you own.
* [The CLI reference](/reference/cli): commands, flags, and the `.seal-actions.yml` schema.

<figure><img src="/files/sCnfxJ7yywepgkkp0Q6f" alt="Seal CLI scan and fix output in a terminal"><figcaption><p>The Seal CLI output developers see in CI logs.</p></figcaption></figure>


# If you're a security analyst

How to navigate the Seal docs as a security analyst.

This guide is for the analyst-level work of operating Seal day-to-day: triaging the vulnerabilities Seal discovers, creating Sealing Rules for the ones that need fixing, monitoring notifications, and producing reports for leadership.

## Where to start

* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): what Seal sees and how that picture is built.
* [The Protection page](/discovering/protection-page) and [Package states](/discovering/package-states): the triage view and what each state means.
* [Sealing Rules](/using-platform/sealing-rules): how to create the rules that drive the Seal CLI to apply fixes.
* [Notification Center](/using-platform/notification-center): configuring which events are delivered and where, including personal email notifications.
* [Reports Manager](/using-platform/reports-manager): building reports for leadership.
* [Seal AI Agent](/using-platform/seal-ai-agent): the chatbot in the Seal UI, useful for answering "what's our exposure to X?" without leaving the conversation.

<figure><img src="/files/G8yqdVsyU3dU2GfKXJtg" alt="The Protection page Vulnerable packages tab showing a mix of package states"><figcaption><p>The Vulnerable packages tab on the Protection page, the analyst's primary triage view.</p></figcaption></figure>


# Glossary

The Seal-specific vocabulary used throughout these docs.

Seal-specific terms used throughout these docs, alphabetized. Standard industry terms (CI/CD, SBOM, SSO, and so on) are not redefined here unless Seal uses them in a particular way.

### Artifact

A specific file downloaded from an artifact server. Examples: `ejs-2.7.4.tgz` (an npm artifact), `junit-4.13.jar` (a Maven artifact), `requests-2.31.0-py3-none-any.whl` (a Python wheel).

### Attestation

A signed document Seal publishes alongside each sealed artifact, listing exactly which vulnerabilities have been remediated. Two formats are produced for every artifact: a human-readable PDF, and a machine-readable Vulnerability Exploitability eXchange (VEX) record.

### Build-time dependency sealing

A sealing approach in which the customer's build picks up a sealed dependency at build time and uses it in producing the customer's own artifact. The path for application-dependency ecosystems like npm, pip, Maven, Gradle, Go modules, Composer, Bundler, and NuGet.

### CLI fix mode

The mode the Seal CLI runs in. Three values: **local** (rules from a `.seal-actions.yml` file in your source), **remote** (rules from the Seal Platform UI), **all** (every vulnerable package replaced automatically).

### Code diff

The diff between a sealed version and its origin version. Seal publishes the code diff for every sealed package; you can view it on the Protection page or the Repository page.

### CVE

Common Vulnerabilities and Exposures identifier (for example, `CVE-2023-45857`). Seal uses CVEs as the primary vulnerability reference. When a CVE is not assigned to a vulnerability, Seal falls back, in order of preference, to a GHSA (GitHub advisory ID), a Snyk ID, or another source's identifier (such as a Sonatype ID).

### Default project

The built-in catch-all Seal Project that exists in every tenant. Collects package-detection results that cannot be attributed to a specific Seal Project, such as unattributed SBOM uploads. Treated as a view rather than a real Seal Project: it should not be connected to source control or used as a CLI target.

### Deployment method

How Seal is integrated into your environment. Five named methods: **Automatic Remediation**, **Remote**, **Local**, **Artifact Server**, **Manual**.

### Dev dependency

A dependency the package manager has marked as used only for testing or building, not for shipping to production. Seal can identify a dev dependency when the ecosystem's package manager exposes the marking natively (for example, the `devDependencies` block in `package.json` for npm or Yarn) AND Seal can see the relevant manifest file — which happens either through a source-control connection or, equivalently, when the Seal CLI runs in your CI pipeline and reports the manifest it scanned. Anything not explicitly marked is assumed to reach production. Distinct from a [development token](#development-token), which is a tenant-level credential.

### Development token

A Seal token issued for use on developer machines and other untrusted contexts. Activity authenticated with a development token is filtered out of the Protection page by default, so day-to-day developer experimentation does not pollute production posture metrics. Contrast with a [production token](#production-token). Distinct from a [dev dependency](#dev-dependency).

### Discovered package

A package Seal has seen in your environment, regardless of which package discovery mode produced the signal.

### Ecosystem

A language environment or OS package format that Seal works with. Examples: Java, Python, npm, APK, RPM.

### Last seen

The Seal UI timestamp showing when Seal most recently saw a given package. Accurate across all four package discovery modes.

### Open vulnerability

A vulnerability that has not yet been remediated by Seal in the current sealed version. May be open for several reasons: outside Seal's default scope (medium or low severity), disclosed after the current sealed version shipped, severity disputed, or unable to be remediated without breaking compatibility (in which case a [private version](#private-version) may be available).

### Operating system / OS

The OS layer of the customer's environment, typically a Linux distribution. The abbreviation "OS" in Seal's docs always means operating system, never open source.

### Origin version

The community's upstream version of a package: the public release before Seal builds a sealed counterpart from it. For example, `ejs@2.7.4` is the origin version that Seal builds `ejs@2.7.4-sp1` from.

### Package

A unit of open-source software, distributed through a package manager. Examples: `ejs` (an npm package), `commons-text` (a Maven package), `requests` (a Python package).

### Package discovery mode

The per-Seal-Project setting that determines how Seal sees the customer's packages. Four values: **source code**, **CLI**, **artifact server**, **imported manifest**.

### Package manager

A specific tool within an ecosystem. Examples: Maven and Gradle within Java; npm, Yarn, and pnpm within JavaScript.

### Package state

The lifecycle position of a package on the Vulnerable packages tab. Six values: **Sealed**, **Pending deploy**, **Ready to seal**, **Version in progress**, **Generate available**, **Unfixable**.

### Package version

A specific version of a package, expressed in the ecosystem's version format. Example: `ejs@2.7.4`.

### Post-build artifact sealing

A sealing approach in which Seal produces a fully built artifact (typically a JAR or Python wheel) that the customer drops into a built environment, replacing an existing artifact in place. Used when a rebuild is not available or not practical, most commonly inside container images.

### Private version

A sealed version that is not perfectly backwards compatible with the origin version. Seal enables a private version for a specific Seal Project after the customer has requested it and acknowledged the compatibility change.

### Production token

A Seal token issued for use in production-equivalent environments: CI/CD pipelines, build infrastructure, and any other context where the resulting activity should count toward your security posture. Activity authenticated with a production token is fully tracked on the Protection page. Contrast with a [development token](#development-token).

### Project ID

A Seal Project's machine-readable identifier. Immutable after creation, restricted to letters, numbers, dots, hyphens, and underscores. The Seal CLI and the Seal Public API both work against the Project ID; the `SEAL_PROJECT` environment variable holds it. Distinct from the project's display name, which is mutable and used in the UI.

### Reports Manager

The Seal UI page for creating custom reports. Three report types in scope today: Vulnerable Packages, Sealed Packages, and ROI.

### Safest version

The most recent sealed version released for a given origin version. Each origin version has its own safest counterpart; cumulative fixes flow into the same line. Distinct from "latest", which usually refers to the most recent upstream public release of the package.

### Embedded package

A package shipped inside another package's distributed artifact. The canonical case Seal handles is the Java shaded JAR. Embedded packages do not appear as their own rows on the Protection page; they are listed in the package drawer when you open the parent package's row. Sealing the parent package transitively resolves the embedded package's vulnerabilities, so no separate Sealing Rule is needed for the embedded package itself.

### Flow

A Seal Engineer task definition: a named entry with a template, persona / tone, schedule, and Slack channel. The Seal Engineer runs flows; each execution is a flow run.

### Seal AI Agent

A Seal Platform feature: the chatbot inside the Seal UI. Used to query your security posture, create Sealing Rules through conversation, and get help integrating the Seal CLI into your CI/CD. Distinct from the [Seal Engineer](#seal-engineer): you talk to the Seal AI Agent; you schedule the Seal Engineer.

### Seal Apps

The Seal product that remediates vulnerabilities in your application's third-party open-source dependencies.

### Seal Artifact Server

The package registry that hosts every sealed package Seal has built. The Seal CLI fetches sealed packages from it; customers can also configure their package managers to point at it directly.

### Seal Base Images

The Seal product that provides sealed versions of public container base images, derived from the upstream images you would normally pull.

### Seal CLI

The command-line tool customers run to apply sealed packages or to report on what is discovered.

### Seal Engineer

A Seal Platform feature: the schedulable automated-workflow runtime. Runs [flows](#flow) that behave like a security engineer on the team — scheduled queries, drafted remediations, results posted back to a Slack channel. Distinct from the [Seal AI Agent](#seal-ai-agent): you talk to the Seal AI Agent; you schedule the Seal Engineer.

### Seal GitHub App

The GitHub-hosted application that connects a customer's GitHub repositories to Seal. Reads dependency manifests, opens automatic pull requests for fixes, and reports findings to the Seal Platform.

### Seal My Container

The Seal product that produces sealed copies of customer private container images. Also known as container-to-container sealing.

### Seal OS

The Seal product that remediates vulnerabilities in OS-level packages and language runtimes on Linux servers and inside containers, including EOL distributions.

### Seal Platform

The Seal backend that holds your tenant's state: discovered packages, vulnerabilities, Sealing Rules, Seal Projects, users, tokens, and the operational data the UI and the CLI both work against.

### Seal Project

The entity inside the Seal Platform that represents one of your codebases or build pipelines. Distinct from the customer's source repository, which is referred to as "your repository" or "your codebase". Has two distinct identifiers: a [Project ID](#project-id) (machine-readable, fixed) and a human-readable name (mutable).

### Seal Public API

The programmable REST API for integrating Seal with external tooling.

### Seal UI

The Seal web application: viewing discovered packages, creating Sealing Rules, managing Seal Projects, configuring tenant settings, operating the AI features.

### Seal Vendor Apps

The Seal product that remediates open-source vulnerabilities inside containers shipped by your vendors, by running in place inside the vendor's container in your environment.

### Sealed package

A package Seal has built from a public origin version, with security fixes backported in. A drop-in replacement for the origin version, with no breaking changes.

### Sealed version

The released sealed counterpart of a specific origin version, identified by the origin version plus a sealed-version suffix.

### Sealed vulnerability

A vulnerability that has been remediated by Seal in the current sealed version of a package.

### Sealed-version suffix

The marker on a sealed version's identifier that distinguishes it from the origin version. The exact form depends on the ecosystem: `-sp1` for npm and Go, `+sp1` for Maven and PyPi, and others for Ruby and Alpine. The full table is in [Naming and versioning conventions](/reference/naming-and-versioning).

### Sealing approach

The technical mechanism by which a sealed package reaches the customer. Two approaches: [build-time dependency sealing](#build-time-dependency-sealing) and [post-build artifact sealing](#post-build-artifact-sealing).

### Sealing Rule

An instruction telling Seal which package to replace and with which sealed version. A Sealing Rule can be saved on the Seal Platform through the UI (a **remote Sealing Rule**) or in a `.seal-actions.yml` file in your source code (a **local Sealing Rule**). Applied by the Seal CLI when it runs.

### Severity

The severity rating of a vulnerability. Four categories: **critical**, **high**, **medium**, **low**. Vulnerabilities without a CVSS score are treated as low; malicious packages are always critical. Seal's default scope fixes high and critical vulnerabilities only; medium and low severity coverage is available on request.

### Tenant

The customer's top-level entity in the Seal Platform. Quotas (package usage, AI tokens) are tenant-wide.

### Usage page

The Seal UI page tracking tenant-wide consumption: package usage and AI token usage, against the contractual monthly quota.

### VEX record

Vulnerability Exploitability eXchange record. A machine-readable format documenting which vulnerabilities apply (or do not apply) to specific software. Seal produces a VEX record alongside every sealed artifact; scanners that consume the Seal feed (Trivy, Wiz, and others) use VEX records to update their assessment of your environment.


# Getting started

Sign in, set up users and tokens, create your first Seal Project, and run a Proof of Value.

The day-1 essentials before any deeper configuration. Everything in this section is a one-time setup: you sign in, you set up the people and tokens that will use Seal, you create the Seal Projects that represent your codebases, and you run a Proof of Value against a real component to confirm the mechanics.

## What's in this section

* [Sign up and sign in](/getting-started/sign-up-and-sign-in): account creation, multi-tenant sign-in, and SAML auto-provisioning.
* [The onboarding wizard](/getting-started/onboarding-wizard): the three-stage wizard that walks a new tenant through CLI access, source-control connection, and first project import.
* [Managing users, roles & SSO](/getting-started/users-and-sso): the four user roles, invite flow, and SAML single sign-on.
* [Managing tokens](/getting-started/tokens): production and development tokens, generation and revocation, security best practices.
* [Creating a Seal Project](/getting-started/creating-a-seal-project): how Seal Projects are created, named, and mapped to your environment.
* [Your first Proof of Value](/getting-started/proof-of-value): a structured 2-3 week evaluation against a representative component.


# Sign up and sign in

Activating your invite, signing in, and switching tenants.

Access to the Seal Platform is invite-only. Your first sign-in starts from an email invite; once activated, you sign in like any other web application.

## Activating your invite

The first user of a new tenant receives an invite email directly from Seal Security. After that, tenant admins invite additional users from inside the platform.

1. Open the invite email and click the activation link. Invite links expire after **seven days**.
2. Choose how you want to authenticate. The hosted login page offers a password and the social-login providers Seal supports: **Google**, **GitHub**, **Microsoft**, and **Facebook**.
3. If you set a password, follow the strength rules shown on the page.
4. You land in the Seal UI, scoped to the tenant the invite was issued for.

If your organization is configured for SAML single sign-on, you may not need an explicit invite at all. See [Single sign-on and auto-provisioning](#single-sign-on-and-auto-provisioning) below.

## Single sign-on and auto-provisioning

If your organization has SAML single sign-on configured for its Seal tenant:

* New users do not need a separate email invite. The first time they sign in through your identity provider (IdP), Seal auto-provisions their account in your tenant.
* Subsequent sign-ins go through your IdP as usual.

## Signing in

For subsequent sign-ins:

1. Go to <https://app.sealsecurity.io/>.
2. Click **Log in** at the top right.
3. Enter your credentials (password or social login).
4. You land in the tenant you most recently visited.

<figure><img src="/files/mhcvLqHsZzgWK16qmxkI" alt="The Seal hosted login page with email/password and four social-login buttons"><figcaption><p>The Seal hosted login page</p></figcaption></figure>

## Switching between tenants

A single Seal account can be associated with more than one tenant, though in practice most users belong to one. After signing in:

1. Click your user-profile icon at the top right of the Seal UI.
2. Select **Switch tenant**.
3. Choose the tenant you want from the picker.

## Forgotten password

The login page does not currently include a self-serve password reset. Contact a tenant admin to have your password reset.

## Related

* [Managing users, roles & SSO](/getting-started/users-and-sso): inviting users from inside the platform, configuring SAML, and the user role model.
* [Managing tokens](/getting-started/tokens): production and development tokens for the Seal CLI and the Public API.


# The onboarding wizard

A guided three-stage setup that runs the first time anyone signs in to a new tenant.

The onboarding wizard runs automatically the first time anyone signs in to a brand-new tenant. It walks the first user through generating an access token for the Seal CLI, optionally connecting Seal to GitHub, and importing the tenant's first projects so Seal has something to scan.

Some tenants are configured by Seal to skip the wizard. In that case the first user lands directly on the Protection page, where the equivalent setup options are offered as [Welcome cards](#the-welcome-cards-on-the-protection-page).

The wizard runs once per tenant. After it completes or is skipped, subsequent users land on the Dashboard.

You can skip any step in the wizard with a **Maybe later** button.

## 1. Set up your CLI access

The first stage generates a **production access token** that the Seal CLI uses to authenticate against the Seal Artifact Server.

1. Click **Generate token**. The token appears in a read-only field with a copy-to-clipboard icon.
2. Copy the token and save it somewhere secure: a secret manager or your CI/CD's secret store. The token only allows pulling sealed packages from the Seal Artifact Server; it does not let anyone perform operations on the platform on your behalf. Treat it like any other credential.
3. The token is shown only at generation time. If you lose it, you can create a new one from **Settings > Tokens** at any time. The Tokens tab is also where you create development tokens for local use.
4. Click **Next** to continue.

<figure><img src="/files/3nyfvStgBzlJZzjVIZrQ" alt="Stage 1 of the onboarding wizard: Set up your CLI access, with the Generate token control"><figcaption><p>Stage 1: Set up your CLI access</p></figcaption></figure>

## 2. Connect your source control

Connecting Seal to your source control gives Seal more accurate visibility into your packages and, for GitHub, lets Seal open automatic pull requests for fixes. Seal recommends connecting if you can. It is not a blocker: if your team does not yet have permission to install GitHub Apps in your organization or approval will take time, click **Maybe later** and proceed with a CLI-only setup. Seal works fully without source-control access.

The wizard's source-control step uses **GitHub**, through the Seal GitHub App. Click the GitHub card to install and authorize the app. You will be redirected to GitHub to choose which repositories Seal sees, then returned to the wizard.

For **GitLab** or **Azure DevOps** connections, set those up later from the Projects page using the **Import project** button.

<figure><img src="/files/vsxjQJRR7QihTHmGT9sQ" alt="Stage 2 of the onboarding wizard: Connect your source control, showing the GitHub card"><figcaption><p>Stage 2: Connect your source control</p></figcaption></figure>

## 3. Import your first projects

After GitHub is connected, the wizard offers two import flows:

* **Pick from a list of all your repositories.** Seal lists the repositories you authorized; you select which ones to import. This flow works well when your authorized set is in the dozens. With thousands of repositories it becomes impractical to select individually; importing all of them is possible, but the initial scan can take an hour or more.
* **Paste specific repository URLs.** If you already know which repository or repositories you want, paste their URLs directly. The manual flow is currently capped at three URLs.

Once at least one project is imported, click **Next** to finish the wizard. You land on the Dashboard.

<figure><img src="/files/WN50lytmrqUo1c12vpFh" alt="Stage 3 of the onboarding wizard: Import your first projects, showing the repository list"><figcaption><p>Stage 3: Import your first projects</p></figcaption></figure>

## The Welcome cards on the Protection page

Until your tenant has accumulated scan data, the Protection page shows two suggestion cards in place of the usual tabs. The cards are the same setup choices the wizard offers and remain available whether you went through the wizard, skipped it, or your tenant was configured to skip it from the start. Once Seal has scanned at least one Seal Project, the cards are replaced by the regular Protection page tabs.

<figure><img src="/files/5xKfFjRcWCHz7u1NclGE" alt="The Protection page in its empty state, showing the Connect to source control and Connect to artifact server Welcome cards"><figcaption><p>The Welcome cards on the Protection page</p></figcaption></figure>

### Connect to source control

The card's primary button is labeled **Import projects**. Clicking it opens a dropdown of supported sources:

* **GitHub** (the recommended path; uses the Seal GitHub App).
* **GitLab**.
* **Azure DevOps**.
* **Snyk**, for importing existing Snyk projects into Seal.
* A file-upload option for one-shot manifest or SBOM imports.

Selecting a source opens its modal, which handles authentication and project selection.

### Connect to artifact server

The card's button is labeled **See instructions**. Clicking it opens an in-page guide showing the three things you need to use the Seal Artifact Server as a deployment method:

1. **Generate an access token.** The same generate-token control the wizard uses is embedded in the modal. If you already have a token saved, you do not need a new one.
2. **Configure Seal as an artifact server** in your package manager.
3. **Edit your dependency files** to use sealed versions.

The modal links out to the relevant setup chapters and to `support@seal.security` for help.

<figure><img src="/files/JEmFvRQXdmH14JFyk5ls" alt="The Connect to artifact server instructions modal, showing the three numbered setup steps"><figcaption><p>The artifact-server instructions modal</p></figcaption></figure>

## After the wizard

Initial scans run in the background.

Right after the wizard exits, the [Dashboard](/discovering/dashboard) shows a Welcome view with onboarding suggestions rather than the regular metric tiles, since no scans have produced data yet. To watch scan results as they come in, open the **Vulnerable packages** tab on the Protection page. (Until at least one scan has produced data, that tab is replaced by the [Welcome cards](#the-welcome-cards-on-the-protection-page) above.) Once it appears, the tab lists the vulnerable packages Seal has found, the vulnerabilities affecting them, and a count of vulnerable packages at the top. It updates as each scan completes.

If you skipped source-control connection, your next step is usually to install the Seal CLI in your CI/CD pipeline. See [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd).

To create additional Seal Projects, see [Creating a Seal Project](/getting-started/creating-a-seal-project).

## Related

* [Sign up and sign in](/getting-started/sign-up-and-sign-in)
* [Managing tokens](/getting-started/tokens)
* [The Protection page](/discovering/protection-page)


# Managing users, roles & SSO

User roles, inviting team members, and configuring single sign-on.

Tenant administrators manage users from **Settings**. Seal supports four user roles with distinct permission sets, an invite-based flow for adding team members, and SAML single sign-on for organizations that use it.

<figure><img src="/files/2koBbhLSGDfqLReo7xtN" alt="The Settings > User permissions tab with user rows and the Invite new user button."><figcaption><p>The User permissions tab on the Settings page.</p></figcaption></figure>

* [User roles](/getting-started/users-and-sso/user-roles): the four roles (Admin, Sealer, Collaborator, Watcher) and the permission matrix.
* [Inviting and managing users](/getting-started/users-and-sso/inviting-users): the invite flow, role changes, and revoking access.
* [SSO and SAML](/getting-started/users-and-sso/sso-and-saml): connecting your identity provider through the authentication portal.


# User roles

The four user roles in Seal and the permission matrix.

Seal supports four user roles, each with a distinct permission set. Tenant administrators assign a role at the time they invite a user and can change a user's role later.

## The four roles

<figure><img src="/files/uvFMlZsO9LhbKD9GBJEk" alt="The User permissions page with a role dropdown open on one row"><figcaption><p>Tenant admins assign and change user roles from Settings → User permissions.</p></figcaption></figure>

The roles form a hierarchy, with each level adding capabilities on top of the one below.

* **Admin.** Full permissions. In addition to everything a Sealer can do, an Admin controls tenant-wide settings: managing users and their roles, generating tokens, configuring SSO, enabling automatic pull requests, enabling AI features, and the rest of the tenant configuration.
* **Sealer.** Operating permissions that can affect the actual code running in your environment. Sealers create and edit remote Sealing Rules, configure automatic pull requests, and otherwise drive the Seal CLI to apply fixes. They cannot change tenant-wide settings or manage users.
* **Collaborator.** Operating permissions that can affect how your security posture is reported, but not the code that runs. Collaborators can scan, import data, hide packages from views, and trigger Generate fix on a vulnerable package. They cannot create Sealing Rules.
* **Watcher.** Read-only. Watchers can view data and generate reports.

## Permission matrix

| Permission                                                 | Admin | Sealer | Collaborator | Watcher |
| ---------------------------------------------------------- | :---: | :----: | :----------: | :-----: |
| View data (the Protection page, the Repository page, etc.) |   ✓   |    ✓   |       ✓      |    ✓    |
| Generate reports                                           |   ✓   |    ✓   |       ✓      |    ✓    |
| Import a manifest, SBOM, or Snyk export                    |   ✓   |    ✓   |       ✓      |         |
| Hide and restore rows on the Protection page               |   ✓   |    ✓   |       ✓      |         |
| Create, edit, or archive a Seal Project                    |   ✓   |    ✓   |       ✓      |         |
| Connect source control                                     |   ✓   |    ✓   |       ✓      |         |
| Trigger a scan                                             |   ✓   |    ✓   |       ✓      |         |
| Trigger Generate fix on a vulnerable package               |   ✓   |    ✓   |       ✓      |         |
| Create Sealing Rules                                       |   ✓   |    ✓   |              |         |
| Configure automatic pull requests                          |   ✓   |    ✓   |              |         |
| Edit tenant settings                                       |   ✓   |        |              |         |
| Invite users and change their roles                        |   ✓   |        |              |         |
| Generate tokens                                            |   ✓   |        |              |         |

## Permissions and the Seal AI Agent

The Seal AI Agent runs in the context of the user who triggered it. Anything you ask the AI Agent to do is gated by your role's permissions: a Watcher cannot ask the AI Agent to create a Sealing Rule, a Collaborator cannot ask it to invite users, and so on. The AI Agent does not have its own permissions or its own role.

The Seal Engineer is a separate product with a separate permissions model: flows run on a schedule and may act outside any individual user's session. Its guardrails (what a flow can do without explicit confirmation, how per-tenant tool gating works) are covered under the Seal Engineer chapter.

## Related

* [Inviting and managing users](/getting-started/users-and-sso/inviting-users): the invite flow and role changes.
* [SSO and SAML](/getting-started/users-and-sso/sso-and-saml): how roles are assigned when users are auto-provisioned through SAML.


# Inviting and managing users

Inviting team members, changing their roles, and revoking access.

User management lives at **Settings > Roles and Permissions**. Only users with the **Admin** role have access to this page.

<figure><img src="/files/2koBbhLSGDfqLReo7xtN" alt="The Settings Roles and Permissions page showing a list of users and their roles"><figcaption><p>The Roles and Permissions page</p></figcaption></figure>

## Inviting a user

1. Open **Settings > Roles and Permissions**.
2. Click **Invite user**.
3. Fill in the modal:
   * **Name**: the user's display name.
   * **Email**: their work email address. Seal sends the invite email here.
   * **Role**: pick one of [Admin, Sealer, Collaborator, Watcher](/getting-started/users-and-sso/user-roles).
4. Click **Send**.

<figure><img src="/files/BSIhfJqZiJJcquBR2Tyf" alt="The Invite user modal with Name, Email, and Role fields"><figcaption><p>The Invite user modal</p></figcaption></figure>

The invited user receives an email with an activation link valid for **seven days**. See [Sign up and sign in](/getting-started/sign-up-and-sign-in) for the user-side flow.

## Changing a user's role

In the **Settings > Roles and Permissions** table, click the edit icon on the user's row, pick a new role from the dropdown, and confirm. The change takes effect immediately.

## Revoking access

To remove a user from your tenant, click the delete icon on their row and confirm with **Delete** in the dialog. The user can no longer sign in to your tenant.

## Resending an invite

Seal does not have a built-in resend control. If a user's invite expires before they activate it, send them a fresh invite by repeating the **Invite user** flow with the same email address.

## Transferring the Admin role

There is no separate transfer-ownership flow. To move administration to a new user, promote them to **Admin** first, then remove the previous admin or change their role.

## Related

* [User roles](/getting-started/users-and-sso/user-roles): what each role can do.
* [SSO and SAML](/getting-started/users-and-sso/sso-and-saml): when SAML is configured for your tenant, new users can be auto-provisioned without an explicit invite.


# SSO and SAML

Connecting your identity provider through Seal's authentication portal.

Seal supports SAML single sign-on through an embedded authentication portal. Tenant Admins configure their identity provider (IdP) by opening the portal from Seal's Settings; the actual SAML metadata exchange happens there.

## Opening the configuration screen

1. Sign in to Seal as a user with the **Admin** role.
2. In **Settings**, open the **Admin portal** page. The page explains that Seal uses the Frontegg platform for authentication and provides an **Admin portal** button.
3. Click the **Admin portal** button. A pop-up window opens to the Frontegg configuration screen, where you set up SAML, multi-factor authentication, and other authentication features for your tenant.

<figure><img src="/files/G4zgz4QzRkyrM3etuBXQ" alt="The Settings Admin portal page with the launch button"><figcaption><p>The Admin portal page in Settings</p></figcaption></figure>

## Configuring SAML

Inside the configuration screen, set up your IdP using the standard SAML steps:

* Provide the IdP metadata URL or upload an XML metadata file.
* Map SAML attributes (email, display name, and any role attribute you want Seal to consume).
* Set the application's ACS URL and entity ID in your IdP, using the values shown in the screen.

Field-level help and per-IdP guidance live inside the configuration screen rather than in these docs.

## Auto-provisioning

Once SAML is configured for your tenant, any user at your organization can sign in directly through your IdP. The first time a user signs in, Seal auto-provisions an account in your tenant. They do not need a separate email invite.

The role auto-provisioned users receive depends on your IdP attribute mapping. Configure attribute mappings in the authentication portal to assign roles automatically; otherwise, an Admin will need to update each new user's role from **Settings > Roles and Permissions** after their first sign-in.

## Related

* [Inviting and managing users](/getting-started/users-and-sso/inviting-users): when SAML is not configured, this is how you add users.
* [User roles](/getting-started/users-and-sso/user-roles): what each role can do, including roles assigned through SAML attribute mapping.
* [Sign up and sign in](/getting-started/sign-up-and-sign-in): the user-side sign-in experience, including SSO.


# Managing tokens

Production and development tokens, how to generate them, and how to handle them safely.

Tokens authenticate the Seal CLI (and other clients) against the Seal Artifact Server. Token generation and revocation live at **Settings > Tokens**; only Admin-role users have access.

<figure><img src="/files/DYeUYl1kU5rntEzmU4jq" alt="The Settings > Tokens tab with token rows and the New token button visible."><figcaption><p>The Tokens tab on the Settings page.</p></figcaption></figure>

* [Token types](/getting-started/tokens/token-types): production versus development, and when to use each.
* [Generating and revoking tokens](/getting-started/tokens/generating-tokens): the create flow, the one-time reveal, and revocation.
* [Token security best practices](/getting-started/tokens/best-practices): scope, rotation, and where to store tokens.


# Token types

Production tokens versus development tokens, and when to use each.

Seal supports two token types: **Production** and **Development**. They authenticate against the Seal Artifact Server in the same way; they differ in tracking and intended usage.

## Production tokens

Activity that uses a production token is tracked by Seal. Production tokens are intended for the CI/CD pipeline of your main branch, where Seal's view of your discovered packages should be authoritative.

## Development tokens

Activity that uses a development token is not tracked the same way. Vulnerable packages discovered through scans that authenticated with a development token are filtered out of the Protection page by default, so they do not dilute the production picture with churn from local builds and feature branches.

The **Settings > Tokens** page itself shows all tokens regardless of type; the default filter applies to scan results on the Protection page, not to the Tokens table.

## Picking the right type

Use a production token for any pipeline that runs on your main branch, and a development token for local machines and feature-branch CI/CD.

You do not need a separate token per project or per pipeline. Most tenants operate with a single production token reused across CI/CD pipelines and a single development token shared by developers.

## Related

* [Generating and revoking tokens](/getting-started/tokens/generating-tokens): the UI flow.
* [Token security best practices](/getting-started/tokens/best-practices): scope, rotation, and storage.


# Generating and revoking tokens

Creating a token, copying it during the one-time reveal, and revoking it.

Token generation and revocation live at **Settings > Tokens**. Only Admin-role users have access.

## Generating a token

1. Open **Settings > Tokens**.
2. Click **Create token**.
3. Fill in the form:
   * **Token name**: a name that helps you identify what the token is for. You do not need a separate token per project; most tenants are fine with one production token and one development token, named accordingly.
   * **Token type**: [Production or Development](/getting-started/tokens/token-types).
   * **Expiry**: **Never** or **After one year**.
4. Click **Create token**.

<figure><img src="/files/HfCpEl0gVyIUIGSVK1u3" alt="The Create token modal with Token name, Token type, and Expiry fields"><figcaption><p>The Create token form</p></figcaption></figure>

The next step shows the token value with a copy-to-clipboard button. **The token is shown only once.** Copy it before you close the modal; the **Done** button is disabled until you copy. If you close the modal without copying, the token is unrecoverable. In that case, generate a new one and revoke the lost one.

<figure><img src="/files/j8Z30aFmnZNq2KHkIxjG" alt="The token one-time reveal modal with the token value, copy button, and a disabled Done button"><figcaption><p>The token's one-time reveal</p></figcaption></figure>

## Revoking a token

1. Open **Settings > Tokens**.
2. Find the token in the table and open its row menu.
3. Click the delete icon. A confirmation dialog appears showing the token's name and warning that the action is irreversible.
4. Click **Delete** to confirm.

The token is invalidated immediately. Any client still using it will fail authentication on its next request.

## The Tokens table

The **Settings > Tokens** page lists all tokens for your tenant in a single table:

<figure><img src="/files/K9YzK2psEXEIjNIwogdD" alt="The Settings Tokens page showing a table of production and development tokens"><figcaption><p>The Tokens table</p></figcaption></figure>

| Column            | Description                                                      |
| ----------------- | ---------------------------------------------------------------- |
| **Name**          | The token's name.                                                |
| **Type**          | Production or Development.                                       |
| **Expiry**        | Never, or the number of days remaining before the token expires. |
| **Created by**    | The user who generated the token.                                |
| **Creation date** | When the token was created.                                      |

There is no built-in rotation or auto-renewal: tokens with **Never** expiry remain valid until manually revoked, and tokens with **After one year** expiry are auto-invalidated at the one-year mark.

## Related

* [Token types](/getting-started/tokens/token-types): when to use each type.
* [Token security best practices](/getting-started/tokens/best-practices): scope, rotation, and storage.


# Token security best practices

Scoping, rotating, and storing Seal tokens safely.

Seal tokens authenticate against the Seal Artifact Server only. They allow pulling sealed packages; they do not authorize any operation on the Seal Platform on the holder's behalf. Treat them like any other credential.

## Store tokens in a secret manager, not in source

Production tokens belong in your CI/CD's secret store: GitHub Actions encrypted secrets, GitLab CI variables, Azure DevOps secret variables, or a dedicated secret manager that your CI/CD pulls from. Never check a production token into source control.

Development tokens belong in the developer's local secret manager or environment variables, never in a shared file or chat.

## Use the right token type for the context

Production tokens are tracked. Use them only on main-branch CI/CD pipelines where the activity should be authoritative in Seal's view.

Development tokens are not tracked. Use them for local machines and feature-branch pipelines, where activity is noisy and would otherwise dilute the production picture.

## Rotate periodically

Seal tokens with **Never** expiry remain valid indefinitely. For operational hygiene, rotate production tokens at a cadence that matches the rest of your secret-rotation policy:

1. Generate a new token.
2. Update the secret in your CI/CD secret store.
3. Confirm a CI run completes successfully with the new token.
4. Revoke the old token.

Tokens created with **After one year** expiry are auto-invalidated at the end of the year; even so, you should rotate ahead of expiry rather than letting builds fail when the token expires.

## Revoke immediately if leaked

If a token is exposed (committed to source, pasted into a chat, recovered from logs), revoke it immediately from **Settings > Tokens**. Generate a fresh token and update your secret store.

## Related

* [Token types](/getting-started/tokens/token-types): production versus development.
* [Generating and revoking tokens](/getting-started/tokens/generating-tokens): the UI flow.


# Creating a Seal Project

Creating, naming, and managing the Seal Projects that represent your codebases and pipelines.

A **Seal Project** is the entity inside the Seal Platform that represents one of your codebases or build pipelines. Each Seal Project has its own [package discovery mode](/discovering/package-discovery-mode) (source code, CLI, artifact server, or imported manifest), its own deployment method, and its own scan history. Most of Seal's day-to-day pages (Sealing Rules, the Protection page, reports) are scoped per Seal Project.

Users with the Admin, Sealer, or Collaborator [role](/getting-started/users-and-sso/user-roles) can create, edit, and archive Seal Projects. Watchers cannot.

<figure><img src="/files/UjOT4YFY2MigfJ8k4468" alt="The Projects page showing a table of Seal Projects with edit, archive, and delete controls"><figcaption><p>The Projects page</p></figcaption></figure>

## How Seal Projects get created

You can create a Seal Project in four ways:

* **Through the onboarding wizard** when a tenant is first set up. The wizard creates one Seal Project per imported GitHub repository.
* **From the Projects page** using the **Import projects** dropdown, with five sources: GitHub, GitLab, Azure DevOps, Snyk, or file upload (for one-shot manifest or SBOM imports).
* **From the Projects page** using the **New project** button, for Seal Projects that do not correspond to an imported source-control repository.
* **Implicitly through the Seal CLI.** When the CLI runs with a `SEAL_PROJECT` value that does not match any existing Seal Project in your tenant, the Seal Platform creates a new project automatically and uses the supplied value as the project's Project ID. This is useful for organizations with thousands of pipelines, where pre-creating projects through the UI is impractical.

## Project ID and project name

Every Seal Project has two distinct identifiers:

* **Project ID:** machine-readable, immutable after creation, restricted to letters, numbers, dots, hyphens, and underscores (no spaces or other punctuation), up to 255 characters. The Seal CLI and the Seal Public API both work against the Project ID. The `SEAL_PROJECT` environment variable holds the Project ID.
* **Name:** human-readable, mutable, allows spaces and a wider character set. The name is used in the Seal UI: the Projects table, page titles, search.

Both fields are unique within a tenant. The two are independent: renaming a project in the UI does not affect its Project ID, and the Project ID cannot be changed once the project exists.

### How the two identifiers are populated

* **Imported from source control.** Seal generates the Project ID automatically from the connected repository (it is opaque, not human-friendly). The display name is derived from the owner, repository name, and (when one repository contains multiple manifests) the path to the manifest file.
* **Created manually with the New project button.** You provide a name. The Project ID is assigned by the platform.
* **Created implicitly through the CLI.** The Project ID is the exact value of `SEAL_PROJECT`. The platform fills in a starter name based on it, which you can change later.

### Picking a Project ID

The only path that lets you pick a Project ID is implicit creation through the Seal CLI: whatever value you put in `SEAL_PROJECT` becomes the Project ID. SCM imports and the **New project** button both leave the Project ID to the platform.

Because the Project ID is what your CI/CD pipelines and any automation reference forever, the value you choose for `SEAL_PROJECT` deserves the same care you would put into naming a build artifact or a container image. What works in practice:

* **Mirror your existing naming.** If your CI/CD pipelines, container registries, or other tooling already name things by `{team}/{service}` or `{repo}-{component}`, use the same shape for the Project ID. Cross-tool searches stay clean.
* **Stay consistent on case and separators.** Pick lowercase or mixed-case, dots or hyphens or underscores, and apply uniformly. Customers who slip into `my-app`, `MyApp`, and `my_app` for the same component end up with three Seal Projects instead of one.
* **Disambiguate when one repository ships multiple components.** If a single source repository builds two different containers or components, give them distinct Project IDs (typically by appending the path or component label).

## Mapping projects to your environment

A Seal Project's source-code or CLI mode operates against a single manifest file (`requirements.txt`, `package-lock.json`, `pom.xml`, and so on). That has two consequences for how you carve up your repositories.

* **One Seal Project per programming language.** A repository that contains a Python service plus a Java tool needs two Seal Projects, one per manifest. There is no way to scan multiple manifests under a single project.
* **One Seal Project per deployable unit.** Beyond the per-language constraint, give each separately-built artifact its own Seal Project.

Some scenarios:

* **One repository, one application, one manifest.** One Seal Project. Name it after the repo.
* **One repository, multiple manifests** (monorepo, multi-language, or multi-component). One Seal Project per manifest, named with the path or component as a suffix.
* **CLI-only deployment with no source-control connection.** One Seal Project per CI/CD pipeline that runs the CLI. Either pre-create the project from the **New project** button or let the CLI create it implicitly on first run.

### Anti-patterns

* **Reusing one Project ID across unrelated pipelines.** The platform attributes each scan to the project the ID matches, and the latest scan overwrites the previous one. Two pipelines reporting under the same `SEAL_PROJECT` value will see each other's results clobber theirs.
* **Frequently switching a project's modes.** See [Mode changes](#mode-changes) below.

## The Default project

Every tenant has a built-in Seal Project named **Default**. It collects package-detection results that cannot be attributed to a specific project, including unattributed SBOM uploads and similar one-shot activity.

The Default project is special. Treat it as a catch-all view rather than a real Seal Project:

* Do not connect it to source control.
* Do not point your Seal CLI at it.

If you find detection results in the Default project that belong somewhere else, the right move is usually to create the appropriate Seal Project and re-run the relevant scan or import there.

## Filtering the Projects table

The Projects toolbar has a search box and two multi-select filters that narrow which rows the table shows. Both filters accept more than one value at a time and are stored in the page URL, so a filtered view can be bookmarked or shared.

* **Package discovery** filters by each project's [package discovery mode](/discovering/package-discovery-mode): **Source control** (projects connected to GitHub, GitLab, or Azure DevOps), **CLI**, **Artifact server**, **Imported manifest**, and **Unknown** for projects with no discovery signal yet.
* **CLI fix mode** filters by the [CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode) the project last ran in: **All**, **Remote**, **Local**, and **No CLI** for projects that have not run the Seal CLI.

See [Mode changes](#mode-changes) for what these two settings mean and how they change over time.

## Editing a project

In the Projects table, click the edit icon on a project row. The **Edit project** modal opens with these fields:

* **Name**.
* **Description** (optional).
* **Source control path URL** is the URL to the project's manifest file in your source control system (for example, the GitHub URL of `requirements.txt` or `package-lock.json`). The UI validates that the URL points to a recognized manifest file; non-manifest URLs are rejected.

Changes save with the **Save** button.

<figure><img src="/files/xqEppFKZEtsJ0Jae0Naa" alt="The Edit project modal with Name, Description, and Source control path URL fields"><figcaption><p>The Edit project modal</p></figcaption></figure>

### Connecting an existing project to source control

You can take a project that started as CLI-only or artifact-server-only and connect it to your source control system later. From the project's Edit modal, set the **Source control path URL** to the URL of the project's manifest file. Seal needs read access to the repository, which is provided by the connected SCM integration.

### Archiving a project

Click the archive icon on a project row. The project moves from the **Projects** tab to the **Projects archive** tab and stops being scanned. Archived projects are not deleted; you can restore them from the archive.

### Deleting a project

Click the delete icon. The project is permanently removed, along with its scan history. Deleting is irreversible; archive first if you might want the project back.

## Mode changes

A project's CLI fix mode and package discovery mode can change after creation, but they behave differently.

### CLI fix mode

The CLI fix mode is freely changeable in any direction. It updates whenever the Seal CLI runs against the project: the platform records the mode the CLI ran in (local, remote, or all) and shows that as the project's current mode. To switch modes, change the CLI's invocation in your pipeline; the next run updates the recorded mode.

### Package discovery mode

The package discovery mode is one-way. Behind the scenes, the platform picks a single "best" signal source per project and ignores everything else. The order, from least to most reliable:

1. **Imported manifest** (a one-shot snapshot at upload time).
2. **Artifact server** (signal accumulates as your build pulls sealed packages).
3. **CLI** (the CLI reports each run).
4. **Source code** (Seal's SCM integration reads your manifests directly).

A project moves up this hierarchy automatically when a more reliable source produces signal. Pulling a sealed package from the Seal Artifact Server while a project is in imported-manifest mode promotes it to artifact-server mode. Running the Seal CLI against the project promotes it to CLI mode. Connecting source control promotes it to source-code mode.

The reason this is one-way is that a "downgrade" cannot really happen: if a project is in source-code mode and your build also pulls from the Seal Artifact Server, the artifact-server pulls are ignored. The same applies all the way down: any signal from a less reliable source than the project's current mode is dropped. So if you point an unrelated pipeline's CLI invocation, or a stray artifact-server pull, at a project that already has a more reliable source, those events disappear silently rather than appearing under that project.

To genuinely operate a project in a less reliable mode, archive or delete it and create a new one.

{% hint style="info" %}
**Tip: pick a mode and stick with it.** The platform tolerates mode changes, but reports and Sealing Rules become harder to reason about when a project bounces between modes. Change only when you have a reason to.
{% endhint %}

## Related

* [The onboarding wizard](/getting-started/onboarding-wizard): the wizard creates your tenant's first Seal Projects.
* [Package discovery mode](/discovering/package-discovery-mode): the four modes a Seal Project can use.
* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): the deployment method options for Seal Apps.


# Your first Proof of Value

Validating Seal on a representative component from your environment, with sales engineering support.

A Proof of Value (PoV) is a structured evaluation of Seal against your own codebase, run jointly with Seal's sales engineering team. It is not a self-service trial. By the end, you should be confident that Seal can remediate the open-source vulnerabilities in your stack without breaking your components, and you should have a working plan for how to deploy Seal in production.

A typical PoV runs 2-3 weeks. A Seal sales engineer is available throughout: scoping the work with you, building the sealed packages you ask for, and helping you over any rough spots in integration.

## What a successful PoV produces

You leave the PoV with two things:

* **Confidence that Seal works on your code.** Sealed versions of packages from your environment, dropped into your build, with the component still passing your tests.
* **A deployment plan.** A concrete idea of which deployment method (Remote, Local, Artifact Server, Manual) you will adopt, where it sits in your CI/CD, and what rollout looks like after the PoV.

## Picking a component

The PoV runs against a single component from your environment, sometimes two. Pick something:

* **Representative of your real stack.** If most of your build pipeline is Java with Maven, a Java/Maven service is the right pick. Choosing the one Python tool nobody owns will not tell you what you need to know.
* **Vulnerable.** The component should have known open-source vulnerabilities, ideally including some high or critical severity. Without vulnerabilities to remediate, there is nothing for Seal to demonstrate.
* **Buildable and testable by you.** You need to be able to rebuild the component with the sealed packages in place, and you need to be able to verify it still works (functional tests, integration tests, a manual smoke test, whatever you trust).

Enterprises ship many components in many ecosystems, and producing sealed versions for all of them up front is not the point of a PoV. One representative component is enough to prove the mechanics. If your environment has two genuinely distinct stacks (for example, a Maven backend and an npm frontend) and one is not representative of the other, picking one component from each is reasonable. More than that is usually unproductive.

## The steps

### 1. Kickoff with sales engineering

A Seal sales engineer walks through your setup with you: which ecosystems you use, where your build pipelines live, which vulnerability scanners you run, and what your remediation workflow looks like today. Out of that conversation, you agree on:

* The component you will use as the PoV target.
* The deployment method that fits your environment best (typically Remote or Local mode of the Seal CLI).
* Who on your side runs the integration: usually a developer or a DevOps engineer.

### 2. Send the package list

Once the component is chosen, send Seal a list of the vulnerable open-source packages it depends on, with **exact package names and exact versions**.

The version is essential. Seal builds a sealed version from a specific origin version, not from a range. `requests@2.28.1` and `requests@2.31.0` are two separate origin versions and produce two separate sealed versions; Seal needs to know which one your component actually pulls in.

The list usually comes from your existing scanner: a CSV export from Snyk, the dependency tree from `mvn dependency:tree`, the lockfile from `package-lock.json`, or a similar artifact. Whatever format it arrives in, the names and versions need to be unambiguous.

### 3. Seal builds the sealed packages

<figure><img src="/files/GDZL3XeqhorI13k2goji" alt="The Sealed packages tab on the Protection page with a freshly built sealed package row"><figcaption><p>Sealed packages appear on the Protection page's Sealed packages tab once your build pulls them.</p></figcaption></figure>

From your list, Seal selects 3-5 packages that exemplify your remediation needs (high and critical CVEs, mainstream packages, a representative spread across ecosystems if relevant) and produces sealed versions for them. The sealed packages land on the Seal Artifact Server, ready for your build to pull.

The sealed versions do not appear on the Protection page's Sealed packages tab right away. They show up there only after your build (or a manual download) actually pulls each sealed package at least once. Until then, you can still:

* Create a Sealing Rule against the new sealed version, so the next CLI run replaces the vulnerable origin version with it.
* Pull the sealed package directly from the Seal Artifact Server in artifact-server deployments.
* Download the sealed artifact manually from the Repository page and drop it into your build by hand.

### 4. Integrate the sealed packages into your build

There are two paths for getting the sealed packages into your component.

**Recommended: a separate dev pipeline.** Run the Seal CLI in a dev or feature-branch CI pipeline, configured to replace the vulnerable packages with their sealed counterparts. This is what the integration will look like in production, so testing it at PoV time gives you a directly applicable result.

**Fallback: manual replacement.** If standing up a dev pipeline is impractical at PoV time (vendor onboarding delays, security review, no DevOps capacity, or the component is built in a way that does not lend itself to a separate pipeline), the developer can replace the packages manually. Pull each sealed version from the Seal Artifact Server or download it from the Seal UI, swap it into the build, and rebuild. This requires more developer time and does not validate the production integration, but it does prove that the sealed packages work.

Your sales engineer will help you pick the right path and unblock you if integration runs into trouble.

### 5. Build and test

Rebuild the component with the sealed packages in place, and run whatever validation you would normally run before shipping. The goal is to confirm two things:

* The build succeeds.
* The component behaves the same as it did with the original packages.

If something fails, your sales engineer is the first call. Most issues at this stage are integration-level (a misconfigured CLI invocation, a manifest the Seal CLI did not pick up, a registry-routing problem) rather than problems with the sealed packages themselves.

### 6. Review against success criteria

With the rebuild green, walk through the [success criteria](#what-a-successful-pov-produces) above with your sales engineer. If both hold, the PoV is successful and the conversation moves to deployment planning.

## Timeline expectations

The clock on a PoV starts when you send Seal the package list and stops when you finish testing the rebuilt component. That window is typically 2-3 weeks. Most of it is on your side: integrating in a dev pipeline (or finding a developer with time to do the manual swap) and running tests. Seal's package builds typically take a few days from list to delivery.

## Related

* [The onboarding wizard](/getting-started/onboarding-wizard): how a tenant is set up at the start of a PoV.
* [Creating a Seal Project](/getting-started/creating-a-seal-project): the Seal Project that holds the PoV component's scan data.
* [Architecture overview](/introduction/architecture): the components that show up in the integration step.


# Discovering vulnerabilities

How Seal discovers your packages, and the UI surfaces you use to triage what it finds.

Seal needs to see your packages before it can remediate them. This section covers the four ways Seal sees your environment (the **package discovery modes**), the connections that feed them, and the UI pages where you triage the discovered vulnerabilities day-to-day.

## What's in this section

* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): the model and the four discovery modes.
* [Package discovery mode](/discovering/package-discovery-mode): one page per mode (source code, CLI, artifact server, imported manifest).
* [Connecting source control](/discovering/connecting-source-control): GitHub, GitLab, Azure DevOps; connection management.
* [Connecting via the Seal CLI in CI](/discovering/cli-in-ci): the CLI as the discovery signal.
* [Configuring the Seal Artifact Server for discovery](/discovering/artifact-server-discovery): when your build pulls drive discovery.
* [Importing manifests & SBOMs](/discovering/importing-manifests): one-shot import from a dependency manifest or SBOM.
* [The Dashboard](/discovering/dashboard): the tenant-wide aggregate view.
* [The Protection page](/discovering/protection-page): the per-package triage view, with four tabs (vulnerable, sealed, sealing rules, scanner exclusions).
* [Package states](/discovering/package-states): the six states a vulnerable package can be in.
* [Triggering Generate fix](/discovering/generate-fix): asking Seal to build a sealed version on demand.
* [The package drawer](/discovering/package-drawer): the per-package drawer.
* [The Repository page](/discovering/repository-page): the public catalog of sealed packages.
* [Partial fixes & open vulnerabilities](/discovering/partial-fixes): when a sealed version still carries open vulnerabilities, and why.
* [Private versions](/discovering/private-versions): sealed versions whose fix introduces a breaking change.


# How Seal discovers your packages

The four package discovery modes Seal supports, and the trade-offs each one makes.

Before Seal can remediate a vulnerable package, it has to know the package is in your environment. The mechanism is **package discovery**: a per-Seal-Project setting that controls how the Seal Platform learns about the packages in your codebase. Seal supports four package discovery modes, and a Seal Project uses exactly one at a time.

The mode determines how complete the platform's picture is and how much of your environment Seal needs access to. If your organization restricts source-code access to third-party tooling, the three no-source modes still give you full remediation. Only the discovery side changes.

## The four modes

| Mode                  | How Seal learns about your packages                                           | What Seal needs                                                  |
| --------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| **Source code**       | A connected SCM integration reads your dependency manifests directly.         | Read access to the repository.                                   |
| **CLI**               | The Seal CLI runs in your CI/CD pipeline and reports the manifest it scanned. | The Seal CLI integrated into your build.                         |
| **Artifact server**   | The Seal Artifact Server records each sealed package your build pulls.        | Your package manager configured to use the Seal Artifact Server. |
| **Imported manifest** | A one-shot upload of a manifest, lockfile, or SBOM.                           | The file.                                                        |

The full reference for each mode is in [Package discovery mode](/discovering/package-discovery-mode).

## Trade-offs

The four modes are not equivalent. They differ on three axes that matter day to day.

**Completeness.** Source code mode sees the manifest as Seal's integration parses it. Artifact server mode only sees what your build actually pulls, which can miss declared-but-unused dependencies. CLI mode sits between the two, reporting what the CLI's scan reads on each run. Imported manifest mode is whatever was in the file you uploaded, nothing more.

**Freshness.** Source code mode tracks the latest commit. CLI mode updates each pipeline run. Artifact server mode accumulates over time as pulls happen, so the picture builds up but never reflects the very latest commit. Imported manifest mode does not refresh at all; the snapshot ages from the moment it is uploaded.

**Source access.** Source code mode requires read access to the repository. The other three modes do not. CLI mode in particular is the strongest fit when your organization restricts third-party access to source: Seal still gets a complete picture, because the CLI does the manifest reading inside your pipeline and reports back only what is needed.

## What Seal can additionally tag

Beyond the package itself, Seal records two flags per discovered package row when the ecosystem and the discovery mode allow it:

* **Dev dependency.** If the package manager exposes a dev-versus-production marking natively (for example, the `devDependencies` block in `package.json` for npm) AND Seal can see the relevant manifest file, Seal tags the package accordingly. Seeing the manifest happens through a source-control connection or, equivalently, when the Seal CLI runs in your CI pipeline and reports the manifest it scanned. The tag drives the **Dev dependency** filter on the Protection page and the `is_dev_dependency` parameter of the Seal Public API. Anything not explicitly marked is assumed to reach production. Sealing Rules apply to dev and production dependencies alike; the tag is for filtering and reporting, not for rule scoping.
* **Embedded package.** A package shipped inside another package's distributed artifact. The canonical case Seal handles is the Java shaded JAR. Embedded packages do not appear as their own rows on the Protection page; they are listed in the package drawer when you open the parent package's row. Sealing the parent package transitively resolves the embedded package's vulnerabilities; no separate Sealing Rule is needed for the embedded package. See [embedded package](/introduction/glossary#embedded-package) in the glossary.

## Picking a mode

A Seal Project's mode is set when the project is created. After creation, it can move toward more reliable signal sources (toward source code) but not back. The mechanics are covered under [Mode changes in Creating a Seal Project](/getting-started/creating-a-seal-project#mode-changes).

A starting point for the choice:

* If Seal has SCM integration with your organization and the repository is in scope, **source code** mode is the most accurate.
* If you want full remediation without granting source access, **CLI** mode is the strongest no-source option.
* Use **artifact server** mode when the Seal CLI cannot run in the build (for example, when a vendor or another team owns the pipeline) but the build can be pointed at a configured remote.
* Use **imported manifest** mode for one-shot evaluation: an SBOM you received, a Snyk export, a snapshot from a vendor.

The per-mode "when to choose this" detail and the connector how-tos live under [Package discovery mode](/discovering/package-discovery-mode).

## Related

* [Package discovery mode](/discovering/package-discovery-mode): the reference for the four modes.
* [Creating a Seal Project](/getting-started/creating-a-seal-project): where a project's mode is set, and the rules for changing it later.


# Package discovery mode

Reference for the four package discovery modes a Seal Project can use.

**Package discovery mode** is a per-Seal-Project setting that controls how the Seal Platform learns about the packages in your codebase. A Seal Project uses exactly one mode at a time. There are four:

* [Source code](/discovering/package-discovery-mode/source-code): Seal's SCM integration reads your dependency manifests directly from the connected repository.
* [CLI](/discovering/package-discovery-mode/cli): the Seal CLI runs in your CI/CD pipeline, scans the manifest, and reports the result to the Seal Platform.
* [Artifact server](/discovering/package-discovery-mode/artifact-server): the Seal Artifact Server records each sealed package your build pulls.
* [Imported manifest](/discovering/package-discovery-mode/imported-manifest): a one-shot upload of a manifest, lockfile, or SBOM.

Each sub-page covers one mode in detail: what it sees, when to choose it, and how to set it up.

For the high-level orientation and trade-offs across the four modes, see [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages).

## Discovery mode is not deployment method or fix mode

Package discovery mode answers "how does Seal see my packages?". Two adjacent settings answer different questions and should not be confused:

* **Deployment method** answers "how is Seal integrated into my environment?". Five values: Automatic Remediation, Remote, Local, Artifact Server, Manual.
* **CLI fix mode** answers "what does the Seal CLI do when it runs?". Three values: local, remote, all.

A single Seal Project has all three settings, and they interact. Most commonly, a Seal Project in CLI discovery mode runs the Seal CLI in remote fix mode under the Remote deployment method.

## Mode changes

The mode is set automatically when a Seal Project first sees signal. It moves up the reliability hierarchy automatically (imported manifest → artifact server → CLI → source code) when a more reliable signal source produces signal, but it never moves back. Signals from a less reliable source than the project's current mode are dropped silently rather than recorded under the project. The full mechanics live under [Mode changes in Creating a Seal Project](/getting-started/creating-a-seal-project#mode-changes).

## Related

* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): the orientation page with the trade-off table.
* [Creating a Seal Project](/getting-started/creating-a-seal-project): where a project's mode is set, and the rules for changing it later.


# Source code

Reads your dependency manifests directly through a connected SCM integration.

In source code mode, the Seal Platform reads your dependency manifests directly from the connected repository through Seal's SCM integration. It is the most accurate and freshest of the four package discovery modes, and the default choice when an SCM connection is available.

## What it sees

Seal sees the manifest as the SCM integration parses it on each commit. For ecosystems with lockfiles checked in (`package-lock.json`, `Pipfile.lock`, `composer.lock`, and so on), this includes both direct and transitive dependencies. For ecosystems where the manifest only declares direct dependencies (a `pom.xml` without a flattened build, for example), Seal sees the direct dependencies; transitive dependencies do not appear unless the lockfile equivalent is committed.

The signal updates as soon as a new commit lands on a tracked branch. The picture matches the latest commit, not the latest deploy.

## What Seal needs

Read access to the repository, granted through a connected SCM integration. Seal supports GitHub, GitLab, and Azure DevOps. The level of read access is the minimum required to fetch dependency manifests from the repository.

If your organization restricts third-party read access to source code, source code mode is not the right choice. Use [CLI mode](/discovering/package-discovery-mode/cli) instead, which gives you the same remediation capability without granting source access.

## When to choose this mode

* You already have, or can grant, a Seal SCM integration with read access to the repository.
* You want the freshest possible picture of your packages, updated per commit rather than per build.
* For a GitHub-connected Seal Project, you want Seal to be able to open automatic pull requests for fixes (a GitHub-only feature today).

## Setting it up

A Seal Project enters source code mode automatically the first time the SCM integration produces a successful manifest read. To set up the integration, see [Connecting source control](/discovering/connecting-source-control).

You can also start a Seal Project in another mode and connect source control later. In that case the project promotes to source code mode on the first manifest read after the connection is set up, and signal from the previous mode is dropped.

## Source code mode and remediation

Source code mode covers discovery only. The actual replacement of vulnerable packages with sealed versions still requires the Seal CLI to run in your CI/CD pipeline. The Sealing Rules the CLI applies can come from either of two places:

* **Remote Sealing Rules** that you create through the Seal UI. The CLI runs in remote fix mode and pulls them at run time.
* **Local Sealing Rules** in a `.seal-actions.yml` file checked into your repository. The CLI runs in local fix mode and reads them from the file.

For source-code-mode Seal Projects on GitHub, the Seal GitHub App can populate the `.seal-actions.yml` file by opening automatic pull requests with proposed Sealing Rules. You review and merge the PRs as you would any other change. The CLI still has to run in CI on the merged commit to apply the rules and replace the packages; the automatic PRs are a way to author the rules, not to deploy them.

## Related

* [Connecting source control](/discovering/connecting-source-control): how to set up the GitHub, GitLab, or Azure DevOps integration.
* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): how source code mode compares to the other three.


# CLI

Runs the Seal CLI in your CI/CD pipeline and reports the manifest it scanned.

In CLI mode, the Seal CLI runs in your CI/CD pipeline, scans the manifest the build resolves against, and reports the result to the Seal Platform. CLI mode is the right choice when you cannot connect Seal to your source code (for example, your organization does not permit third-party SCM integrations) but you can run the Seal CLI in CI, where it can reach Seal's servers from inside the pipeline.

A Seal Project is in CLI mode only if it is not also connected to source control. Connecting source control promotes the project to source code mode and the CLI's manifest scan stops being the discovery signal (though the CLI itself can keep running for remediation; see [Sealing Rules and CLI mode](#sealing-rules-and-cli-mode) below).

## What it sees

Seal sees the manifest as the CLI's scan parses it on each pipeline run. This includes whatever the CLI is invoked against (a `package-lock.json`, a `requirements.txt`, a `pom.xml`, and so on), and behaves consistently with how a build-time scan resolves dependencies. The signal updates each time the pipeline runs, which is typically once per commit.

CLI mode does not see what is in the repository between runs. If your CI does not run on a branch, CLI mode does not produce signal for that branch.

## What Seal needs

The Seal CLI integrated into your build, configured with a [token](/getting-started/tokens). Seal does not need any read access to the repository; the CLI does the manifest reading inside your pipeline and reports back only what is needed for discovery.

## When to choose this mode

* You cannot grant Seal read access to your source code, but the Seal CLI can run inside your CI/CD and reach Seal's servers from there.
* SCM integration is on the roadmap but not yet approved, and you want full discovery and remediation in the meantime.

## Setting it up

A Seal Project enters CLI mode automatically the first time the Seal CLI runs against it. To set up the CLI in your pipeline, see [Connecting via the Seal CLI in CI](/discovering/cli-in-ci).

## Sealing Rules and CLI mode

Sealing Rules apply whenever the Seal CLI runs, regardless of which package discovery mode the Seal Project is in. The most common pairings are:

* **CLI discovery mode + the CLI running for remediation:** the CLI does both jobs in the same pipeline run.
* **Source code discovery mode + the CLI running for remediation:** the SCM integration handles discovery; the CLI runs in CI to apply Sealing Rules and replace vulnerable packages with sealed versions.

The CLI's [fix mode](/getting-started/creating-a-seal-project#cli-fix-mode) determines whether rules come from the Seal Platform (remote fix mode) or from a checked-in `.seal-actions.yml` file (local fix mode).

## Related

* [Connecting via the Seal CLI in CI](/discovering/cli-in-ci): how to set up the CLI in your pipeline.
* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): how CLI mode compares to the other three.


# Artifact server

Learns about your packages by recording what your build pulls from the Seal Artifact Server.

In artifact server mode, the Seal Platform learns about your packages indirectly: by recording what your build pulls through the Seal Artifact Server. There is no source-side or CI-side scan; the only signal Seal sees is the act of pulling.

A Seal Project is in artifact server mode only if it is not also connected to source control and the Seal CLI does not run against it. The moment either of those happens, the project promotes to a more reliable mode and the artifact-server signal stops being recorded.

## What it sees

What Seal sees in artifact server mode depends on how you configure the Seal Artifact Server in your package manager.

**As your primary or first-lookup remote.** When your package manager looks at the Seal Artifact Server first for every package, the Seal Artifact Server proxies the requests it cannot fulfill to the public registries (the npm public registry, Maven Central, PyPi, and so on) and serves sealed packages directly when one applies. In this configuration, Seal sees every package your build asks for, vulnerable origin versions included, not just the sealed versions you have already replaced.

**As a secondary or fallback remote.** When your package manager only consults the Seal Artifact Server for the specific sealed packages it has been told to fetch from there, Seal sees only those sealed-version requests. Vulnerable origin versions your build still pulls from the public registries are invisible to Seal.

In both configurations, the picture builds up as your build runs over time. It never represents the latest commit; it represents what has been requested so far.

### Caching

Caching makes the picture more indeterminate. If your CI runners cache packages locally or your organization runs an internal artifact-server cache between your build and the Seal Artifact Server, the cache fulfills requests that would otherwise reach Seal. In that case Seal might see a package pulled once, on the first build that needed it, and then never see it again, even if every subsequent build still depends on it. Seal cannot tell from the artifact-server stream whether a package is still in use, abandoned, or in use across multiple Seal Projects whose builds happen to share a cache.

### One package, multiple versions in the same project

Some package managers (npm in particular) allow the same project to use both a sealed version and the vulnerable origin version of the same package at the same time. Artifact server mode cannot tell these apart. The last pulled version of a given package wins: if the last pull was the sealed version, Seal records the package as sealed across the project; if the last pull was a vulnerable origin version, Seal records it as vulnerable across the project. Other discovery modes work from the manifest and do not have this problem.

For ongoing remediation, the higher-reliability modes (CLI or source code) avoid this entire class of indeterminacy.

## What Seal needs

Your package manager configured to use the Seal Artifact Server, with a [token](/getting-started/tokens) for authentication. No source-control connection and no CLI integration.

## When to choose this mode

* The Seal CLI cannot run in your build (for example, when a vendor or another team owns the pipeline) but your package manager can be pointed at the Seal Artifact Server.
* You operate the Artifact Server [deployment method](/setup-apps-os/choosing-deployment-method) and want the discovery side to align with it.

## Setting it up

A Seal Project enters artifact server mode automatically the first time your build pulls a sealed package authenticated as that project. To configure your package manager and tokens, see [Configuring the Seal Artifact Server for discovery](/discovering/artifact-server-discovery).

## Related

* [Configuring the Seal Artifact Server for discovery](/discovering/artifact-server-discovery): how to set up your package manager and tokens.
* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): how artifact server mode compares to the other three.


# Imported manifest

Parses a single uploaded file as the Seal Project's package picture.

In imported manifest mode, you give Seal a single file describing your dependencies. The Seal Platform parses the file once and uses that snapshot as the Seal Project's picture of your environment. The mode is well-suited to one-shot evaluation and to importing data from another tool, but it does not refresh.

## What it sees

Imported manifest mode sees whatever was in the file you uploaded, and nothing more. Supported file types include:

* **Dependency manifests** (`package-lock.json`, `requirements.txt`, `pom.xml`, `composer.lock`, and other ecosystem-specific files).
* **Software Bill of Materials (SBOM)** files in CycloneDX or SPDX format.
* **Snyk exports** (CSV from a Snyk project, or via the Snyk integration).

What imported manifest mode does not see:

* Anything that changes after the upload. The snapshot ages from the moment it is uploaded; subsequent commits, builds, or pulls do not refresh it.
* Anything not in the file. If the manifest only declares direct dependencies, Seal does not infer transitives.

## What Seal needs

The file. No SCM connection, no CLI integration, no artifact-server pull required.

## When to choose this mode

* You want a quick evaluation of Seal against an existing snapshot of your environment, without setting up an integration.
* A vendor or another team has provided you with an SBOM you need to assess.
* You have an existing Snyk export and want to bring its data into Seal.

For ongoing remediation, you will eventually want a higher-reliability mode (CLI or source code). Imported manifest mode is most useful as a starting point or for one-shot work.

## Setting it up

To upload a file, see [Importing manifests & SBOMs](/discovering/importing-manifests).

## Related

* [Importing manifests & SBOMs](/discovering/importing-manifests): the upload flows for each supported file type.
* [How Seal discovers your packages](/discovering/how-seal-discovers-your-packages): how imported manifest mode compares to the other three.


# Connecting source control

How to connect Seal to GitHub, GitLab, or Azure DevOps so it can read your dependency manifests directly.

Connecting source control is how a Seal Project gets into [source code mode](/discovering/package-discovery-mode/source-code), the most accurate of the four package discovery modes. Seal supports three source-control systems:

* [Connecting GitHub](/discovering/connecting-source-control/github): the most complete integration. Adds discovery, automatic pull requests for Sealing Rules, and findings sync.
* [Connecting GitLab](/discovering/connecting-source-control/gitlab): discovery only.
* [Connecting Azure DevOps](/discovering/connecting-source-control/azure-devops): discovery only.

GitHub uses the Seal GitHub App and an OAuth-style install flow. GitLab and Azure DevOps use a personal access token (PAT) plus the platform URL.

After a system is connected, additional repositories can be imported through the same flow without reconnecting. Existing connections are managed at [Settings > Integrations](/discovering/connecting-source-control/managing-connections).

<figure><img src="/files/hMwNnDsNv16Tv9TRs42e" alt="The Projects page Import projects dropdown showing GitHub, GitLab, Azure DevOps, Snyk, and Import from file"><figcaption><p>The Import projects dropdown</p></figcaption></figure>

## Permissions

Inside Seal, you need the **Admin** or **Sealer** [role](/getting-started/users-and-sso/user-roles) to connect or disconnect a source-control system, and to import projects.

On the source-control side, the permission you need depends on the system:

* **GitHub:** authority to install GitHub Apps on the organization (typically an org owner or a user with the appropriate org-level permission).
* **GitLab:** a personal access token from a user with **Developer, Maintainer, or Owner** role on the GitLab projects you want to scan, with the `api` scope.
* **Azure DevOps:** a personal access token with **full access**, or at least **Code (Read & Write)**.

## Related

* [Source code mode](/discovering/package-discovery-mode/source-code): the discovery mode an SCM connection puts a Seal Project into.
* [Managing source control connections](/discovering/connecting-source-control/managing-connections): viewing, re-authenticating, and disconnecting existing connections.
* [The onboarding wizard](/getting-started/onboarding-wizard): the wizard's source-control step is a wrapper around the GitHub flow described here.


# Connecting GitHub

Install the Seal GitHub App and import GitHub repositories as Seal Projects.

Connecting GitHub installs the Seal GitHub App on your organization, gives the Seal Platform read access to the repositories you choose, and makes the GitHub-only automatic pull request feature available. It is the most complete of the three source-control integrations Seal supports.

## Before you start

* You have the **Admin** or **Sealer** [role](/getting-started/users-and-sso/user-roles) in Seal.
* You can install GitHub Apps on the GitHub organization (typically an org owner, or a user with the appropriate org-level permission).
* You have decided whether to grant the app access to all repositories in the organization or to a specific list. You can change this later from GitHub.

## Steps

1. Open the **Projects** page in the Seal UI.
2. Click **Import projects** and select **GitHub** from the dropdown. The **Select projects to import from GitHub** modal opens.
3. **If the Seal GitHub App is already installed** on the organization you want to import from, the modal lists its repositories directly. Skip to step 6.
4. **If the Seal GitHub App is not yet installed** on the organization, click the install link in the modal. You are redirected to GitHub.
5. On GitHub, choose the organization, pick **All repositories** or **Only select repositories** (and pick the list), and authorize the install. GitHub returns you to Seal, and the modal now lists the organizations the Seal GitHub App can see.
6. Select the repositories you want to import as Seal Projects, then confirm.

<figure><img src="/files/GQDZGI4QlSv3mWx9H8Rl" alt="The Select projects to import from GitHub modal with repositories listed and checkboxes"><figcaption><p>Selecting GitHub repositories to import as Seal Projects</p></figcaption></figure>

## Verify

Each imported repository becomes a Seal Project in [source code mode](/discovering/package-discovery-mode/source-code). The first scan starts in the background; results appear on the Protection page's Vulnerable packages tab as the scan completes.

If you do not see your Seal Projects on the Projects page within a minute of import, refresh the page.

## Automatic pull requests

The Seal GitHub App can open pull requests against your repositories that propose Sealing Rules for the vulnerable packages Seal has discovered. The PRs do not modify your dependency manifests directly. Instead, they write the proposed Sealing Rules into a `.seal-actions.yml` file at the repository root, where they become **local Sealing Rules** scoped to that repository.

### When automatic PRs make sense

Automatic PRs are useful only when the Seal Project's deployment method is **Local**, which runs the Seal CLI in CI in local fix mode and reads its rules from `.seal-actions.yml`. Other deployment methods either ignore that file (Remote and Automatic Remediation, which take rules from elsewhere) or do not run the CLI at all (Artifact Server, Manual), so a merged automatic PR has no effect.

After you review and merge an automatic PR, the Seal CLI still has to run in CI on the merged commit to actually replace the vulnerable packages with sealed versions. Automatic PRs are an authoring path for local Sealing Rules, not a no-CLI deployment channel.

### Configuring automatic PRs

Automatic PRs are configured at **Settings > Preferences > PR Setting**. Configuring this setting requires the **Admin** [role](/getting-started/users-and-sso/user-roles).

Settings:

* **Trigger:** **On demand** or **After every scan**.
* **Update `.snyk` file:** if your CI/CD also runs Snyk and the repository contains a `.snyk` policy file, the automatic PR also updates that file to mark the vulnerabilities Seal remediated as resolved.
* **Update `.grype.yaml` file:** the same for Grype, against a `.grype.yaml` policy file in the repository.

## What the Seal GitHub App can see

The Seal GitHub App needs read access to your repository contents to read dependency manifests for discovery. If you want to use [automatic pull requests](#automatic-pull-requests), the App also needs write access to pull requests; otherwise read access is sufficient. The exact scopes are presented by GitHub during the install flow.

## Related

* [Source code mode](/discovering/package-discovery-mode/source-code): what Seal sees once GitHub is connected, and how source code mode handles remediation.
* [Managing source control connections](/discovering/connecting-source-control/managing-connections): viewing the installation later, or disconnecting.
* [The onboarding wizard](/getting-started/onboarding-wizard): the wizard's source-control step uses this same flow.


# Connecting GitLab

Connect Seal to a GitLab instance using a personal access token.

Connecting GitLab gives the Seal Platform read access to the GitLab projects you choose, so they can run in [source code mode](/discovering/package-discovery-mode/source-code). The GitLab integration covers discovery; remediation runs through the Seal CLI in your CI/CD pipeline (or one of the other deployment methods).

## Before you start

* You have the **Admin** or **Sealer** [role](/getting-started/users-and-sso/user-roles) in Seal.
* You have the URL of your GitLab instance (for example, `https://gitlab.com/your-organization/` for GitLab.com, or your self-hosted URL).
* You have a GitLab **personal access token** with the `api` scope, generated by a user with **Developer**, **Maintainer**, or **Owner** role on the projects you want to import.

## Steps

1. Open the **Projects** page in the Seal UI.
2. Click **Import projects** and select **GitLab** from the dropdown.
3. **If GitLab is not yet connected**, the modal opens at the **LOGIN** step. Fill in:
   * **GitLab URL** (the URL of your GitLab instance).
   * **Personal Access Token** (with the `api` scope).
4. **If GitLab is already connected**, the modal opens directly at the **IMPORT** step.
5. In the IMPORT step, select the GitLab projects you want to import as Seal Projects, then confirm.

<figure><img src="/files/wkQj4QIVj9lRgp2Ri1p4" alt="The Connect to GitLab modal LOGIN step with URL and PAT fields"><figcaption><p>Connecting to GitLab</p></figcaption></figure>

## Verify

Each imported project becomes a Seal Project in source code mode. The first scan starts in the background; results appear on the Protection page's Vulnerable packages tab as the scan completes.

## Related

* [Source code mode](/discovering/package-discovery-mode/source-code): what Seal sees once GitLab is connected.
* [Managing source control connections](/discovering/connecting-source-control/managing-connections): viewing or disconnecting the GitLab installation.


# Connecting Azure DevOps

Connect Seal to an Azure DevOps organization using a personal access token.

Connecting Azure DevOps gives the Seal Platform read access to the repositories you choose, so they can run in [source code mode](/discovering/package-discovery-mode/source-code). The Azure DevOps integration covers discovery; remediation runs through the Seal CLI in your CI/CD pipeline (or one of the other deployment methods).

## Before you start

* You have the **Admin** or **Sealer** [role](/getting-started/users-and-sso/user-roles) in Seal.
* You have the URL of your Azure DevOps organization (for example, `https://dev.azure.com/your-organization/`).
* You have an Azure DevOps **personal access token** with **full access**, or at least **Code (Read & Write)**.

## Steps

1. Open the **Projects** page in the Seal UI.
2. Click **Import projects** and select **Azure DevOps** from the dropdown.
3. **If Azure DevOps is not yet connected**, the modal opens at the **LOGIN** step. Fill in:
   * **Azure DevOps URL** (the URL of your organization).
   * **Personal Access Token**.
4. **If Azure DevOps is already connected**, the modal opens directly at the **IMPORT** step.
5. In the IMPORT step, select the repositories you want to import as Seal Projects, then confirm.

<figure><img src="/files/CmjahsLKYbgVR1xo0MPx" alt="The Connect to Azure DevOps modal LOGIN step with URL and PAT fields"><figcaption><p>Connecting to Azure DevOps</p></figcaption></figure>

## Verify

Each imported repository becomes a Seal Project in source code mode. The first scan starts in the background; results appear on the Protection page's Vulnerable packages tab as the scan completes.

## Related

* [Source code mode](/discovering/package-discovery-mode/source-code): what Seal sees once Azure DevOps is connected.
* [Managing source control connections](/discovering/connecting-source-control/managing-connections): viewing or disconnecting the Azure DevOps installation.


# Managing source control connections

View existing source-control installations, disconnect, or replace credentials.

Existing source-control connections live at **Settings > Integrations**. The page shows one card per integration: GitHub, GitLab, Azure DevOps, and Snyk. Clicking a card opens a drawer listing the installations the tenant has set up for that integration.

<figure><img src="/files/2NUxY0v5jQQHRhhE806s" alt="The Settings Integrations page showing GitHub, GitLab, Azure DevOps, and Snyk cards"><figcaption><p>The Integrations page</p></figcaption></figure>

## Viewing an installation

Click the card for the integration you want to look at. A drawer opens listing each installation: the GitHub organization, GitLab instance, or Azure DevOps organization the tenant is connected to. Each row shows the owner name (which is copyable) and a delete button.

<figure><img src="/files/cEcDBk0v7VDVWTJAvkdV" alt="The Integrations drawer showing two GitHub installations with delete controls"><figcaption><p>The Integrations drawer for GitHub</p></figcaption></figure>

## Disconnecting

To remove an installation, click the delete icon on its row in the drawer and confirm.

What disconnecting does:

* Stops further discovery for the Seal Projects that were using this connection. They remain in source code mode (per the [one-way mode rule](/getting-started/creating-a-seal-project#mode-changes)) but stop receiving fresh signal.
* Stops the Seal GitHub App from opening new automatic PRs for the affected Seal Projects (GitHub only).

What disconnecting does not do:

* Delete the imported Seal Projects. They remain on the Projects page until you archive or delete them.
* Remove the Seal GitHub App from your GitHub organization. If you want to fully uninstall the app on the GitHub side, do that from your GitHub organization settings as well.

## Re-authenticating

Seal does not expose an in-place re-authentication control. To replace credentials (a rotated GitLab or Azure DevOps PAT, or a re-installation of the Seal GitHub App), delete the existing installation from the drawer and add it again through the **Import projects** flow on the Projects page. Each Seal Project's connection is tracked by the manifest URL, so the existing projects re-attach automatically when the new installation covers the same repositories.

## Related

* [Connecting GitHub](/discovering/connecting-source-control/github), [Connecting GitLab](/discovering/connecting-source-control/gitlab), [Connecting Azure DevOps](/discovering/connecting-source-control/azure-devops): the original install flows.
* [Source code mode](/discovering/package-discovery-mode/source-code): the discovery mode the connections drive, and what happens to it when the connection stops producing signal.


# Connecting via the Seal CLI in CI

Run the Seal CLI in your CI/CD pipeline so it discovers your packages without source-control access.

When you cannot grant Seal read access to your source code, but the Seal CLI can run inside your CI/CD pipeline, the CLI itself becomes Seal's window into your packages. The Seal Project enters [CLI discovery mode](/discovering/package-discovery-mode/cli) the first time the CLI runs against it.

This chapter is the minimum setup to wire CLI-driven discovery in. The deeper, per-platform CI integration mechanics (GitHub Actions, GitLab CI, Azure DevOps Pipelines, Jenkins, CircleCI, and others) live in [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd).

## Before you start

* A **production** [token](/getting-started/tokens), stored in your CI's secret manager.
* A **Project ID** for the Seal Project. If a project with that Project ID does not exist in your tenant, it is created automatically the first time the CLI runs.
* A CI environment that can install the Seal CLI and reach Seal's servers over HTTPS.

{% hint style="info" %}
**Project ID, not project name.** A Seal Project has two distinct identifiers: a human-readable **name** (mutable, allows spaces, used in the UI) and a machine-readable **Project ID** (immutable, limited to letters, numbers, dots, hyphens, and underscores, used in the API and the CLI). The two are independent. The CLI works against the Project ID; the display name has no effect on a CLI run.
{% endhint %}

## Steps

1. **Install the Seal CLI** in your CI runner. The cross-platform install steps are in [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli).
2. **Configure environment variables** for the pipeline step that runs the CLI:
   * `SEAL_TOKEN`: the production token, pulled from your CI's secret store.
   * `SEAL_PROJECT`: the Seal Project's Project ID.
3. **Run `seal scan`** in the working directory of the project you want to scan:

   ```bash
   seal scan
   ```

   The first run creates the Seal Project (if needed) with the supplied Project ID, and populates it with discovered packages. Subsequent runs with the same `SEAL_PROJECT` value attach to the same project and produce fresh signal.

## Verify

<figure><img src="/files/m2TYUdXYcl4kJHwGEjga" alt="A Projects page row showing the CLI discovery mode badge"><figcaption><p>The Projects page shows "CLI" as the discovery mode after the first CLI run.</p></figcaption></figure>

* On the **Projects** page, your Seal Project appears with **CLI** as its package discovery mode.
* On the **Protection** page's **Vulnerable packages** tab, the packages from your manifest appear as Seal scans them.

## Troubleshooting

**The CLI fails with an authentication error.** Confirm `SEAL_TOKEN` is set in the pipeline step's environment, that the token has not been revoked, and that you are using a production token. Activity authenticated with a development token is filtered out of the Protection page by default, so the scan can succeed but the results may not appear where you expect.

**The Seal Project does not appear on the Projects page.** Either the CLI did not finish (check the pipeline log) or the run authenticated against a different tenant than you are looking at.

**The CLI rejects the value of `SEAL_PROJECT`.** Project IDs are restricted to letters, numbers, dots, hyphens, and underscores (no spaces or other punctuation), and capped at 255 characters. Pick a value that fits the rules.

**Two pipelines are clobbering each other's results.** Both pipelines are running with the same `SEAL_PROJECT` value, so they are writing into the same Seal Project. Give each pipeline its own Project ID. See [Anti-patterns in Creating a Seal Project](/getting-started/creating-a-seal-project#anti-patterns).

## Related

* [CLI mode](/discovering/package-discovery-mode/cli): the discovery mode this chapter sets up.
* [Managing tokens](/getting-started/tokens): production vs development tokens, and what each one is tracked against.
* [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd): the per-platform CI integrations and the broader fix-mode story.


# Configuring the Seal Artifact Server for discovery

Configure your package manager to pull through the Seal Artifact Server so Seal sees what your build uses.

When the Seal CLI cannot run in your build, but your package manager can be pointed at a remote, the Seal Artifact Server is the discovery path. Each authenticated pull is recorded against the Seal Project named in the credentials, and the project enters [artifact server discovery mode](/discovering/package-discovery-mode/artifact-server) the first time a sealed package is pulled for it.

This chapter is the minimum you need to know about how authentication carries the Project ID into a pull. The full per-ecosystem package-manager setup (npm, pip, Maven, Gradle, Go modules, Composer, Bundler, NuGet) lives in [Seal Apps via the Seal Artifact Server](/setup-apps-os/artifact-server).

## Before you start

* A **production** [token](/getting-started/tokens). Per [token security best practices](/getting-started/tokens/best-practices), store it in a secret manager rather than in the package manager configuration on disk.
* The [**Project ID**](/getting-started/creating-a-seal-project#project-id-and-project-name) of the Seal Project you want pulls attributed to. If the project does not exist yet, pre-create it from the **New project** button on the Projects page.
* A package manager that can be pointed at a configurable remote (npm, pip, Maven, Gradle, Go modules, Composer, Bundler, NuGet).

## How the Seal Artifact Server attributes a pull

The Seal Artifact Server has a single tenant-wide URL per ecosystem (for example, one URL for npm, one for pip, one for Maven). The URL is the same for every Seal Project in your tenant. The project context comes from HTTP Basic authentication on each pull:

* **Username:** the Seal Project's Project ID.
* **Password:** the production token.

A single token works across every Seal Project in the tenant; the Project ID in the username determines which project a given pull is attributed to. Different projects pull through the same URL with different usernames.

If the username is empty, the pull is attributed to the [Default project](/getting-started/creating-a-seal-project#the-default-project) instead of a specific Seal Project.

## Steps

1. **Generate (or reuse) a production token.** See [Generating and revoking tokens](/getting-started/tokens/generating-tokens).
2. **Decide which Seal Project will own the pulls.** Reuse an existing project's Project ID, or pre-create a project from the **New project** button.
3. **Configure your package manager** to use the Seal Artifact Server, with the Project ID in the username field and the production token in the password field. The exact configuration syntax for each ecosystem is in [Seal Apps via the Seal Artifact Server](/setup-apps-os/artifact-server).
4. **Run a build that pulls a sealed package.** This is the trigger that switches the Seal Project to artifact server discovery mode.

## Verify

<figure><img src="/files/neIO8TbLSkZGBYpClPC4" alt="A Projects page row showing the Artifact server discovery mode badge"><figcaption><p>The Projects page shows "Artifact server" as the discovery mode once a pull lands.</p></figcaption></figure>

* On the **Projects** page, the Seal Project shows **Artifact server** as its package discovery mode.
* On the **Protection** page's **Vulnerable packages** tab, the sealed packages your build pulled appear in the project's stream.

## Coverage caveats

Artifact server discovery has more visibility caveats than the other modes (the picture depends on whether the Seal Artifact Server is your primary or fallback remote, on how aggressively your CI runners and any internal artifact-server caches cache pulls, and on whether your build still pulls origin versions from public registries). The full discussion is in [Artifact server mode](/discovering/package-discovery-mode/artifact-server#what-it-sees).

## Troubleshooting

**Pulls are landing in the Default project.** The username in your package manager config is empty or wrong. Set it to the Project ID of the Seal Project you want to use.

**The project shows up in CLI mode rather than artifact server mode.** A Seal Project enters CLI mode if the Seal CLI runs against it, regardless of any artifact-server traffic. If the CLI runs for any reason against the same Project ID, the discovery mode upgrades to CLI and subsequent artifact-server signal is dropped. See [Mode changes](/getting-started/creating-a-seal-project#mode-changes).

## Related

* [Artifact server mode](/discovering/package-discovery-mode/artifact-server): what artifact server discovery actually sees, and the configurations that affect coverage.
* [Seal Apps via the Seal Artifact Server](/setup-apps-os/artifact-server): the per-ecosystem package-manager setup.
* [Project ID and project name](/getting-started/creating-a-seal-project#project-id-and-project-name): the Project ID that goes in the username field.


# Importing manifests & SBOMs

One-shot uploads of dependency manifests, SBOMs, and Snyk CSV exports.

The Seal Platform accepts three kinds of one-shot uploads:

* [Uploading a dependency manifest](/discovering/importing-manifests/dependency-manifest): `package-lock.json`, `requirements.txt`, `pom.xml`, and other ecosystem-specific lockfiles.
* [Uploading an SBOM](/discovering/importing-manifests/sbom): CycloneDX or SPDX in JSON.
* [Importing from a Snyk export](/discovering/importing-manifests/snyk-export): a CSV exported from Snyk.

All three go through the same **Import from file** flow on the Projects page. Each upload creates or contributes to one Seal Project, and the project ends up in [imported manifest discovery mode](/discovering/package-discovery-mode/imported-manifest). The upload is a snapshot: the platform parses the file once and does not refresh it, so the picture ages from the moment of import.

## When file imports are the right choice

File imports are the answer when the higher-reliability discovery modes are not available to you. Specifically, when for security or organizational reasons you cannot:

* Connect Seal to your source control,
* Run the Seal CLI in your CI/CD pipeline, **and**
* Configure the Seal Artifact Server as your primary remote so it sees all your build's package pulls.

When at least one of those is available, prefer it. Source code, CLI, and artifact-server-as-primary-remote all give Seal a refreshing picture; imports are a frozen snapshot.

## Before you start

* You have the **Admin**, **Sealer**, or **Collaborator** [role](/getting-started/users-and-sso/user-roles) in Seal.
* You know the file type and have the file accessible. The detector inspects filename and contents, so a file named correctly for its kind is the easiest path.
* Your file is **100 MB or smaller**. This is the maximum supported upload size; a larger file is rejected before the upload starts.
* You have decided whether the upload should create a new Seal Project or attach to the [Default project](/getting-started/creating-a-seal-project#the-default-project).

## The shared flow

1. Open the **Projects** page.
2. Click **Import projects** and select **Import from file**.
3. Drag the file onto the upload area, or click to browse. The modal validates the file and shows the detected type.
4. Choose the destination:
   * **Add entries to a new project** and provide a project name. The platform creates a new Seal Project with that name and assigns its [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name).
   * **Add entries to the Default project** to land the entries in the catch-all instead.
5. Confirm the upload. A progress bar tracks the upload while it runs; large files may take a little longer to finish.

<figure><img src="/files/iR0eyRzmAY7PwQ32F9Ew" alt="The Import from file modal with a selected file and the new-project / Default-project destination radio"><figcaption><p>The unified Import from file modal</p></figcaption></figure>

The Seal Platform parses the file asynchronously after the modal closes; the resulting Seal Project (or new entries in Default) appears on the Projects page within a minute.

## What each upload produces

| Upload              | Result                                                                                |
| ------------------- | ------------------------------------------------------------------------------------- |
| Dependency manifest | One Seal Project (or Default) populated with the packages declared in the manifest.   |
| SBOM                | One Seal Project (or Default) populated with the components listed in the SBOM.       |
| Snyk CSV export     | One Seal Project (or Default) populated with the vulnerable packages from the export. |

## Related

* [Imported manifest mode](/discovering/package-discovery-mode/imported-manifest): the discovery mode an upload puts a Seal Project into.
* [Creating a Seal Project](/getting-started/creating-a-seal-project): the rest of the project-creation paths.


# Uploading a dependency manifest

Upload a dependency manifest like package-lock.json or pom.xml as a one-shot snapshot.

Uploading a dependency manifest gives Seal a one-time view of the packages a build resolves to. The Seal Project lands in [imported manifest discovery mode](/discovering/package-discovery-mode/imported-manifest). The snapshot does not refresh: subsequent commits or builds in the customer's environment do not update it.

## Supported file types

| Ecosystem      | Files                                              |
| -------------- | -------------------------------------------------- |
| npm            | `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` |
| Python         | `requirements.txt`, `Pipfile.lock`                 |
| Go             | `go.mod`                                           |
| Maven          | `pom.xml`                                          |
| .NET           | `*.csproj`                                         |
| PHP (Composer) | `composer.lock`                                    |
| Ruby (Bundler) | `Gemfile.lock`                                     |

`package.json` is **not** accepted. It declares dependencies but does not pin them; only resolved manifests (lockfiles) and `pom.xml` produce a meaningful snapshot.

## Steps

Follow the [shared Import from file flow](/discovering/importing-manifests#the-shared-flow). Drag your manifest file onto the upload area; the detector picks the right parser based on the filename.

## Verify

The new Seal Project appears on the Projects page in **Imported manifest** discovery mode. Discovered packages appear on the Protection page's Vulnerable packages tab as the parser finishes.

## Troubleshooting

**The modal rejects `package.json`.** Upload `package-lock.json` (or `yarn.lock` / `pnpm-lock.yaml`) instead.

**The modal rejects the file outright.** The detector inspects both filename and content. A renamed file (for example, `requirements.txt` saved as `deps.txt`) is rejected. Use the canonical filename.

## Related

* [Importing manifests & SBOMs](/discovering/importing-manifests): the parent overview, including the destination radio and what the upload produces.
* [Imported manifest mode](/discovering/package-discovery-mode/imported-manifest): coverage and refresh behavior.


# Uploading an SBOM

Upload a CycloneDX or SPDX SBOM as a one-shot snapshot of an environment.

Uploading a Software Bill of Materials gives Seal a one-time view of the components in a built environment, without needing access to the source or the build pipeline. The Seal Project lands in [imported manifest discovery mode](/discovering/package-discovery-mode/imported-manifest). The snapshot does not refresh.

SBOM uploads are useful for:

* Assessing a vendor-supplied component you are evaluating.
* Standing up a Seal Project quickly for an environment whose build you do not own.
* Auditing an existing artifact you have a generated SBOM for.

## Supported formats

* **CycloneDX** in JSON, identified by `"bomFormat": "CycloneDX"` in the file.
* **SPDX** in JSON, identified by an `"SPDXID"` field.

XML SBOMs are not accepted. If your tooling produces XML, regenerate or convert to JSON before uploading.

## Steps

Follow the [shared Import from file flow](/discovering/importing-manifests#the-shared-flow). Drag your `.json` SBOM onto the upload area; the detector reads the file's contents to identify the format.

## Verify

The new Seal Project appears on the Projects page in **Imported manifest** discovery mode. Discovered packages appear on the Protection page's Vulnerable packages tab as the parser finishes.

For ongoing remediation of an SBOM-described environment, plan to switch to a higher-reliability discovery mode once you have the access to do so. The SBOM upload is a snapshot; new commits or vulnerabilities discovered after the upload do not refresh it.

## Related

* [Importing manifests & SBOMs](/discovering/importing-manifests): the parent overview.
* [Imported manifest mode](/discovering/package-discovery-mode/imported-manifest): coverage and refresh behavior.


# Importing from a Snyk export

Upload a CSV exported from Snyk to bring its findings into Seal as a one-shot snapshot.

Importing a Snyk CSV gives Seal a one-time view of the vulnerable packages a Snyk environment has identified. The Seal Project lands in [imported manifest discovery mode](/discovering/package-discovery-mode/imported-manifest). The snapshot does not refresh.

This is the path for bringing Snyk-discovered vulnerabilities into Seal. The separate [Snyk integration](/integrations/internal-scanners/snyk) goes the other direction (it lets Seal inform Snyk about the vulnerabilities it has remediated) and does not import findings from Snyk into Seal.

## Generating the export from Snyk

In the Snyk UI, export the project's findings as CSV. The format Seal expects matches Snyk's standard project-level CSV export.

## Steps

Follow the [shared Import from file flow](/discovering/importing-manifests#the-shared-flow). Drag the `.csv` onto the upload area; the detector identifies it by extension and contents.

## Verify

The new Seal Project appears on the Projects page in **Imported manifest** discovery mode. Discovered packages appear on the Protection page's Vulnerable packages tab as the parser finishes.

## Related

* [Importing manifests & SBOMs](/discovering/importing-manifests): the parent overview.
* [Snyk integration](/integrations/internal-scanners/snyk): the live, refreshing alternative to a CSV upload.
* [Imported manifest mode](/discovering/package-discovery-mode/imported-manifest): coverage and refresh behavior.


# The Dashboard

A tenant-wide executive view of vulnerability and remediation metrics, refreshed daily.

The Dashboard is the Seal UI's landing page after sign-in. It aggregates the state of every Seal Project in your tenant into a small set of summary tiles and charts, refreshed once a day. There is no per-project filter on the Dashboard itself; for project-level detail, use the [Protection page](/discovering/protection-page).

<figure><img src="/files/JidOD4wpKmky3T4NBojd" alt="The Seal Dashboard with nine widgets covering vulnerable packages, sealed packages, available fixes, time savings, total projects, vulnerable packages over time, most critical vulnerable packages, and most vulnerable projects"><figcaption><p>The Dashboard</p></figcaption></figure>

## What's on the Dashboard

| Widget                                | What it shows                                                                                                     |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Vulnerable packages**               | Donut chart of vulnerable packages broken down by severity (critical, high, medium, low).                         |
| **Sealed packages**                   | Donut chart of sealed packages broken down by severity.                                                           |
| **Available fixes**                   | Count of vulnerable packages that have a sealed version available but have not been replaced yet.                 |
| **Estimated time saved**              | Engineering hours saved by sealed packages already deployed.                                                      |
| **Predicted time savings**            | Engineering hours that would be saved if every available fix were applied.                                        |
| **Total number of projects**          | Count of active Seal Projects in the tenant. Archived projects are excluded.                                      |
| **Vulnerable packages over time**     | Line chart of vulnerable-package counts by severity, with a range selector for the last quarter or the last year. |
| **Most critical vulnerable packages** | Top vulnerable packages ranked by maximum CVSS score. Columns: package, version, project, vulnerabilities.        |
| **Most vulnerable projects**          | Top 5 Seal Projects ranked by vulnerability severity. Columns: project, owner, vulnerabilities, last seen.        |

## How the numbers are computed

The Dashboard is **tenant-wide aggregate**. Every Seal Project's data is rolled up into the metrics. To break the same numbers down by Seal Project, by package manager, or by team, generate a report from the [Reports Manager](/using-platform/reports-manager).

The metrics are **recomputed once a day** by a scheduled job, not in real time. Activity that lands after the most recent recompute does not appear on the Dashboard until the next run.

Rows hidden on the Protection page are excluded from every Dashboard widget by default.

## Empty states

* **Brand-new tenant, before any scans land.** The Dashboard displays a Welcome view with onboarding suggestions in place of the metric tiles. Once scans complete and the tenant transitions out of the onboarding state, the metric tiles take over.
* **Vulnerable packages over time, with insufficient history.** The line chart needs at least two data points to render. While the platform is still accumulating points, the chart shows "Not enough data yet."
* **Top tables, with no findings.** The Most critical vulnerable packages and Most vulnerable projects tables show empty-state messages when there are no findings to rank.

## Relationship to the ROI report

The Dashboard's **Estimated time saved** and **Predicted time savings** tiles show the headline numbers from the same model as the **ROI report** in the Reports Manager. The two views differ in shape:

* The Dashboard is a single read-only view of tenant-wide aggregates.
* The ROI report can be filtered by Seal Project and by package manager, and exported as CSV or PDF.

For executive snapshots and the at-a-glance posture, the Dashboard is the right view. For finer-grained reporting, generate an ROI report. See [Reports Manager](/using-platform/reports-manager) for the full set of report types.

## Permissions

Every authenticated user in the tenant sees the Dashboard, regardless of role. The data shown is the same for all roles.

## Related

* [The Protection page](/discovering/protection-page): per-Seal-Project detail for the same data.
* [Reports Manager](/using-platform/reports-manager): the ROI report and other report types.
* [If you're a security leader](/introduction/audience-guides/security-leader): how a security leader uses the Dashboard.


# The Protection page

The Seal UI page where you triage vulnerable packages, review what is sealed, manage Sealing Rules, and configure Scanner Exclusions.

The Protection page is the day-to-day workspace for security analysts and engineers. It groups every package and every rule across your tenant into four tabs:

* [Vulnerable packages](/discovering/protection-page/vulnerable-packages-tab): every package Seal has discovered that has at least one open vulnerability.
* [Sealed packages](/discovering/protection-page/sealed-packages-tab): every package that has been replaced with a sealed version, with attestation downloads.
* [Sealing rules](/discovering/protection-page/sealing-rules-tab): the list of remote Sealing Rules in the tenant.
* [Scanner exclusions](/discovering/protection-page/scanner-exclusions-tab): the list of Scanner Exclusions in the tenant. Hidden by default; an Admin enables the feature in Settings.

<figure><img src="/files/W3QjDwg8ca5GlrKtYrqE" alt="The Protection page on the Vulnerable packages tab, showing the tab strip, filter bar, and a populated package table"><figcaption><p>The Protection page</p></figcaption></figure>

The Protection page is **tenant-scoped**: all tabs span every Seal Project unless you filter by Project. There is no separate "per-project" view.

## The drawer

Clicking a row on the Vulnerable packages or Sealed packages tab opens a side drawer with that row's package detail. The drawer is **per-package**: it shows everything Seal knows about, say, `ejs@2.7.4`, including the full list of vulnerabilities affecting that package version, the matching sealed version (when one exists), the [code diff](/trust/code-diff), and links to relevant Sealing Rules. If the package has multiple CVEs, they all appear together in the drawer.

## Empty state

Until your tenant has accumulated scan data, the Protection page shows the [Welcome cards](/getting-started/onboarding-wizard#the-welcome-cards-on-the-protection-page) in place of the regular tabs.

## Related

* [Package states](/discovering/package-states): the canonical reference for the six values shown in the Vulnerable packages tab's state column.
* [The package drawer](/discovering/package-drawer): the per-vulnerability content shown inside the drawer.
* [Sealing Rules](/using-platform/sealing-rules): the deeper concept-and-how-to home for the Sealing rules tab.
* [Scanner Exclusions](/using-platform/scanner-exclusions): the deeper home for the Scanner exclusions tab.


# The Vulnerable packages tab

Reference for the columns, filters, and per-row actions on the Vulnerable packages tab.

Every package Seal has discovered with at least one open vulnerability appears in this tab. It is the day-to-day triage view.

<figure><img src="/files/P4fbtBd77wCU0dYKYYw0" alt="The Vulnerable packages tab with rows showing varied state badges and severity chips"><figcaption><p>The Vulnerable packages tab is the day-to-day triage view.</p></figcaption></figure>

## Columns

| Column              | Contents                                                                                  |
| ------------------- | ----------------------------------------------------------------------------------------- |
| **Package**         | The package name (for example, `ejs`, `commons-text`, `requests`).                        |
| **Version**         | The specific package version Seal has discovered (for example, `2.7.4`).                  |
| **Ecosystem**       | The package's ecosystem (for example, npm, Maven, PyPi).                                  |
| **Project**         | The Seal Project this row belongs to.                                                     |
| **Vulnerabilities** | The vulnerabilities affecting this package, with severity.                                |
| **Last seen**       | The most recent time Seal saw this package, whichever discovery mode produced the signal. |

Each row also has a state badge (Sealed, Pending deploy, Ready to seal, Version in progress, Generate available, or Unfixable) and an actions menu. The state badge values are documented in [Package states](/discovering/package-states).

The default sort is by **severity, descending** (most severe rows at the top). All columns marked above are sortable.

## Filters

<figure><img src="/files/aMiQcYHjzvjI08KwpT3K" alt="The Vulnerable packages tab filter bar with the Availability filter open"><figcaption><p>The filter bar with the Availability dropdown open.</p></figcaption></figure>

| Filter                | What it narrows                                                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Search**            | Free-text search across package names and CVE identifiers.                                                                            |
| **Ecosystem**         | Show only one ecosystem at a time.                                                                                                    |
| **Project**           | Show only rows from one Seal Project.                                                                                                 |
| **Availability**      | Show rows in a specific package state (Sealed, Pending deploy, Ready to seal, Generate available, and so on).                         |
| **Visibility**        | Show all rows, only visible rows, or only hidden rows.                                                                                |
| **Development token** | Filter rows by the type of [token](/getting-started/tokens) that authenticated the activity. Default: production-token activity only. |
| **Dev dependency**    | Include or exclude [development dependencies](/introduction/glossary#dev-dependency). Default: excluded.                              |

The two filters narrow the default view in different ways and are independent: a row excluded by one is not necessarily excluded by the other.

## Per-row actions

<figure><img src="/files/LG1fXcoqcfVSrHXnYfsb" alt="A row with the per-row action menu open"><figcaption><p>The per-row action menu, with "Seal in all projects" among the entries.</p></figcaption></figure>

The actions available depend on your role.

| Action                                                                                                                             | Roles                       |
| ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
| **Seal** (the primary button on a row that has a sealed version available; creates a Sealing Rule using the safest sealed version) | Admin, Sealer               |
| **Seal in all projects** (apply the rule across every project where this package and version appear)                               | Admin, Sealer               |
| **Generate fix** (the action behind the **Generate available** state)                                                              | Admin, Sealer, Collaborator |
| **Hide** / **Restore** (toggle the row's visibility; hidden rows are excluded from the Dashboard and from reports by default)      | Admin, Sealer, Collaborator |

A **Download report** action above the table exports the current filtered set as a Vulnerable Packages report. See [Reports Manager](/using-platform/reports-manager).

## Related

* [Package states](/discovering/package-states): the meaning of each state badge and the transitions between them.
* [Triggering Generate fix](/discovering/generate-fix): the action behind the Generate available state.
* [Sealing Rules](/using-platform/sealing-rules): what the **Seal** button creates.


# The Sealed packages tab

Reference for the columns, filters, and per-row actions on the Sealed packages tab.

Every package that has been replaced with a sealed version in your environment appears here, with a row per Seal Project that has pulled the sealed version at least once. Use this tab to verify that remediation is taking hold and to download the attestations you need for audit.

<figure><img src="/files/uaXBZ5C0wxToYc3ls5ee" alt="The Sealed packages tab populated with rows"><figcaption><p>The Sealed packages tab shows one row per Seal Project that has pulled each sealed package.</p></figcaption></figure>

## Columns

| Column              | Contents                                                                                                    |
| ------------------- | ----------------------------------------------------------------------------------------------------------- |
| **Package**         | The package name.                                                                                           |
| **Version**         | The sealed version in use (for example, `2.7.4-sp1`).                                                       |
| **Ecosystem**       | The package's ecosystem.                                                                                    |
| **Project**         | The Seal Project this row belongs to.                                                                       |
| **Vulnerabilities** | The vulnerabilities the sealed version remediates.                                                          |
| **Last seen**       | The most recent time Seal saw this sealed package being used, whichever discovery mode produced the signal. |

The default sort is by **severity, descending**.

## Filters

The same filters as the [Vulnerable packages tab](/discovering/protection-page/vulnerable-packages-tab#filters), minus the Availability filter (since every row here is in the Sealed state).

## Per-row actions

| Action                                                                      | Roles                       |
| --------------------------------------------------------------------------- | --------------------------- |
| **Hide** / **Restore** (toggle the row's visibility)                        | Admin, Sealer, Collaborator |
| **Download attestation** (the human-readable PDF for this row)              | Any authenticated user      |
| **Download VEX attestation** (the machine-readable VEX record for this row) | Any authenticated user      |

## Bulk downloads

<figure><img src="/files/bWcnzXbxgnTfIUgHXFH9" alt="The bulk downloads menu expanded above the Sealed packages table"><figcaption><p>The bulk downloads menu offers combined attestation and VEX downloads for the current filtered set.</p></figcaption></figure>

Above the table, a download menu offers two bulk actions that operate on the current filtered set:

* **Download all attestations**: a single PDF that combines the attestations for every row in the filtered set.
* **Download all VEX attestations**: a single JSON file that combines every row's VEX record.

A separate **Download report** action exports the filtered set as a Sealed Packages report. See [Reports Manager](/using-platform/reports-manager).

## Related

* [Attestations](/trust/attestations): the canonical home for both attestation formats.
* [Sealed package](/introduction/seal-approach/sealed-packages): the concept behind every row in this tab.


# The Sealing rules tab

Reference for the list view of remote Sealing Rules.

The Sealing rules tab lists every remote Sealing Rule in your tenant. Local Sealing Rules (rules in `.seal-actions.yml` files in your repositories) are not shown here; they live in source control instead.

The full concept-and-how-to home for Sealing Rules is in [Sealing Rules](/using-platform/sealing-rules). This page is the field reference for the list view.

<figure><img src="/files/GcEqdXFeHXDXqWuhBBFQ" alt="The Sealing rules tab showing tenant-wide and project-specific rules"><figcaption><p>Tenant-wide rules carry a scope icon; project-specific rules do not.</p></figcaption></figure>

## Columns

| Column                            | Contents                                                                                                                                |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| *(scope indicator)*               | An icon that marks the rule as **tenant-wide** (applies to every Seal Project in the tenant). Project-specific rules show no icon.      |
| **Project**                       | The Seal Project the rule applies to, or "All projects" for tenant-wide rules.                                                          |
| **Vulnerable package to replace** | The origin package and version the rule targets.                                                                                        |
| **Substitute package**            | The package the rule replaces it with (different from the origin package only when [renaming](/integrations/package-renaming) applies). |
| **Substitute version**            | The sealed version the rule replaces it with.                                                                                           |
| **User**                          | The user who created the rule.                                                                                                          |
| **Creation time**                 | When the rule was created.                                                                                                              |

The default sort is by **creation time, descending** (newest rules at the top).

## Filters

* **Search**: free-text search across package names.
* **Project**: show only rules for a single Seal Project, or rules that apply to all projects. The picker lists only projects that can take a remote Sealing Rule (those on the **Remote** deployment method, plus connected projects whose deployment method is not yet determined). Projects on the **Local**, **Automatic Remediation**, **Artifact Server**, or **Manual** deployment method do not appear.

## Per-row actions

| Action          | Roles         |
| --------------- | ------------- |
| **Edit rule**   | Admin, Sealer |
| **Delete rule** | Admin, Sealer |

A **New rule** button in the tab header opens an inline editable row for creating a rule from scratch. See [Creating a Sealing Rule](/using-platform/sealing-rules#creating-a-sealing-rule) for the create flow.

## Related

* [Sealing Rules](/using-platform/sealing-rules): the canonical home for the concept, the create flow, and the local-vs-remote split.


# The Scanner exclusions tab

Reference for the list view of Scanner Exclusions, the false-positive workaround.

A **Scanner Exclusion** is a rule that tells Seal to [rename](/integrations/package-renaming) a particular package and version in your build so that external scanners stop flagging it as vulnerable. The mechanic is the same as for renaming applied to sealed packages: scanners look up vulnerabilities by package name, and a renamed package has no entries in their databases, so the alert stops.

Scanner Exclusions are aimed at false positives that come from scanners other people run on your output: most often your customers' scanners on the artifacts you ship to them. Those alerts can drive significant pressure to "upgrade" packages that are not actually vulnerable (the underlying CVE was retracted, the affected-version range is wrong, the vulnerable code never compiles into the package, and so on).

Scanner Exclusions are applied by the Seal CLI when it runs in your CI/CD pipeline, the same way Sealing Rules are. A deployment method that does not run the CLI in CI (Artifact Server, Manual) cannot apply Scanner Exclusions.

The feature is hidden until an Admin enables it from Settings. Once enabled, the Scanner exclusions tab and the related actions appear across the platform.

The full concept-and-how-to home for Scanner Exclusions is in [Scanner Exclusions](/using-platform/scanner-exclusions). This page is just the field reference for the list view.

<figure><img src="/files/TqTtyfRBWDVUYOUTvg7u" alt="The Scanner exclusions tab populated with rows and a row menu open"><figcaption><p>The Scanner exclusions tab with tenant-wide and project-specific rules and an Edit/Delete row menu open.</p></figcaption></figure>

## Columns

| Column              | Contents                                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| *(scope indicator)* | An icon that marks the exclusion as **tenant-wide** (applies to every Seal Project). Project-specific exclusions show no icon. |
| **Package**         | The package the exclusion targets.                                                                                             |
| **Ecosystem**       | The package's ecosystem.                                                                                                       |
| **Version**         | The version the exclusion applies to.                                                                                          |
| **Project**         | The Seal Project the exclusion applies to, or "All projects" for tenant-wide exclusions.                                       |
| **User**            | The user who created the exclusion.                                                                                            |
| **Last updated**    | When the exclusion was last modified.                                                                                          |

The default sort is by **creation time, descending**.

## Filters

* **Search**: free-text search across package names.
* **Project**: show only exclusions for a single Seal Project, or exclusions that apply to all projects. The picker lists only projects that can take a remote Sealing Rule (those on the **Remote** deployment method, plus connected projects whose deployment method is not yet determined). Projects on the **Local**, **Automatic Remediation**, **Artifact Server**, or **Manual** deployment method do not appear.

## Per-row actions

| Action          | Roles         |
| --------------- | ------------- |
| **Edit rule**   | Admin, Sealer |
| **Delete rule** | Admin, Sealer |

## Related

* [Scanner Exclusions](/using-platform/scanner-exclusions): the canonical home for the concept, the create flow, and the comparison with [package renaming](/integrations/package-renaming).


# Package states

The six package states a vulnerable package can be in, how they transition, and what to do for each.

Every vulnerable package on the [Vulnerable packages tab](/discovering/protection-page/vulnerable-packages-tab) is in exactly one of six **package states**. The state captures where the package sits in its remediation lifecycle: whether a sealed version exists, whether you have asked Seal to build one, whether you have created a Sealing Rule, whether the CLI has applied it, and whether Seal can fix it at all.

| State                   | Meaning                                                                                              |
| ----------------------- | ---------------------------------------------------------------------------------------------------- |
| **Generate available**  | No sealed version exists yet for this package and version. Seal can attempt to build one on request. |
| **Version in progress** | Seal is actively building a sealed version.                                                          |
| **Ready to seal**       | A sealed version exists; no Sealing Rule has been created yet.                                       |
| **Pending deploy**      | A Sealing Rule exists, the Seal CLI runs in CI, and the next CLI run will replace the package.       |
| **Sealed**              | The sealed version is in use.                                                                        |
| **Unfixable**           | Seal cannot build a sealed version for this package.                                                 |

## State machine

The typical path is **Generate available → Version in progress → Ready to seal → Pending deploy → Sealed**, but there are variations driven by the deployment method and by whether matching Sealing Rules already exist when Seal finishes a build.

```mermaid
graph TD
  GA[Generate available] -->|Generate fix| VP[Version in progress]
  VP -->|build fails| U[Unfixable]
  VP -->|build succeeds| RTS[Ready to seal]
  VP -->|matching rule exists or Automatic Remediation| PD[Pending deploy]
  RTS -->|create a Sealing Rule| PD
  RTS -->|Artifact Server pull| S[Sealed]
  PD -->|next CLI run| S
```

A newly discovered vulnerable package usually starts in **Generate available**, but it can start in **Ready to seal** (if Seal already has a sealed version in its catalog), **Unfixable** (if Seal has already determined no fix is possible), **Version in progress** (if Seal is already mid-build), or **Sealed** (if your build is already pulling a sealed version).

<figure><img src="/files/nHQHhTL4Lbtyy5sOaoFN" alt="Vulnerable packages tab rows showing all six state badges"><figcaption><p>The six package states as they appear on the Vulnerable packages tab.</p></figcaption></figure>

## The states in detail

### Generate available

No sealed version exists for this package and version, and the package is in a Seal-supported ecosystem. The row's primary action is **Generate fix**.

Clicking **Generate fix** queues a backend build and moves the package to **Version in progress**. See [Triggering Generate fix](/discovering/generate-fix).

### Version in progress

Seal is actively building a sealed version. The build typically takes **24-72 hours**. While it runs, the row shows a progress indicator instead of an action button.

When the build finishes, the package moves to **Ready to seal** (success) or, when a Sealing Rule already targets the package or the Seal Project uses the Automatic Remediation deployment method, directly to **Pending deploy**. If the build fails, the package moves to **Unfixable**, which is rare.

### Ready to seal

A sealed version exists, but no Sealing Rule applies to the package yet. What you do next depends on your deployment method.

| Deployment method   | Action                                                                                                                                                  | What happens to the state                                                                                  |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| **Remote**          | Click **Seal** for a project-specific Sealing Rule, or **Seal in all projects** in the per-row menu for a tenant-wide rule.                             | Changes immediately to **Pending deploy**.                                                                 |
| **Local**           | Add a local Sealing Rule to the project's `.seal-actions.yml` file. If source control is connected, you can open a pull request from the Projects page. | Changes to **Pending deploy** once source control is connected and a scan picks up the change.             |
| **Artifact Server** | Pin the sealed version in your dependency manifest and run your CI.                                                                                     | Stays as **Ready to seal** until your build pulls the sealed version, then changes directly to **Sealed**. |
| **Manual**          | Download the sealed package from the Repository page and use it however you use packages today.                                                         | Stays as **Ready to seal**. Seal has no signal that you applied the package.                               |

### Pending deploy

A Sealing Rule exists for the package, the Seal Project's deployment method runs the CLI in CI (Remote, Local, or Automatic Remediation), and the next CLI run will replace the vulnerable package with the sealed version. The package is in **Pending deploy** by definition only while a CLI-driven CI run is the next step.

The package moves to **Sealed** after the next CLI run. If the Sealing Rule is deleted before the run, the package returns to **Ready to seal**.

The Artifact Server and Manual deployment methods do not run the CLI in CI, so packages in those projects bypass Pending deploy entirely.

### Sealed

Seal has confirmed that the sealed version is in use. The package keeps appearing on the Vulnerable packages tab (the underlying origin version is still vulnerable), but the badge confirms your build is using the sealed counterpart. The same package also appears on the [Sealed packages tab](/discovering/protection-page/sealed-packages-tab), with attestation downloads.

If a new vulnerability is later discovered in the sealed version itself, the original package stays in **Sealed**. The sealed version appears as its own row on the Vulnerable packages tab with its own action button. If the original Sealing Rule targets the safest sealed version (not pinned to a specific one), the row automatically promotes to **Pending deploy** when Seal releases the next sealed version of the package; otherwise you create a Sealing Rule for the new sealed version explicitly.

### Unfixable

Seal cannot build a sealed version for this package. The reasons:

* **The package is malicious.** Malicious packages have no sealed counterpart by definition. The Vulnerable packages tab marks them with a red **Malicious** badge in the action column, with a tooltip telling you to remove the package from your code.
* **A Generate fix build failed.** Rare. Contact your Seal account team; they can look at the specific build log and either retry, fix the underlying patch, or confirm the package needs another remediation path.
* **There is no fix that preserves compatibility.** Seal does not build sealed versions when the only available fix is a breaking change. A [private version](/introduction/seal-approach/sealed-packages#private-versions) may be available; ask your Seal account team.

## Filter labels

<figure><img src="/files/dN2o5X5dV3YZqSUsDyxI" alt="The Availability filter dropdown expanded with all six labels"><figcaption><p>The Availability filter's display labels for each of the six package states.</p></figcaption></figure>

The Vulnerable packages tab's **Availability** filter uses slightly different display labels for the same six states: "Already sealed" (Sealed), "Fix available" (Ready to seal), "Fix in preparation" (Version in progress), "Generate fix" (Generate available), "Pending deploy" (Pending deploy), and "Fix not available" (Unfixable).

## Related

* [The Vulnerable packages tab](/discovering/protection-page/vulnerable-packages-tab): where states are displayed.
* [Triggering Generate fix](/discovering/generate-fix): the action that drives Generate available packages into Version in progress.
* [Sealing Rules](/using-platform/sealing-rules): what creating a rule does.


# Triggering Generate fix

Request a sealed version on demand for a vulnerable package in the Generate available state.

**Generate fix** is the action that asks Seal to build a sealed version of a specific package and version on demand. It is the path out of the [Generate available](/discovering/package-states#generate-available) state: until you trigger it, the row sits there waiting.

## Before you start

* You have the **Admin**, **Sealer**, or **Collaborator** [role](/getting-started/users-and-sso/user-roles). Watchers cannot trigger Generate fix.
* The package is in the **Generate available** state on the [Vulnerable packages tab](/discovering/protection-page/vulnerable-packages-tab). If the row is **Unfixable** instead, Generate fix has already been determined to not apply (see the [Unfixable section](/discovering/package-states#unfixable) for why).

{% hint style="info" %}
**Generate fix counts against your package quota.** Each Generate fix request commits Seal to backporting, building, and testing a sealed version, and the resulting package is recorded against your tenant's package usage on the [Usage page](/using-platform/usage-page), regardless of whether you go on to deploy it.
{% endhint %}

## Steps

<figure><img src="/files/bJK9FOzDhsrfsfgy0NDx" alt="Vulnerable packages tab with the Availability filter open and a Generate fix button on a row"><figcaption><p>Filter by Availability > Generate fix to find candidates; the Generate fix button sits in the row's action column.</p></figcaption></figure>

1. Open the **Protection** page and the **Vulnerable packages** tab.
2. Find the package you want a sealed version for. Filter by **Availability > Generate fix** to narrow to just the candidates.
3. Click **Generate fix** in the row's action column.
4. Confirm the dialog: **"Are you sure you want to request a sealed version for `<package>` version `<version>`?"**

The package's state changes to **Version in progress** immediately. A toast confirms the build was queued.

## What happens next

<figure><img src="/files/pSkEwiGG8SdKZzhUbCvZ" alt="A row in the Version in progress state with a progress indicator"><figcaption><p>The row immediately switches to Version in progress with a progress indicator while the sealed version is being built.</p></figcaption></figure>

A typical Generate fix build takes **24-72 hours**. While it runs, the row shows a progress indicator instead of the action button. When the build finishes, the state changes to:

* **Ready to seal** if the build succeeded. The sealed version is now in Seal's catalog.
* **Pending deploy** if the build succeeded **and** a matching Sealing Rule already exists, or **and** the Seal Project uses the Automatic Remediation deployment method. The next CLI run will apply the fix.
* **Unfixable** if the build failed. This is rare. See [Unfixable](/discovering/package-states#unfixable) for the reasons.

Once a sealed version is in the catalog, it is available across your tenant. Other Seal Projects that contain the same vulnerable package and version pick it up: their rows move from Generate available to Ready to seal as Seal next reconciles the discovery signal.

## Troubleshooting

**The Generate fix button is disabled.** Either the package is already in the **Unfixable** state (the tooltip on the disabled button says *"There is no feasible fix at the moment"*), or your role does not include the GENERATE\_FIX permission.

**The Generate fix button is missing entirely.** The package has been flagged as malicious. The action column shows a red **Malicious** badge instead. Malicious packages have no sealed counterpart; remove the package from your dependencies.

**The build has been running for more than 72 hours.** Contact your Seal account team. They can check the build's progress and either explain the delay or escalate.

**The state moved to Unfixable.** A Generate fix build failure is rare. See [Unfixable](/discovering/package-states#unfixable) for the three reasons a row can land there and what to do for each.

## Related

* [Package states](/discovering/package-states): the canonical reference for the six states, including the transitions Generate fix drives.
* [The Vulnerable packages tab](/discovering/protection-page/vulnerable-packages-tab): where Generate fix is triggered.
* [Sealing Rules](/using-platform/sealing-rules): the next step after a successful Generate fix in the Remote and Local deployment methods.


# The package drawer

What the Protection page drawer shows for a discovered package.

When you click a package on the [Vulnerable packages tab](/discovering/protection-page/vulnerable-packages-tab) or [Sealed packages tab](/discovering/protection-page/sealed-packages-tab), a drawer opens with the package's detail. The drawer is where you see why a package is flagged and what Seal can do about it.

The drawer is organized into three tabs:

* **Package info**: top-level metadata for the package version (name, version, ecosystem, project, last seen).
* **Vulnerabilities**: the list of vulnerabilities affecting the package version.
* **Package diff** (only when a sealed version exists): the per-vulnerability [code diff](/trust/code-diff) between the sealed version and its origin version.

The drawer's footer shows a **Generate fix** button when the package is in the [Generate available](/discovering/package-states#generate-available) state. See [Triggering Generate fix](/discovering/generate-fix) for what that does.

<figure><img src="/files/NdGRfWO25laH1kKZdHS3" alt="The Protection page drawer expanded on a package, on the Vulnerabilities tab"><figcaption><p>The drawer's Vulnerabilities tab</p></figcaption></figure>

## The Vulnerabilities tab

The Vulnerabilities tab lists every vulnerability affecting the package version, split into two groups side by side:

* **Sealed**: vulnerabilities Seal has remediated in the current sealed version. These are gone in the sealed counterpart of the origin version.
* **Open**: vulnerabilities that remain.

Each group is headed with its own count, **Sealed vulnerabilities (N)** beside **Open vulnerabilities (N)**, and the cards at the top of the tab repeat the two totals as **Sealed** and **Open**.

Some published packages contain other packages compiled into the same artifact: a Java fat JAR that bundles several smaller packages into one file, a statically-linked C/C++ package, or any other case where one distributed artifact actually includes the code of separate dependencies. Vulnerabilities that originate in those bundled packages rather than in the host package's own code are grouped together under an **Embedded package - `<name>` version `<version>`** indicator, with a count of how many vulnerabilities came from that embedded package. The drawer does not show regular transitive dependencies under this indicator: those appear as their own rows on the Vulnerable packages tab, with their own drawers, because each one is its own distributable artifact.

Each vulnerability shows the same fields:

| Field             | Contents                                                                                                                                                                                                                |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Identifier**    | The CVE, GHSA, Snyk ID, or other reference. Malicious-package warnings are flagged as such instead of by CVE.                                                                                                           |
| **CVSS score**    | A numeric score, or **N/A** when no source has published a score.                                                                                                                                                       |
| **Severity**      | Derived from the CVSS score: **Critical** for 9.0 or higher, **High** for 7.0-8.9, **Medium** for 4.0-6.9, **Low** below 4.0. Vulnerabilities with no score are treated as Low. Malicious packages are always Critical. |
| **KEV badge**     | Marks vulnerabilities included in the CISA Known Exploited Vulnerabilities catalog.                                                                                                                                     |
| **Status**        | Sealed or open, matching the group the vulnerability is listed under.                                                                                                                                                   |
| **Advisory link** | One link to an upstream advisory, routed by the identifier shown: cve.org for CVEs, github.com/advisories for GHSAs, snyk.io for Snyk IDs, osv.dev for malicious-package records.                                       |

### How the CVSS score is chosen

A vulnerability often appears in multiple databases (the National Vulnerability Database, GitHub Advisories, Snyk, Red Hat's CSAF feed) with potentially different CVSS scores. Seal does not pick one feed and ignore the rest. Instead, the score the drawer shows is the **highest** of the scores the available feeds have published for that vulnerability. If no feed has published a score, the field is empty and the vulnerability is treated as Low severity. Malicious packages are scored 10.

### Package-level versus vulnerability-level severity

The Vulnerable packages tab's **Vulnerabilities** column on the row shows a single severity for the whole package. That value is the **maximum** severity across the package's open vulnerabilities. A package with one critical vulnerability and four low ones shows as critical on the row even though most of its vulnerabilities are low. Open the drawer to see the breakdown.

A package's risk is set by the worst vulnerability it carries. A single open critical vulnerability is enough to make the whole package critical to remediate; how many lower-severity vulnerabilities sit alongside it does not change that. An average or a count would understate the urgency of the worst case, which is the part you actually have to act on. Sealed vulnerabilities are excluded because they are no longer in the package: Seal's backport patched them out of the sealed version, so they are not part of the risk profile of the version actually in use.

### Identifiers when a CVE is missing

Not every vulnerability has a CVE assigned. When the identifier in the drawer is not a CVE, Seal uses the next one available, in priority order:

1. **CVE** (`CVE-YYYY-NNNNN`).
2. **Snyk ID** (`SNYK-...`).
3. **GitHub Security Advisory** (`GHSA-...`).
4. Any other vendor-assigned identifier.

Malicious packages are flagged separately and labeled as such.

## The Package diff tab

When a sealed version exists, the **Package diff** tab shows the [code diff](/trust/code-diff) between the sealed version and its origin version. You can pick one vulnerability inside the tab and see the diff for that vulnerability alone, rather than the whole-package change set.

The diff covers every change Seal made to remediate the vulnerability: the patch itself, plus the dedicated tests Seal added to confirm the patch is effective. The tests are backported alongside the patch so the proof of remediation lives in the same artifact.

## Related

* [The Protection page](/discovering/protection-page): the parent page that hosts the drawer.
* [Triggering Generate fix](/discovering/generate-fix): the action behind the **Generate fix** button in the drawer footer.
* [Code diff](/trust/code-diff): the canonical home for the per-vulnerability patch view.
* [Partial fixes & open vulnerabilities](/discovering/partial-fixes): why some vulnerabilities may show as open in the drawer even after a sealed version is in use.


# The Repository page

Where to find sealed packages for manual download, get shareable code diffs, and run an assessment of an arbitrary dependency set.

The Repository page lives at [`https://app.sealsecurity.io/repository/packages`](https://app.sealsecurity.io/repository/packages) and is reachable from the **Repository** entry in the Seal UI's sidebar.

If you are signed in, you use it to:

1. **Find a sealed package and download it** for the [Manual deployment method](/setup-apps-os/choosing-deployment-method). The catalog lists every sealed package Seal has built; each one's detail page has the artifact download. See [Browsing sealed packages](/discovering/repository-page/sealed-packages).
2. **Get a public link to a code diff** so that an auditor or a downstream customer can verify a remediation themselves. Each sealed package's per-vulnerability diff has a **Share** button; the resulting link works without authentication.
3. **Run a Seal Assessment** when you are considering expanding Seal's scope inside your organization. The Seal Assessment tab takes a dependency manifest, lockfile, or SBOM and shows you which of its packages have sealed versions available, scoped to your tenant.

If you are not signed in, you can also run a **Free Assessment**: an upload-and-check flow open to anyone with no registration. It is reachable via the **Scan my dependencies** button on the Packages tab, and the upload URL is [`https://app.sealsecurity.io/repository/packages/upload`](https://app.sealsecurity.io/repository/packages/upload). The Free Assessment lets a prospect run an assessment without creating an account, and lets a customer share that same URL with a peer at another company who is interested in Seal. See [Free assessment](/discovering/repository-page/free-assessment).

<figure><img src="/files/hRIXOoeuR5lAI7GSpMuR" alt="The public Repository page showing the sealed-package card grid and the Scan my dependencies button"><figcaption><p>The Repository page</p></figcaption></figure>

## Related

* [Browsing sealed packages](/discovering/repository-page/sealed-packages): how to navigate the catalog and the per-package detail.
* [Free assessment](/discovering/repository-page/free-assessment): the upload-and-check flow open to anyone.
* [Code diff](/trust/code-diff): what is in the diff and how the public Share link works.


# Browsing sealed packages

Browse the public catalog of sealed packages, with search, per-package detail, and a shareable code diff.

The public catalog at [`https://app.sealsecurity.io/repository/packages`](https://app.sealsecurity.io/repository/packages) lists every sealed package Seal has built. Browsing requires no account.

## The grid

<figure><img src="/files/hRIXOoeuR5lAI7GSpMuR" alt="The public sealed packages catalog grid with the filter sidebar"><figcaption><p>The public catalog of sealed packages, with cards showing ecosystem, version, and severity chips.</p></figcaption></figure>

Each sealed package is a card in an infinite-scroll grid. Each card shows the package name with the ecosystem icon, the package version, and vulnerability chips color-coded by severity that summarize the vulnerabilities the sealed version remediates relative to its origin version.

A search-and-filter sidebar narrows the grid by package name or CVE, by version (prefix match), and by ecosystem.

## Per-package detail

<figure><img src="/files/yvfK5RvMYEpxbJfQ6EFa" alt="A per-package detail page with the code-diff side drawer and Share button"><figcaption><p>The per-package detail page shows Vulnerabilities and Hashes tabs; the code-diff drawer has a Share button that copies a public link.</p></figcaption></figure>

Clicking a card opens a detail page for that exact `package@version` combination. The detail page has two tabs:

* **Vulnerabilities**: the table of vulnerabilities affecting the origin version, with severity, status (sealed by Seal or open), and links to the upstream advisory. The same model as the [The package drawer](/discovering/package-drawer) drawer in your tenant, just for the public catalog.
* **Hashes**: the cryptographic hashes of the sealed artifacts (the JAR, wheel, tarball, etc.) for verification.

A side drawer on the same page shows the per-vulnerability [code diff](/trust/code-diff) between the sealed version and its origin version. The diff covers every change Seal made to remediate the vulnerability: the patch itself, plus the dedicated tests Seal added to confirm the patch is effective. The tests are backported alongside the patch so the proof of remediation lives in the same artifact.

## Sharing a code diff

The code-diff drawer has a **Share** button that copies a public link to the same diff. The link works without authentication; you can paste it into an email, a ticket, or a chat without granting access to anything else in your tenant.

The two common reasons to share a diff:

* An auditor wants to verify that a specific vulnerability was actually addressed in code, not just label-changed.
* A downstream customer wants to verify that the package shipped in your product no longer carries the vulnerability they flagged.

The shared link points at a real, public, verifiable artifact: the patch and its tests. There is no need to share screenshots, internal tooling outputs, or paraphrased descriptions.

## Related

* [The package drawer](/discovering/package-drawer): the per-vulnerability content equivalent inside an authenticated tenant.
* [Code diff](/trust/code-diff): the canonical home for what the side drawer shows.
* [Free assessment](/discovering/repository-page/free-assessment): upload your manifest and get back the sealed-coverage answer for every package in it.


# Free assessment

Upload a manifest or SBOM at the public URL and see which of its packages have sealed versions.

The **free assessment** is a public upload flow on the Repository page. You give it a dependency manifest, lockfile, or SBOM; Seal parses it; and the results page tells you which of the packages in your file have sealed versions available, with severity counts. No sign-in required.

The upload URL is [`https://app.sealsecurity.io/repository/packages/upload`](https://app.sealsecurity.io/repository/packages/upload). It is a public link, suitable to share with a colleague or to send to a prospect who wants a quick read on whether Seal would fix anything in their stack.

## Steps

<figure><img src="/files/SQr6hGiEqLvTFSnpw1PS" alt="The free assessment public upload page with the drag-drop area"><figcaption><p>The public upload page accepts a manifest, lockfile, or SBOM by drag-and-drop or browse.</p></figcaption></figure>

1. Open the upload URL.
2. Drag your file onto the upload area, or click to browse.
3. Wait for the file to be parsed. You land on the results page.

## Supported file types

The free assessment accepts the same formats as the [in-tenant Import from file flow](/discovering/importing-manifests):

* **Dependency manifests and lockfiles**: `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `requirements.txt`, `Pipfile.lock`, `*.csproj`, `go.mod`, `composer.lock`, `Gemfile.lock`.
* **SBOMs**: CycloneDX or SPDX, in JSON.
* **Snyk CSV exports**.

`package.json` is not accepted; use `package-lock.json` or another lockfile that pins resolved versions.

## The results page

<figure><img src="/files/TcYKzXeAo7GjJtLm12JT" alt="The free assessment results table with Fix available badges"><figcaption><p>The results table marks each row for which Seal has a sealed version with a Fix available badge.</p></figcaption></figure>

After upload, you land on a results table. Each row is one package from the uploaded file, with:

| Column              | Contents                                                            |
| ------------------- | ------------------------------------------------------------------- |
| **Package**         | The package name.                                                   |
| **Version**         | The version pinned in the file.                                     |
| **Vulnerabilities** | The vulnerabilities affecting the package, color-coded by severity. |
| **Ecosystem**       | The package's ecosystem.                                            |
| **Fix available**   | A badge marking rows for which Seal has a sealed version ready.     |

Above the table:

* **Download** the results as CSV.
* **New file upload** to start over with a different file.
* A search box for filtering the table by package name or CVE.

The results page does not require an account; the same anonymous URL works.

## After the assessment

A free assessment is a snapshot. To bring the same picture into a Seal tenant for ongoing remediation, see [Importing manifests & SBOMs](/discovering/importing-manifests), which uses the same file types but lands the data in a Seal Project under your tenant.

## Related

* [The Repository page](/discovering/repository-page): the parent page.
* [Importing manifests & SBOMs](/discovering/importing-manifests): the in-tenant equivalent that creates a Seal Project from the upload.
* [Imported manifest mode](/discovering/package-discovery-mode/imported-manifest): the discovery mode an in-tenant import lands a project in.


# Partial fixes & open vulnerabilities

Why a sealed package may still carry open vulnerabilities, and what to do about each kind.

A sealed package is a drop-in replacement for an origin version with security fixes backported in. "Backported" sometimes means "every vulnerability the origin version had is gone" but not always: a sealed version may still list **open vulnerabilities** in the [Vulnerabilities tab of the drawer](/discovering/package-drawer#the-vulnerabilities-tab). When that happens, the package is **partially fixed**.

There are three reasons a sealed version may carry an open vulnerability, plus a related case where a vulnerability you expected to see does not appear at all. The first two are routine; partial fixes for those reasons are still worth deploying. The third needs a separate conversation.

## 1. The vulnerability is medium or low severity

By default, Seal builds sealed versions that remediate **critical** and **high** severity vulnerabilities, not medium or low. A package with one open critical, three open highs, and two open mediums will, after sealing, still list the two mediums as open. They are not in scope for the default coverage.

If your environment requires coverage of medium and low severities for a specific package or set of packages, your Seal account team can extend the scope.

## 2. The vulnerability was disclosed after the sealed version was released

Seal builds a sealed version against the vulnerabilities it knows about at build time. A new vulnerability disclosed after the sealed version ships is open against that sealed version until Seal builds the next iteration: `sp2`, `sp3`, and so on, each one sealing every previous vulnerability plus the new one.

What happens in your tenant when Seal publishes a new sealed version for a package you have already sealed depends on whether your existing Sealing Rule is pinned to a specific sealed version or tracks the safest version.

* **Unpinned (safest version)**. The Sealing Rule automatically points at the new sealed version. The row for the previously-sealed version (for example, `ejs@2.7.4-sp1` once `sp2` ships) appears in Pending deploy; on the next CLI run, the build pulls `sp2` and the row moves to Sealed. The original origin-version row (`ejs@2.7.4`) continues to show Sealed throughout, because the package has been sealed the whole time.
* **Pinned to a specific sealed version**. The Sealing Rule does not move on its own. The original origin-version row stays in Sealed (the pinned version was, and still is, sealed). A new row appears for the now-vulnerable previously-sealed version, with a **Seal** button next to it. Clicking the button is the path to update the Sealing Rule, either by pinning to the new sealed version or switching to the safest-version option. The same update can be made directly on the [Sealing rules tab](/discovering/protection-page/sealing-rules-tab).

## 3. The vulnerability cannot be remediated without breaking changes

Some vulnerabilities can only be removed by changing behavior the package's users may rely on. The pattern is usually one of these:

* **Removing a feature that is itself the vulnerability.** For example, support for a deprecated, insecure cryptographic algorithm. The fix is to remove the algorithm; the breaking part is that callers still using the algorithm stop working.
* **Changing a default from insecure to secure.** For example, switching a setting that was permissive by default to restrictive by default. Existing configurations that relied on the permissive default fail or behave differently after the change.

The functionality being removed or changed is often obscure or undocumented, but some users do depend on it. Seal does not backport a fix that would silently break the customers using the sealed package: a sealed version is a drop-in replacement, by definition, and a behavior-changing patch is not.

For these cases, Seal can build a [private version](/discovering/private-versions) on request: a sealed version that includes the fix, with the customer's explicit acknowledgement of the compatibility impact. Private versions are not enabled in your tenant by default; ask your Seal account team to enable one for a specific package.

## A related case: a vulnerability that does not appear at all

Sometimes a vulnerability that one of your other scanners flags does not appear in Seal's view at all, neither sealed nor open. The most common reason is that Seal has determined the vulnerability is not really a vulnerability for this package and version, and removed it from its database. The dispositions Seal applies:

* **Not a vulnerability.** The reported issue is a regular bug with no security impact, or a legitimate feature the original researcher misclassified.
* **Wrong package.** The vulnerable code is not actually compiled into this package, even though the source repository overlaps. This happens when several packages share a source tree but each only compiles a subset of the files; the researcher attributed the issue to the parent package without checking which artifact actually ships the code.
* **Wrong version.** The vulnerability was introduced in a later version than the published affected-version range claims, so the version on the row is not actually affected.

When Seal disposes of a vulnerability this way, it is removed from Seal's database. If it was the package's only vulnerability, the row does not exist on the Vulnerable packages tab at all. If the package has other vulnerabilities, the disputed one is absent from both the sealed and open lists in the drawer. Other scanners that have not made the same disposition may still report the vulnerability against the package; that is a downstream noise problem, addressed in [Scanner Exclusions](/using-platform/scanner-exclusions).

## Where partial fixes show up in the UI

<figure><img src="/files/tuw1S1BPDN8PPz8NMa50" alt="A partially-fixed row with the drawer open showing both sealed and open vulnerabilities"><figcaption><p>The Vulnerabilities column splits the chip count, and the drawer lists sealed and open vulnerabilities side by side.</p></figcaption></figure>

* **The Vulnerabilities column on the Vulnerable packages tab** splits the chip count between sealed and open vulnerabilities. A row whose package has been sealed but still has open vulnerabilities shows both counts.
* **The drawer's Vulnerabilities tab** lists sealed and open vulnerabilities side by side. Each open vulnerability is an entry with the same fields as a sealed one (identifier, severity, advisory link), so you can see exactly what is left.
* **The package's row state** stays as Sealed when the package has been replaced with the sealed version, even if open vulnerabilities remain. The Sealed state means "the sealed version is in use", not "every vulnerability is gone".

## Related

* [The package drawer](/discovering/package-drawer): the drawer where the open list lives.
* [private versions](/discovering/private-versions): the path for vulnerabilities that need a behavior-changing patch.
* [Package states](/discovering/package-states): why a row stays in Sealed state even when open vulnerabilities remain.
* [Scanner Exclusions](/using-platform/scanner-exclusions): the workaround for vulnerabilities that other scanners flag but Seal has disputed.


# Private versions

Sealed versions whose fix introduces a breaking change, enabled per Seal Project after the customer acknowledges the impact.

A **private version** is a sealed version whose fix is not a perfect drop-in replacement for the origin version. Most sealed packages preserve the origin version's behavior exactly: a private version is the exception, used when a vulnerability cannot be remediated without changing something the origin version's users may have been depending on.

The [Partial fixes & open vulnerabilities](/discovering/partial-fixes) chapter is the canonical home for the case that produces private versions: a vulnerability that can only be removed by removing a feature, changing a default, or otherwise altering observable behavior. A private version is what Seal can offer when a customer is willing to accept the impact in exchange for the fix.

## What a private version is

A private version is built from the same origin version as a regular sealed version, with a closely related but distinct version-string suffix. Where a regular sealed version uses `-sp[N]` or `+sp[N]` (depending on the ecosystem), a private version uses `-sp[N]p[M]` or `+sp[N]p[M]`. `[N]` matches the public sealed iteration the private version is built on top of; `[M]` is a running count of private fixes within that iteration. So `ejs@2.7.4-sp1p1` is the first private version sitting on top of the public `ejs@2.7.4-sp1`.

When Seal releases a new public sealed version for a package that already has private versions, the private versions are rebuilt to keep up. A customer using `ejs@2.7.4-sp1p1` will be offered `ejs@2.7.4-sp2p1` once `ejs@2.7.4-sp2` ships, with the private fix re-applied on top of the newer public sealed iteration. Private versions do not fall behind public sealed versions.

## Why a private version makes sense

A private version's compatibility caveat is real, but the breaking change usually affects features most customers do not use. Removing support for a deprecated, insecure cryptographic algorithm only breaks code paths that still call that algorithm; flipping a permissive default to a strict one usually only affects deployments that depended on the old default. The customers most likely to adopt a private version are the ones who can confirm their code does not use the changing behavior at all.

Even when the changing feature is not in use, the vulnerability is often still worth fixing:

* The vulnerable code may be reachable through another call path, independent of the feature the private version changes.
* The vulnerable code may not be reachable at all, but compliance frameworks or a downstream customer's policy may require remediation regardless.

If the changing feature is not used, the private version delivers the fix at no behavioral cost. Compared to the alternative when there is no public sealed version for the CVE, which is usually upgrading to a major new release of the package or of the framework that bundles it, a private version is far cheaper: enabling it for a Seal Project takes the time of one conversation and one CLI run, rather than the weeks of testing and migration a major upgrade would need.

## When Seal builds a private version

Seal does not build a private version unless a customer asks for one. The trigger is always a customer request: a vulnerability that matters to the customer, that has no clean backport because the only fix involves a behavior change, and that the customer is willing to accept the impact of.

Examples:

* A package's only fix removes support for a deprecated, insecure cryptographic algorithm. Customers whose code does not use the algorithm can adopt the private version safely. Customers whose code does use it would silently break and have to migrate first.
* A package's only fix changes a default that was permissive to a stricter setting. Customers whose deployments rely on the permissive default would behave differently after the change.

In both cases, Seal could not ship the fix as a public sealed version: its compatibility contract would no longer hold for every customer of that package. Building it as a private version, only enabled for customers who have evaluated the impact, preserves the contract.

## Why usage is per Seal Project

Private versions are enabled per Seal Project, not tenant-wide and not platform-wide. Each Seal Project has its own list of allowed private versions; only versions on the list are served to that project's builds.

The reason is that the breaking-change impact depends on the customer's code in that specific project. A customer with two Seal Projects, one that uses the affected behavior and one that does not, may want the private version for the second project but not the first. Per-project enablement makes that a normal configuration choice rather than a global all-or-nothing.

## Requesting and enabling a private version

The flow for getting a private version into a Seal Project:

1. **Identify the package and version**. The vulnerability is open in the [drawer](/discovering/package-drawer), and the [Unfixable](/discovering/package-states#unfixable) section of Package states is where Seal's analysis lands when no clean fix exists.
2. **Contact your Seal account team** to request a private version for that package and version. Describe which Seal Project you intend to enable it for.
3. **Review the breaking-change impact** with the account team. The conversation covers what behavior the private version changes, who would be affected, and how to test that the change is safe for your project.
4. **Acknowledge the impact** to the account team. Acknowledgement is what authorizes Seal to enable the private version for your specific Seal Project.
5. **Seal enables the private version** for the project. The next CLI run, or the next pull through the [Seal Artifact Server](/discovering/artifact-server-discovery), can use it.

The first time a customer requests a private version that does not yet exist, Seal builds the version itself before enabling it. If the version already exists for the package (because another tenant has already requested it), Seal can enable it for your project on its own schedule.

## After a private version is enabled

A private version is a normal sealed version once enabled. You create a Sealing Rule for it the same way you do for a public sealed version, on the [Sealing rules tab](/discovering/protection-page/sealing-rules-tab) or with the **Seal** button on a Vulnerable packages row. The Vulnerable packages tab moves the row to Pending deploy and then to Sealed in the usual way; the row carries the same state semantics as any other sealed package.

Disabling a private version is the same out-of-band conversation with the account team: ask, the project's allow-list is updated, the next CLI run no longer pulls the private version.

## Related

* [Partial fixes & open vulnerabilities](/discovering/partial-fixes): the broader framing of why some vulnerabilities can only ship as private versions.
* [The package drawer](/discovering/package-drawer): where you see the open vulnerability that motivated the request.
* [Package states](/discovering/package-states): the lifecycle a private-version-using package follows once enabled.


# Application and OS setup

Day-1 setup for Seal Apps and Seal OS — the two products that seal packages inside your build.

This section covers the day-1 mechanics for the two Seal products that work at the **dependency layer**: **Seal Apps** (your application's open-source dependencies) and **Seal OS** (OS-level packages and language runtimes). Both products work by sealing packages *inside* a build, in contrast to the container-layer products covered under [Container and image setup](/setup-containers).

## What's in this section

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): the decision page comparing the five deployment methods (Remote, Local, Automatic Remediation, Artifact Server, Manual).
* [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd): the recommended deployment — installing the CLI, fix modes, per-CI-system integration, Dockerfile patterns, local development.
* [Seal Apps via the Seal Artifact Server](/setup-apps-os/artifact-server): pointing your package manager at the Seal Artifact Server as a remote.
* [Seal OS in CI/CD](/setup-apps-os/seal-os-cicd): the `seal fix --os` command, sealing OS packages in a Dockerfile, container build pipelines.
* [On-prem and air-gapped environments](/setup-apps-os/on-prem): hosting patterns when neither the Seal CLI nor the artifact server can reach the public internet.


# Choosing your deployment method

A decision page for the five Seal deployment methods, ordered by what they give you.

A Seal Project's **deployment method** is how Seal is integrated into the customer's environment: how sealed packages reach the build, and how Sealing Rules (or their absence) drive what gets replaced. Seal supports five deployment methods. The first three are flavors of the same setup ("the Seal CLI runs in CI/CD"); they differ only in the [CLI fix mode](/getting-started/creating-a-seal-project#cli-fix-mode) the CLI is invoked with. The last two do not run the CLI in CI at all.

## The five deployment methods

| Deployment method         | What runs in CI                                                | Source of Sealing Rules                                                                                      |
| ------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| **Remote**                | Seal CLI in **remote mode**                                    | Sealing Rules from the Seal Platform UI                                                                      |
| **Local**                 | Seal CLI in **local mode**                                     | A `.seal-actions.yml` file checked into source                                                               |
| **Automatic Remediation** | Seal CLI in **all mode**                                       | None: every vulnerable package is replaced automatically                                                     |
| **Artifact Server**       | Nothing in CI; the Seal Artifact Server is a configured remote | Manifest pinning (the customer points specific versions at sealed counterparts in their dependency manifest) |
| **Manual**                | Nothing in CI                                                  | None                                                                                                         |

If the Seal CLI can run in your CI/CD pipeline, the choice between Remote, Local, and Automatic Remediation is a single CLI flag: the same install, the same token, the same pipeline step, with a different fix-mode value. Switching between them later is a one-line change. The choice between CLI-in-CI and Artifact Server (or Manual) is the larger decision, because it changes what is set up where.

## A decision tree

Two questions narrow the choice:

1. **Can the Seal CLI run in your CI/CD pipeline?**
   * Yes → run the CLI. Then pick the fix mode that fits where you want your Sealing Rules:
     * In the Seal Platform UI, managed centrally → **remote** fix mode → **Remote**.
     * In `.seal-actions.yml` files version-controlled with the code → **local** fix mode → **Local**.
     * No rules; replace every vulnerable package → **all** fix mode → **Automatic Remediation**.
   * No → continue to question 2.
2. **Can your package manager be pointed at a configured remote?**
   * Yes → **Artifact Server**.
   * No → **Manual**.

## Who runs each method

A bigger factor than the technical setup is which team is going to operate the deployment day to day. The five methods differ on whether developers, the security team, or no one in particular has to act for a remediation to land.

* **Remote**: best for security teams who want to remediate independently. The team creates Sealing Rules in the Seal Platform UI, the next CLI run picks them up, the build ships sealed packages. No pull request, no waiting for a developer to merge. Rules are not tracked in source control, which is a slight loss in auditability traded for the agility to actually fix problems instead of nagging developers to prioritize them.
* **Local**: best for developers who want to be hands-on and keep the remediation process in their own change-review flow. Every Sealing Rule is a change to `.seal-actions.yml`, which means every Sealing Rule is a pull request. The plus side is that the rules are tracked in source control alongside the code. The down side is that anyone without merge rights, the security team in most organizations, has to go through someone with merge rights to land a rule. Local is most workable when the developers themselves are the ones adopting Seal.
* **Automatic Remediation**: requires no action from anyone in particular. The CLI runs in CI with `--mode all`, every vulnerable package is replaced. Useful when the policy is "always seal what we can" and there is no per-rule review to manage.
* **Artifact Server**: like Local in that the developers have to change the manifest and merge it; unlike Local in that there is no Sealing Rule abstraction, the manifest pinning is the rule. Same coordination cost as Local, with weaker discovery on top.
* **Manual**: the most labor-intensive for developers. Each fix is a download from the [Repository page](/discovering/repository-page/sealed-packages) and a manual replacement of the artifact. Requires high technical knowledge and is the heaviest operational lift of the five methods, but customers do use it at scale when their environment leaves no other option.

## Our recommendation, when more than one option fits

All five methods are workable at scale. When more than one is available to you, the one we recommend reaching for first is the one closest to the top of this list. The others remain perfectly good choices, and the right one for your environment is the one you can actually adopt.

1. **Remote**. Lets security teams remediate independently, and works fine for developer-led teams as well.
2. **Local**. Suits developer-led teams that want every change reviewed in source. The pull-request flow adds coordination cost when the security team does not have merge rights.
3. **Automatic Remediation**. The right fit when the policy is "seal everything we can" and there is no per-rule review to manage.
4. **Artifact Server**. The choice when the Seal CLI cannot run in your build. Discovery is weaker than the CLI-in-CI methods, as covered in the [coverage caveats](/discovering/package-discovery-mode/artifact-server), and rules live in the manifest as pins rather than as Sealing Rules in the platform.
5. **Manual**. The right choice when nothing else fits the environment, including air-gapped environments and component handoffs from teams you do not own. Heavier developer effort per remediation than any of the others, but viable at any volume.

## Trade-offs the choice drives

* **Discovery accuracy**. Remote, Local, and Automatic Remediation all run the CLI in CI, which feeds [CLI-mode discovery](/discovering/package-discovery-mode/cli) (or source-code mode if SCM is also connected). Artifact Server feeds [artifact-server-mode discovery](/discovering/package-discovery-mode/artifact-server), with weaker coverage. Manual feeds nothing.
* **Where rules live**. Remote rules live in the Seal Platform UI; Local rules live in source; Automatic Remediation has no rules; Artifact Server uses manifest pinning instead of rules; Manual has no rules.
* **What needs to change in your build**. The three CLI-in-CI methods all need the Seal CLI installed in CI plus a Seal Project's [token](/getting-started/tokens). They differ only in the CLI's fix-mode flag: Remote runs the CLI with `remote`, Local with `local`, Automatic Remediation with `all`. Artifact Server needs your package manager configured to use the Seal Artifact Server. Manual needs nothing in CI; you download artifacts on demand.
* **Whether automatic PRs are available**. The [GitHub automatic-PR feature](/discovering/connecting-source-control/github#automatic-pull-requests) writes proposed Sealing Rules into `.seal-actions.yml`, which only takes effect under Local. Automatic PRs are not relevant to Remote, Automatic Remediation, Artifact Server, or Manual.

## Mixing methods

A tenant with multiple Seal Projects can use different deployment methods per project. This is common in larger organizations: a flagship application uses Remote, a small internal tool uses Local because its team wants their rules in source, and a vendor-built component running in air-gapped infrastructure uses Manual. Each Seal Project records its own method, and the deployment method does not propagate.

## Related

* [Seal Apps via the Seal CLI in CI/CD](/setup-apps-os/cli-in-cicd): the setup chapter for the three CLI-in-CI methods (Remote, Local, Automatic Remediation).
* [Seal Apps via the Seal Artifact Server](/setup-apps-os/artifact-server): the setup chapter for Artifact Server.
* [On-prem and air-gapped environments](/setup-apps-os/on-prem): the setup chapter for environments where hosts cannot reach Seal directly. Covers both Seal Apps and Seal OS.
* [Package discovery mode](/discovering/package-discovery-mode): how each deployment method's discovery side shows up in the Seal Platform.
* [Network requirements](/reference/network-requirements): the hostnames every deployment method needs reachable.


# Seal Apps via the Seal CLI in CI/CD

Setting up the Seal CLI in your CI/CD pipeline so it can scan your manifest and apply Sealing Rules.

Running the Seal CLI in your CI/CD pipeline is the most complete way to use Seal Apps. The CLI scans your dependency manifest, applies the active Sealing Rules (or replaces every vulnerable package, in **all** mode), and produces the build that ships sealed packages instead of vulnerable ones. The same CLI run also feeds Seal's discovery side, so the Seal Project's package picture stays current.

This chapter is the canonical setup home for the three CLI-in-CI deployment methods (Remote, Local, and Automatic Remediation, see [Choosing your deployment method](/setup-apps-os/choosing-deployment-method)). The chapter is structured as:

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli): downloading and unpacking the binary on Linux, macOS, or Windows.
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode): the three modes the CLI runs in (local, remote, all) and which one each deployment method uses.
* Per-platform CI integrations:
  * [Integrating with GitHub Actions](/setup-apps-os/cli-in-cicd/github-actions): the dedicated `seal-community/cli-action`.
  * [Integrating with GitLab CI](/setup-apps-os/cli-in-cicd/gitlab-ci)
  * [Integrating with Azure DevOps Pipelines](/setup-apps-os/cli-in-cicd/azure-devops)
  * [Integrating with Jenkins](/setup-apps-os/cli-in-cicd/jenkins)
  * [Integrating with CircleCI](/setup-apps-os/cli-in-cicd/circleci)
* [Running the CLI inside a Dockerfile](/setup-apps-os/cli-in-cicd/dockerfile): for builds that drop into a container, with or without a CI system around them.
* [Setting up local development](/setup-apps-os/cli-in-cicd/local-development): running the CLI on a developer's machine with a development token.
* [Common issues](/setup-apps-os/cli-in-cicd/common-issues): the failures that come up most often.

## Before you start

* The Seal CLI must run somewhere with network access to the Seal Platform and the [Seal Artifact Server](/discovering/artifact-server-discovery).
* You need a [token](/getting-started/tokens) for authentication. Production tokens for production-equivalent CI; development tokens for developer machines and feature-branch pipelines.
* You need a Seal Project for the CLI to attribute its activity to. The first run with a `SEAL_PROJECT` value that does not exist creates the project automatically; see [Project ID and project name](/getting-started/creating-a-seal-project#project-id-and-project-name).

## What the CLI does in CI

A typical CI invocation runs `seal fix`. The flow:

1. The CLI authenticates with the token from `SEAL_TOKEN`.
2. It scans the dependency manifest in the working directory and reports the discovered packages to the Seal Platform under the supplied `SEAL_PROJECT`.
3. Depending on the [fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode), the CLI fetches the relevant Sealing Rules (remote) or reads them from `.seal-actions.yml` (local), or skips the rule lookup and replaces every vulnerable package it can (all).
4. For each rule that applies, the CLI pulls the sealed version from the Seal Artifact Server and replaces the installed vulnerable version on disk.
5. Subsequent build steps run against the sealed packages in place of the originals.

## When in the pipeline the CLI runs

The CLI replaces packages **on disk** that the dependency-install step has already put there. The right place in your pipeline is therefore **after** the install step (`npm install`, `npm ci`, `mvn install`, `pip install`, `composer install`, and so on) and **before** any step that packages, bundles, or compiles those dependencies together (webpack, JAR packaging, `docker build`, and so on).

If the CLI runs before the install step, there are no installed packages to replace and the step is a no-op. If the CLI runs after the packaging step, the packaged output is already built from the vulnerable versions.

## Related

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): the decision page for the five deployment methods.
* [Connecting via the Seal CLI in CI](/discovering/cli-in-ci): the discovery-side how-to that pre-dates this chapter.
* [Sealing Rules](/using-platform/sealing-rules): the rules the CLI applies in remote and local modes.


# Installing the Seal CLI

Download and unpack the Seal CLI binary on Linux, macOS, or Windows.

The Seal CLI is published as a single binary per platform. There is no installer-managed package today; you download the binary, place it on the `PATH`, and run it. Seal's releases are at [`github.com/seal-community/cli/releases`](https://github.com/seal-community/cli/releases).

In CI/CD pipelines, the install is a step in the pipeline itself. See the per-platform integration pages ([GitHub Actions](/setup-apps-os/cli-in-cicd/github-actions), [GitLab CI](/setup-apps-os/cli-in-cicd/gitlab-ci), [Azure DevOps](/setup-apps-os/cli-in-cicd/azure-devops), [Jenkins](/setup-apps-os/cli-in-cicd/jenkins), [CircleCI](/setup-apps-os/cli-in-cicd/circleci), [Dockerfile](/setup-apps-os/cli-in-cicd/dockerfile)) for the exact shape of that step on your platform.

## Linux

```bash
curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest.zip -o seal.zip
unzip seal.zip
chmod +x seal
./seal version
```

The downloaded archive contains the `seal` binary. Place it on the `PATH` (for example, `mv seal /usr/local/bin/seal`) for system-wide use, or run it from the working directory as shown.

## macOS

A signed `.pkg` installer is available from the [latest release](https://github.com/seal-community/cli/releases/tag/latest). Download it and double-click to install; the binary lands at `/usr/local/bin/seal`.

A zipped binary is also available on the same release page if you prefer to install manually:

```bash
curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-darwin-amd64-latest.zip -o seal.zip
unzip seal.zip
chmod +x seal
./seal version
```

For Apple Silicon, swap `amd64` for `arm64` in the URL.

## Windows

The Windows binary is `amd64` (x86-64), published as both a `.zip` and a standalone `seal-windows-amd64-latest.exe` on the [latest release](https://github.com/seal-community/cli/releases/tag/latest).

```powershell
Invoke-WebRequest -Uri https://github.com/seal-community/cli/releases/download/latest/seal-windows-amd64-latest.zip -OutFile seal.zip
Expand-Archive seal.zip -DestinationPath .
.\seal.exe version
```

The archive contains the `seal.exe` binary. Run it from the working directory as shown, or add its directory to the `Path` environment variable for use anywhere.

{% hint style="info" %}
The Windows binary is unsigned, so Windows SmartScreen may warn on first run. The `gradle` and `bundler` package managers are not yet supported on Windows; running the CLI against a Gradle or Bundler project on Windows prints a "not yet supported on Windows" message. The other supported package managers behave as they do on Linux and macOS.
{% endhint %}

## Verifying the install

```bash
seal version
```

The command prints the installed version. If the output is a version string, the install is good.

## Use the latest version

For new installs, use `latest`. The Seal CLI deprecates older versions over time, so a build that pins an old version eventually stops working as the platform moves forward. The recommended practice is to use whatever the `latest` URL resolves to, and to refresh the install whenever the CLI changes underneath your build.

If you have a strong operational reason to pin (a regulated environment with a frozen build chain, for example), pin to a recent version and treat the pin as a renewal commitment: keep the pinned version no more than six months old, and upgrade on a regular cadence.

## Related

* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode): what to pass next, once the CLI is on the `PATH`.
* [Network requirements](/reference/network-requirements): the hostnames the CLI host needs reachable.
* The per-platform CI integration pages for pipeline-step shapes.


# The CLI fix mode

The three modes the Seal CLI runs in, and which deployment method maps to which mode.

The Seal CLI's fix mode is what the CLI does when it runs against a Seal Project. The mode is set by the `--mode` flag on `seal fix`. There are three values:

| Mode         | What the CLI does                                                                                                                            | Deployment method         |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| **`local`**  | Reads Sealing Rules from a `.seal-actions.yml` file in the working directory, applies them, replaces matching packages with sealed versions. | **Local**                 |
| **`remote`** | Fetches Sealing Rules from the Seal Platform for the current Seal Project, applies them, replaces matching packages.                         | **Remote**                |
| **`all`**    | Skips the rule lookup entirely. For every vulnerable package the CLI discovers, it replaces it with the sealed version if one exists.        | **Automatic Remediation** |

The mode is the only thing that distinguishes the three CLI-in-CI [deployment methods](/setup-apps-os/choosing-deployment-method). The CLI itself, the token, the Seal Project, the network requirements, and the manifest scan are the same.

## Choosing a mode

* Use **`remote`** when Sealing Rules are managed centrally through the Seal Platform UI by a security team.
* Use **`local`** when the Sealing Rules should live alongside the code they apply to, version-controlled with it, and reviewed in the same pull requests as code changes. The [Seal GitHub App](/discovering/connecting-source-control/github#automatic-pull-requests) can open automatic pull requests that populate `.seal-actions.yml` for you.
* Use **`all`** when the team wants every vulnerable package replaced as a matter of policy, with no per-rule review. This produces the most replacements with the least operational effort, at the cost of the per-rule control the other two modes provide.

The recommended ordering for the three is in [Choosing your deployment method](/setup-apps-os/choosing-deployment-method#recommended-ordering).

## What the mode controls

The fix mode determines which packages the CLI replaces on a given run. In `remote` mode, the CLI applies the remote Sealing Rules attached to the Seal Project; in `local` mode, the rules in `.seal-actions.yml`; in `all` mode, every vulnerable package that has a sealed version.

The Seal Project's current fix mode is visible on the [Projects page](/getting-started/creating-a-seal-project#editing-a-project), recorded from the most recent CLI run.

Switching modes is supported in any direction, but be aware that a run in the new mode no longer applies the rules from the previous one. Switching from `remote` to `local` makes your existing remote Sealing Rules effectively inert; switching from `local` to `remote` does the same for the rules in `.seal-actions.yml`. Pick a mode, recreate the rules in the new location if you change your mind, and stick with it. See [Mode changes in Creating a Seal Project](/getting-started/creating-a-seal-project#mode-changes).

## Related

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): the decision page that places the three modes within the broader five-method picture.
* [Sealing Rules](/using-platform/sealing-rules): what `local` and `remote` modes apply, and how they are created.


# Integrating with GitHub Actions

Run Seal in your GitHub Actions workflow using the seal-community/cli-action.

For GitHub Actions, Seal publishes a dedicated action: [`seal-community/cli-action`](https://github.com/seal-community/cli-action). Add it as a step in your workflow and it installs the Seal CLI, authenticates, and runs the scan-and-fix pass for you.

The action is distinct from the [Seal GitHub App](/discovering/connecting-source-control/github): the App connects your repositories to the Seal Platform for SCM-side discovery and automatic pull requests; the Action runs the CLI inside your build. You can use both, one, or neither.

## Before you start

* A [token](/getting-started/tokens) stored as a GitHub Actions secret.
* A [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) for the activity to attribute to. The first run with a new ID creates the Seal Project.

## The step

```yaml
- uses: seal-community/cli-action@latest
  with:
    mode: fix
    fix_mode: all
    token: ${{ secrets.SEAL_TOKEN }}
    project: my-project-id
    target: ./package-lock.json
```

Place the step after the dependency-install step (`npm ci`, `mvn install`, and so on) and before any step that packages or bundles those dependencies. See [What the CLI does in CI](/setup-apps-os/cli-in-cicd#when-in-the-pipeline-the-cli-runs).

## Inputs

| Input       | Description                                                                                         |
| ----------- | --------------------------------------------------------------------------------------------------- |
| `token`     | The Seal token, sourced from a secret.                                                              |
| `project`   | The Seal Project's Project ID.                                                                      |
| `mode`      | `scan` or `fix`. Default: `scan`. Use `fix` to apply Sealing Rules and replace vulnerable packages. |
| `fix_mode`  | `local`, `remote`, or `all`. The CLI's [fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode).         |
| `target`    | Path to the dependency manifest. Default: `./requirements.txt`. Override for other ecosystems.      |
| `version`   | The Seal CLI version. Default: latest.                                                              |
| `verbosity` | `v`, `vv`, or `vvv`. Default: `v`.                                                                  |
| `summary`   | Path to write a summary file when running in fix mode.                                              |

For matrix builds, each matrix leg should pass its own `target` and, where relevant, its own Seal Project ID. The action runs on every event type GitHub Actions supports.

## Related

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli): the manual install path the action automates, for non-Actions contexts.
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode): the meaning of the `fix_mode` input.
* [The Seal GitHub App](/discovering/connecting-source-control/github): the SCM-side integration distinct from this action.


# Integrating with GitLab CI

Run Seal in a GitLab CI pipeline.

GitLab CI integration is a shell pattern: install the CLI, run `seal fix`.

## Before you start

* A [token](/getting-started/tokens) saved as a masked CI/CD variable named `SEAL_TOKEN`.
* A [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) for the activity.

## The job

```yaml
seal_fix:
  variables:
    SEAL_PROJECT: my-project-id
  script:
    - curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest.zip -o seal.zip
    - unzip seal.zip && chmod +x seal
    - ./seal fix --mode all
```

Replace `--mode all` with `--mode remote` or `--mode local` per your [deployment method](/setup-apps-os/choosing-deployment-method). The job should run after dependencies are installed and before they are packaged — see [What the CLI does in CI](/setup-apps-os/cli-in-cicd#when-in-the-pipeline-the-cli-runs).

`SEAL_TOKEN` is read by the CLI automatically from the environment; no explicit passing is needed.

## Related

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli).
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode).


# Integrating with Azure DevOps Pipelines

Run Seal in an Azure DevOps Pipelines job.

Azure DevOps integration is a script-step pattern: install the CLI, run `seal fix`.

## Before you start

* A [token](/getting-started/tokens) saved as a pipeline variable, marked secret (refer to as `$(SEAL_TOKEN)` in YAML).
* A [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) for the activity.

## The step

```yaml
- bash: |
    curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest.zip -o seal.zip
    unzip seal.zip && chmod +x seal
    export SEAL_TOKEN=$(SEAL_TOKEN)
    export SEAL_PROJECT=my-project-id
    ./seal fix --mode all
  displayName: Run Seal CLI
```

Replace `--mode all` with `--mode remote` or `--mode local` per your [deployment method](/setup-apps-os/choosing-deployment-method). The step should run after dependencies are installed and before they are packaged.

Pipeline variables marked secret are not exposed to the shell environment by default; the explicit `export SEAL_TOKEN=$(SEAL_TOKEN)` makes the token available to the CLI. If the agent's base image lacks `curl` or `unzip`, install them first.

## Related

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli).
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode).


# Integrating with Jenkins

Run Seal in a Jenkins pipeline.

Jenkins integration is a shell pattern: install the CLI, run `seal fix`.

## Before you start

* A [token](/getting-started/tokens) stored as a **Secret text** credential (for example, with ID `seal-token`).
* A [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) for the activity.

## The stage

```groovy
stage('Seal CLI') {
  environment {
    SEAL_TOKEN = credentials('seal-token')
    SEAL_PROJECT = 'my-project-id'
  }
  steps {
    sh '''
      curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest.zip -o seal.zip
      unzip seal.zip && chmod +x seal
      ./seal fix --mode all
    '''
  }
}
```

Replace `--mode all` with `--mode remote` or `--mode local` per your [deployment method](/setup-apps-os/choosing-deployment-method). The stage should run after dependencies are installed and before they are packaged.

The `credentials('seal-token')` binding sets `SEAL_TOKEN` in the stage's environment. If your pipeline splits the install and the run into separate stages, both need the binding.

## Related

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli).
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode).


# Integrating with CircleCI

Run Seal in a CircleCI pipeline.

CircleCI integration is a shell pattern: install the CLI, run `seal fix`.

## Before you start

* A [token](/getting-started/tokens) stored as a CircleCI environment variable (project-level or context-level) named `SEAL_TOKEN`.
* A [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) for the activity.

## The job

```yaml
seal_fix:
  docker:
    - image: cimg/base:stable
  environment:
    SEAL_PROJECT: my-project-id
  steps:
    - checkout
    - run:
        command: |
          curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest.zip -o seal.zip
          unzip seal.zip && chmod +x seal
          ./seal fix --mode all
```

Replace `--mode all` with `--mode remote` or `--mode local` per your [deployment method](/setup-apps-os/choosing-deployment-method). The job should run after dependencies are installed and before they are packaged.

`SEAL_TOKEN` is read by the CLI automatically from the environment. Custom images need `curl` and `unzip` available.

## Related

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli).
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode).


# Running the CLI inside a Dockerfile

Run the Seal CLI inside a Dockerfile build, replacing vulnerable packages before the image is finalized.

When the entire build is wrapped inside `docker build` with no separate CI step where the Seal CLI could run, the CLI runs inside the Dockerfile itself: install the CLI in an intermediate layer, run `seal fix` after the dependency-install step, finish the build.

## Sketch

```dockerfile
# syntax=docker/dockerfile:1.4

FROM node:20
WORKDIR /app
COPY . .
RUN npm ci

# Install the Seal CLI in an intermediate layer.
ADD https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest /usr/local/bin/seal
RUN chmod +x /usr/local/bin/seal

# Run seal fix with the token mounted as a build-time secret.
ARG SEAL_PROJECT=my-project-id
RUN --mount=type=secret,id=SEAL_TOKEN,env=SEAL_TOKEN \
    seal fix --mode all --remove-cli

RUN npm run build
```

The seal step runs after `npm ci` (so the packages are on disk to be replaced) and before `npm run build` (so the build sees the sealed versions). The same shape applies to every ecosystem; swap `npm ci` for `mvn install`, `pip install -r requirements.txt`, `go mod download`, and so on.

`--remove-cli` deletes the CLI binary at the end of the run, so the final image does not ship with it. Drop the flag if you have a reason to keep the binary in the image.

## Passing the token

The example uses **BuildKit secrets** to mount `SEAL_TOKEN` only for the duration of the seal step. It does not appear in image history or layer metadata. Invoke the build with:

```bash
SEAL_TOKEN=$SEAL_TOKEN docker build --secret id=SEAL_TOKEN,env=SEAL_TOKEN -t my-app .
```

BuildKit secrets are available from Docker 18.09 onward with BuildKit enabled (the default on modern Docker versions). If your build runs on an older Docker without BuildKit, fall back to `--build-arg SEAL_TOKEN=$SEAL_TOKEN` — it works, but the token may appear in image history; rotate the token after the build if that matters for your environment.

## Notes

* `--mode all`, `--mode remote`, and `--mode local` all work inside a Dockerfile. Pick the one that matches your [deployment method](/setup-apps-os/choosing-deployment-method).
* BuildKit aggressively caches `RUN` steps. If `seal fix` is being skipped on re-runs when you expect it to re-execute, see the [BuildKit caching note](/setup-apps-os/cli-in-cicd/common-issues#platform-specific-gotchas).

## Related

* [Installing the Seal CLI](/setup-apps-os/cli-in-cicd/installing-the-cli): the install methods for non-Dockerfile contexts.
* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode): the meaning of `--mode all`.


# Setting up local development

Run the Seal CLI on a developer's machine using a development token.

A developer can run the Seal CLI on their own machine, against the same Seal Project the CI/CD pipeline uses or against a separate one, using a [development token](/getting-started/tokens#development-token). Local activity is filtered out of the Protection page by default, so it does not pollute production-side metrics with churn from local builds.

## Steps

1. [**Install the Seal CLI**](/setup-apps-os/cli-in-cicd/installing-the-cli) on the developer's machine.
2. **Generate a development token** from **Settings > Tokens**, or reuse one your team already shares. See [Generating and revoking tokens](/getting-started/tokens/generating-tokens).
3. **Set environment variables** in the developer's shell (typically through `.bashrc`, `.zshrc`, or the equivalent for the shell of choice):

   ```bash
   export SEAL_TOKEN=<your development token>
   export SEAL_PROJECT=my-project-id
   ```
4. **Run the CLI** from the project's working directory the same way CI does:

   ```bash
   seal fix --mode all
   ```

## What changes versus CI

* The token is a development token, not a production token.
* Activity is filtered out of the Protection page by default. To see local-token activity in the Seal UI, switch the [Development token filter](/discovering/protection-page/vulnerable-packages-tab#filters) on the Vulnerable packages tab to include it.

The CLI's behavior is otherwise identical: same `seal fix --mode <mode>` invocation, same Sealing Rule lookup, same sealed-package replacement.

## Related

* [Token types](/getting-started/tokens/token-types): production versus development tokens and what each is tracked against.
* [Token security best practices](/getting-started/tokens/best-practices): where to keep the development token.


# Common issues

The failures that come up most often when running the Seal CLI in CI.

The Seal CLI fails the same way in CI as it does on a developer's machine. A few specific issues come up disproportionately often in pipeline contexts.

## Network issues

**The CLI cannot reach Seal's servers.** The runner needs HTTPS access to the Seal Platform and the [Seal Artifact Server](/discovering/artifact-server-discovery). The most common blockers:

* A corporate firewall or egress proxy is filtering outbound HTTPS by hostname. Allow-list Seal's hostnames at the egress point.
* A zero-trust network product such as **ZScaler**, **Netskope**, or similar is intercepting outbound traffic and rejecting Seal's servers, or rewriting the connection in a way the CLI cannot complete. Add Seal's hostnames to the product's allow-list, or run the CLI on a runner that is not behind the inspection layer.
* The CI runner is in a private subnet without outbound internet. Either give the runner egress, or move to the on-prem workflow described in [On-prem and air-gapped environments](/setup-apps-os/on-prem).

For fully air-gapped environments, see the same chapter for the air-gapped variants.

## Authentication errors

**`SEAL_TOKEN` is not set** or has been revoked. Confirm the variable is exported in the step's environment, that the token is a current value (not a rotated one), and that the token is the right type for the activity (production for production-equivalent CI, development for developer machines and feature-branch CI).

If the CI step is being run by a forked pull request, your CI platform may not expose secrets to runners by default; the runner sees `SEAL_TOKEN` as empty even though it is set at the project level. Check your platform's fork-PR secrets handling.

## CLI misconfiguration

**The wrong fix mode**. `seal fix --mode remote` fetches rules from the Seal Platform; `seal fix --mode local` reads them from `.seal-actions.yml`; `seal fix --mode all` ignores both and seals every vulnerable package. Mixing them up (for example, running in `local` mode while your rules live in the platform UI) results in no rules being applied. Match the mode to where your rules actually live.

**The wrong `SEAL_PROJECT`**. Two unrelated CI pipelines running with the same `SEAL_PROJECT` clobber each other's results in Seal's view. See the [Anti-patterns section in Creating a Seal Project](/getting-started/creating-a-seal-project#anti-patterns).

**The manifest is not auto-detected**. The CLI looks in the working directory by default. If your manifest is elsewhere, pass it with `--manifest <path>` on the CLI invocation, or `cd` into the directory before running. Common case: a monorepo where the relevant lockfile is several directories deep.

**The wrong manifest is scanned**. The CLI parses the file it finds first. For npm, `package-lock.json` is the right input; `package.json` does not pin versions and is rejected. For Python, both `requirements.txt` and `Pipfile.lock` are valid. If the CLI scans the wrong one, point at the right one with `--manifest`.

## Step placement

**The CLI runs before the dependency-install step**. A common mistake is to put `seal fix` before `npm install` / `mvn install` / `pip install`. The CLI replaces packages on disk that the install step has already put there; if no packages are installed yet, there is nothing to replace and the seal step is effectively a no-op. Run `seal fix` **after** the install step.

**The CLI runs after the packaging step**. The mirror image of the above. If `seal fix` runs after the step that bundles or compiles the dependencies into your final artifact (webpack, JAR packaging, `docker build`, and so on), the packaged output is already built from the vulnerable versions. Run `seal fix` **before** the packaging step.

**The CLI runs on the wrong commit**. In branch-based CI, the CLI runs against whatever is checked out. If your workflow checks out a different ref before the CLI step, the scan and the build can diverge.

## Sealing Rules apply but the build still uses vulnerable versions

A common report. The usual causes:

* **You are looking at an artifact the current build did not produce.** A binary that was uploaded earlier, or built in a previous iteration of the pipeline, will still carry whatever was in it at build time. Confirm the artifact under inspection is the one this build wrote.
* **The Sealing Rule does not match the package**. The rule targets a specific origin version; if your manifest pins a slightly different version, or the rule was created in a different Seal Project, it does not apply to this run.
* **The CLI fix mode does not match where the rules are stored**. `local` reads `.seal-actions.yml` and ignores the platform UI; `remote` does the opposite. A remote-stored rule plus a `local` fix-mode call is a no-op.
* **A cache is serving stale artifacts**. The runner's package-manager cache, or an internal artifact-server cache between the runner and Seal, can return a previously-pulled vulnerable version instead of the sealed one. This is most common in Java (older Maven and Gradle configurations cache aggressively). Clear the cache and re-run.
* **The vulnerability is not one Seal remediates**. Not every CVE has a sealed counterpart. See [Partial fixes & open vulnerabilities](/discovering/partial-fixes) for the reasons.

## Platform-specific gotchas

**GitHub Actions**: secrets are not exposed to runners triggered by pull requests from forks. The CLI step in those PR runs sees `SEAL_TOKEN` as empty. Either run the seal step on `push` triggers only, or configure your repository's fork-PR secrets handling explicitly.

**Jenkins**: the `credentials()` binding sets the environment variable only inside the step that declares it. If your Jenkinsfile splits the install and the run into separate stages, both need the binding.

**CircleCI**: project-level environment variables and context-level variables behave the same in normal jobs but interact differently with restricted contexts. If a job that worked locally fails in the protected context, confirm the token is visible there.

**Azure DevOps**: pipeline variables marked secret are not exposed to the shell environment by default. The script step has to explicitly `export SEAL_TOKEN=$(SEAL_TOKEN)` to make the value visible to the CLI.

**Docker (any CI)**: when running the CLI inside a Dockerfile via `RUN`, BuildKit caching can keep the CLI step's output from re-running when you expect it to. Either invalidate the cache (touch the dependency file before the CLI step, or pass `--no-cache` to `docker build`) or split the CLI step into a stage whose output you do not cache.

## Related

* [The CLI fix mode](/setup-apps-os/cli-in-cicd/cli-fix-mode): the right `--mode` for each deployment method.
* [Connecting via the Seal CLI in CI](/discovering/cli-in-ci): the discovery-side basics, with parallel troubleshooting.
* [Partial fixes & open vulnerabilities](/discovering/partial-fixes): the reasons a sealed package may still carry open vulnerabilities.


# Seal Apps via the Seal Artifact Server

Configuring your package managers to pull sealed packages through the Seal Artifact Server.

Running your package manager against the Seal Artifact Server is how Seal Apps works when the Seal CLI cannot run inside your CI/CD pipeline. Your package manager pulls from the Seal Artifact Server (directly or as an additional remote), Seal serves sealed versions of the packages you have pinned to them, and your build proceeds with those sealed packages in place.

This chapter is the canonical setup home for the Artifact Server deployment method.

* [When to use this method](/setup-apps-os/artifact-server/when-to-use): the situations it fits, and the trade-offs versus the CLI-in-CI methods.
* [Configuring package managers](/setup-apps-os/artifact-server/configuring-package-managers): the per-package-manager configuration patterns.
* [Editing dependency files](/setup-apps-os/artifact-server/editing-dependencies): how manifest edits drive package replacement under this deployment method, with a pointer to the per-ecosystem syntax under [Working with Seal Apps](/using-platform/working-with-seal-apps).
* [Maven-specific server features](/setup-apps-os/artifact-server/maven-server-features): `+safest`, `+safest-until-<cutoff>`, and the redirect policy for non-sealed artifacts.
* [Transparent safest relocation](/setup-apps-os/artifact-server/transparent-safest): the per-tenant mode that serves the safest sealed version for a plain origin-version request, for Maven and npm.
* [Blocking vulnerable downloads](/setup-apps-os/artifact-server/download-blocking): the per-tenant policies that refuse to serve versions with open malicious or high and critical vulnerabilities.
* [JFrog Artifactory as your remote](/setup-apps-os/artifact-server/jfrog-artifactory): when your existing JFrog Artifactory should fetch from Seal as an additional remote.

## Before you start

* A **production** [token](/getting-started/tokens) saved in your CI's secret manager (or your developer's secret store, for local builds against the Seal Artifact Server).
* The [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) of the Seal Project you want this build's pulls attributed to.
* A package manager that can be pointed at a configurable remote (npm, Yarn, pnpm, pip, Poetry, Maven, Gradle, Go modules, Composer, Bundler, NuGet).

## How the deployment works

Seal serves packages from one host per ecosystem: `npm.sealsecurity.io` for npm-style ecosystems, `maven.sealsecurity.io` for JVM packages, `pypi.sealsecurity.io` for Python, and so on. These hosts are public and shared across all Seal customers; the credentials in your package manager's configuration are what identify your tenant and your Seal Project.

The build pulls from those hosts as a remote, with HTTP Basic authentication carrying the Project ID in the username and the token as the password. For sealed packages the customer has pinned in the manifest, the server returns the sealed artifact. For non-sealed packages, the server proxies to the public registry (npm registry, Maven Central, PyPi, and so on).

There is no Seal CLI step in this deployment. Sealing Rules in the platform are not applied here; the equivalent of a "rule" is the version pin in your manifest. Each customer-pinned sealed version travels with the manifest like any other dependency.

The full discovery-side picture (what Seal sees, the primary-vs-fallback configurations, caching caveats) is in [Configuring the Seal Artifact Server for discovery](/discovering/artifact-server-discovery) and [Artifact server mode](/discovering/package-discovery-mode/artifact-server).

## Related

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): the decision page for the five deployment methods.
* [Configuring the Seal Artifact Server for discovery](/discovering/artifact-server-discovery): the discovery-side how-to that mirrors this chapter.
* [Generating and revoking tokens](/getting-started/tokens/generating-tokens): generating the production token used in the configuration below.


# When to use this method

When the Artifact Server deployment method is the right fit, and the trade-offs versus the CLI-in-CI methods.

The Artifact Server deployment method is the right choice when your build cannot run the Seal CLI but can be pointed at a configured remote. Common situations:

* The build pipeline is owned by a team you do not have permission to modify (a vendor pipeline, a contracted operations team).
* The build runs in a sandboxed CI environment that does not allow executing arbitrary binaries.
* The build is implemented through tools that orchestrate package-manager operations directly without an obvious place to insert an additional CLI step.
* You are integrating Seal into an existing remote-server-based workflow (for example, a [JFrog Artifactory](/setup-apps-os/artifact-server/jfrog-artifactory) tenant that already configures upstream remotes for each ecosystem) and want Seal to fit in the same pattern.

## What you trade for what

Choosing the Artifact Server deployment shapes a few things differently from the CLI-in-CI methods:

* **No Sealing Rules**. Rules in the Seal Platform UI and in `.seal-actions.yml` are not consulted; the equivalent is the version pin in your manifest. To use a sealed version, the customer names the sealed version directly in `package.json` / `pom.xml` / `requirements.txt` / and so on.
* **Discovery is per-pull**. Seal sees what the build pulls, not what the manifest declares. The picture builds up over time rather than reflecting the latest commit, and the configurations described in [Artifact server mode](/discovering/package-discovery-mode/artifact-server) determine whether Seal sees only sealed-version requests or every pull. Read that chapter for the coverage caveats.
* **No automatic remediation**. Each sealed version landing in the build is the result of a manifest edit by a developer or by a generated PR. There is no Seal CLI pass that replaces vulnerable packages without manual intervention.
* **Developer effort per remediation**. Editing the manifest, opening a pull request, going through review and merge is on the customer's side for each fix. CLI-in-CI methods can fold that in.

The trade-offs above are the ones to plan for if you choose this method.

## Related

* [Choosing your deployment method](/setup-apps-os/choosing-deployment-method): the broader decision page.
* [Editing dependency files manually](/setup-apps-os/artifact-server/editing-dependencies): the manifest-pinning side of the workflow.
* [Configuring package managers](/setup-apps-os/artifact-server/configuring-package-managers): the remote-configuration side of the workflow.


# Configuring package managers

Point each ecosystem's package manager at the Seal Artifact Server.

Seal serves packages from one host per ecosystem. Each host is public and shared across all Seal customers; the credentials in your package manager configuration are what identify your tenant and your Seal Project. Authentication is HTTP Basic: the [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) as the username, the [production token](/getting-started/tokens) as the password.

| Ecosystem  | Host                                   | Page                                                                                         |
| ---------- | -------------------------------------- | -------------------------------------------------------------------------------------------- |
| npm        | `https://npm.sealsecurity.io/`         | [Configuring npm](/setup-apps-os/artifact-server/configuring-package-managers/npm)           |
| Yarn       | `https://npm.sealsecurity.io/`         | [Configuring Yarn](/setup-apps-os/artifact-server/configuring-package-managers/yarn)         |
| pnpm       | `https://npm.sealsecurity.io/`         | [Configuring pnpm](/setup-apps-os/artifact-server/configuring-package-managers/pnpm)         |
| Maven      | `https://maven.sealsecurity.io/`       | [Configuring Maven](/setup-apps-os/artifact-server/configuring-package-managers/maven)       |
| Gradle     | `https://maven.sealsecurity.io/`       | [Configuring Gradle](/setup-apps-os/artifact-server/configuring-package-managers/gradle)     |
| Go modules | `https://go.sealsecurity.io/`          | [Configuring Go](/setup-apps-os/artifact-server/configuring-package-managers/go)             |
| pip        | `https://pypi.sealsecurity.io/simple/` | [Configuring pip](/setup-apps-os/artifact-server/configuring-package-managers/pip)           |
| Poetry     | `https://pypi.sealsecurity.io/simple/` | [Configuring Poetry](/setup-apps-os/artifact-server/configuring-package-managers/poetry)     |
| Bundler    | `https://ruby.sealsecurity.io/`        | [Configuring Bundler](/setup-apps-os/artifact-server/configuring-package-managers/bundler)   |
| NuGet      | `https://nuget.sealsecurity.io/`       | [Configuring NuGet](/setup-apps-os/artifact-server/configuring-package-managers/nuget)       |
| Composer   | `https://packagist.sealsecurity.io/`   | [Configuring Composer](/setup-apps-os/artifact-server/configuring-package-managers/composer) |

The OS-level ecosystems (`rpm.sealsecurity.io`, `deb.sealsecurity.io`, `apk.sealsecurity.io`) are documented under [Seal OS in CI/CD](/setup-apps-os/seal-os-cicd).

## Multiple remotes and ordering

Most teams run the Seal Artifact Server alongside one or more other remotes (a private registry for internal packages, sometimes the public registry directly). The order matters because it affects whether Seal sees all pulls or only the sealed ones. See [Artifact server mode](/discovering/package-discovery-mode/artifact-server#what-it-sees) for the two configurations and what each one shows in Seal's view.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server): pinning sealed versions in the manifest, with direct and transitive override mechanisms.
* [JFrog Artifactory as your remote](/setup-apps-os/artifact-server/jfrog-artifactory): integrating Seal as a remote inside an existing JFrog tenant.


# Configuring npm

Point npm at the Seal Artifact Server using a per-project .npmrc.

npm reads registry configuration from `.npmrc` files (global, per-user, and per-project). We recommend a per-project `.npmrc` in the repository root so the configuration is version-controlled with the manifest.

## Configuration

Create or edit `.npmrc` in the project root:

```ini
registry=https://npm.sealsecurity.io/
//npm.sealsecurity.io/:username=<project-id>
//npm.sealsecurity.io/:_password=<token-base64>
//npm.sealsecurity.io/:always-auth=true
```

Replace `<project-id>` with the Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) as a literal value. Replace `<token-base64>` with the base64 encoding of your production token:

```bash
echo -n "$SEAL_TOKEN" | base64        # macOS
echo -n "$SEAL_TOKEN" | base64 -w0    # Linux
```

npm decodes the `_password` field with base64. The raw token is not a valid base64 string even though it looks like one, so the encoding step is mandatory.

The `.npmrc` may still refer to other registries for privately scoped packages. Only the default registry is replaced.

## Verify

```bash
npm -d ping
```

A successful response shows the ping going through `https://npm.sealsecurity.io/`:

```
npm notice PING https://npm.sealsecurity.io/
npm notice PONG
```

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/npm): pinning the sealed version in `package.json`, with direct and transitive (`overrides`) examples.


# Configuring Yarn

Point Yarn at the Seal Artifact Server, with separate paths for Yarn v1 and Yarn v2+.

Yarn's registry configuration depends on the major version. Classic Yarn (v1) reads `.npmrc` files like npm; Yarn v2+ (Berry) uses `.yarnrc.yml`.

## Classic Yarn (v1)

Yarn v1 reads `.npmrc`. The configuration is identical to [Configuring npm](/setup-apps-os/artifact-server/configuring-package-managers/npm):

```ini
registry=https://npm.sealsecurity.io/
//npm.sealsecurity.io/:username=<project-id>
//npm.sealsecurity.io/:_password=<token-base64>
//npm.sealsecurity.io/:always-auth=true
```

`<token-base64>` is the base64 encoding of your token (npm decodes the `_password` field as base64).

## Yarn v2+ (Berry)

Yarn v2 and later use `.yarnrc.yml`. Create or edit the file in the project root:

```yaml
npmRegistries:
  "https://npm.sealsecurity.io":
    npmAlwaysAuth: true
    npmAuthIdent: <auth-ident>

npmRegistryServer: "https://npm.sealsecurity.io"
```

The `<auth-ident>` value depends on the exact Yarn version:

* **Yarn v2**: the base64 encoding of `<project-id>:<token>`, computed as `echo -n "<project-id>:<token>" | base64`.
* **Yarn v3+**: the literal string `"<project-id>:<token>"` (no base64 encoding).

Yarn Berry also requires `yarnPath` to point at the bundled Yarn release in `.yarn/releases/yarn-<version>.cjs`; that line is typically already present in projects using Berry.

## Verify

For Classic Yarn:

```bash
yarn config get registry
```

The output should be `https://npm.sealsecurity.io/`.

For Yarn Berry, run a clean install (`yarn install`) and confirm the resolved packages come from `npm.sealsecurity.io`.

## Related

* [Configuring npm](/setup-apps-os/artifact-server/configuring-package-managers/npm): the equivalent setup for npm itself.
* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/yarn): manifest editing with the `resolutions` field (Yarn's transitive-override mechanism).


# Configuring pnpm

Point pnpm at the Seal Artifact Server using a per-project .npmrc.

pnpm reads registry configuration from `.npmrc` files, the same as npm. The configuration is identical.

## Configuration

Create or edit `.npmrc` in the project root:

```ini
registry=https://npm.sealsecurity.io/
//npm.sealsecurity.io/:username=<project-id>
//npm.sealsecurity.io/:_password=<token-base64>
//npm.sealsecurity.io/:always-auth=true
```

Replace `<project-id>` with the Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) as a literal value. Replace `<token-base64>` with the base64 encoding of your production token:

```bash
echo -n "$SEAL_TOKEN" | base64        # macOS
echo -n "$SEAL_TOKEN" | base64 -w0    # Linux
```

The `_password` field is base64-decoded by pnpm in the same way as npm, so encoding the token is mandatory.

## Verify

```bash
pnpm config get registry
```

The output should be `https://npm.sealsecurity.io/`. A clean `pnpm install` should resolve packages from the same host.

## Related

* [Configuring npm](/setup-apps-os/artifact-server/configuring-package-managers/npm): the equivalent npm setup, using the same configuration file format.
* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/pnpm): manifest editing with `pnpm.overrides` (pnpm's transitive-override mechanism).


# Configuring Maven

Point Maven at the Seal Artifact Server using pom.xml and settings.xml.

Maven needs the Seal Artifact Server declared as a repository in `pom.xml` and its credentials supplied in the Maven settings file (`~/.m2/settings.xml` on Unix or `%userprofile%\.m2\settings.xml` on Windows).

## Configuration

### Step 1: Add the repository to `pom.xml`

Open the project's `pom.xml`. If there is no `<repositories>` block, add one. Place the Seal repository first so Maven consults it before falling back to other remotes:

```xml
<repositories>
  <repository>
    <id>seal-security</id>
    <url>https://maven.sealsecurity.io/</url>
  </repository>
</repositories>
```

The `<id>seal-security</id>` value links this entry to its credentials in the settings file. Keep them aligned.

### Step 2: Add credentials to `settings.xml`

Open Maven's settings file. Add a `<server>` entry whose `<id>` matches the repository entry above:

```xml
<settings>
  <servers>
    <server>
      <id>seal-security</id>
      <username>${env.SEAL_PROJECT}</username>
      <password>${env.SEAL_TOKEN}</password>
    </server>
  </servers>
</settings>
```

The `${env.SEAL_PROJECT}` and `${env.SEAL_TOKEN}` placeholders read from the build environment, which keeps the credentials out of version-controlled files.

### Step 3: Set the environment variables when building

```bash
SEAL_PROJECT=<project-id> SEAL_TOKEN=<token> mvn package
```

In CI, set the two variables once at the job level rather than per command.

## Verify

A clean build that resolves at least one dependency should pull from `https://maven.sealsecurity.io/`. Run with `-X` (debug) to see the resolved-from URL in the output if you want to confirm explicitly.

## Related

* [Maven-specific server features](/setup-apps-os/artifact-server/maven-server-features): `+safest`, `+safest-until-<cutoff>`, and the redirect policy for non-sealed artifacts.
* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/maven): pinning sealed versions in `pom.xml`, with the `<dependencyManagement>` block for transitive overrides.
* [Configuring Gradle](/setup-apps-os/artifact-server/configuring-package-managers/gradle): the JVM-ecosystem equivalent for Gradle builds.


# Configuring Gradle

Point Gradle at the Seal Artifact Server using build.gradle and gradle.properties.

Gradle's repository configuration lives in `build.gradle` (or `build.gradle.kts` for Kotlin DSL). Credentials are read from `gradle.properties` or environment variables.

## Configuration

### Step 1: Add the repository to `build.gradle`

In the `repositories` block of the project's (or app's) `build.gradle`, add the Seal Artifact Server. Place it before built-in remotes like `mavenCentral()` and `google()` so Gradle consults it first:

```gradle
repositories {
    maven {
        credentials {
            username "$sealUser"
            password "$sealToken"
        }
        url "https://maven.sealsecurity.io"
    }
    mavenCentral()
    google()
}
```

The `$sealUser` and `$sealToken` references resolve against project properties.

### Step 2: Provide the credentials

Add the properties to `gradle.properties` in the project root:

```properties
sealUser=<project-id>
sealToken=<token>
```

For CI, set the same properties as environment variables (`ORG_GRADLE_PROJECT_sealUser` and `ORG_GRADLE_PROJECT_sealToken`) rather than committing the token to source.

## Verify

A clean build that resolves at least one dependency pulls from `https://maven.sealsecurity.io/`. Use `gradle dependencies --info` to see the resolved-from URL if you want to confirm explicitly.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/gradle): the JVM-ecosystem version-pinning patterns, including `resolutionStrategy.force` for transitive overrides in Gradle.
* [Configuring Maven](/setup-apps-os/artifact-server/configuring-package-managers/maven): the JVM-ecosystem equivalent for Maven builds.


# Configuring Go

Point Go modules at the Seal Artifact Server using the GOPROXY environment variable.

Go modules read the proxy URL from the `GOPROXY` environment variable. The Seal Artifact Server is set up as the first entry, with `direct` as the fallback so packages that Seal does not serve still resolve from their upstream sources.

## Configuration

Set `GOPROXY` before running `go mod download` or `go build`:

```bash
export GOPROXY="https://<project-id>:<token>@go.sealsecurity.io,direct"
go mod download
```

Replace `<project-id>` with the Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) and `<token>` with your production token. The credentials ride in the URL's userinfo block.

In CI, set `GOPROXY` once at the job level rather than per command.

## Verify

```bash
GOPROXY="https://<project-id>:<token>@go.sealsecurity.io,direct" go mod download -x
```

The `-x` flag prints each network operation; the output should show requests to `go.sealsecurity.io` for the modules Go fetches.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/go): pinning sealed versions in `go.mod` and using the `replace` directive for transitive overrides.


# Configuring pip

Point pip at the Seal Artifact Server using a URL with embedded credentials.

pip accepts the registry URL in any of three places: the command line, a `pip.conf` config file, or a `requirements.txt` directive. The URL embeds the Project ID as the username and the token as the password.

## Configuration

The shared URL form is:

```
https://<project-id>:<token>@pypi.sealsecurity.io/simple
```

### Option 1: Command line

```bash
pip install --index-url https://<project-id>:<token>@pypi.sealsecurity.io/simple <package>
```

### Option 2: `pip.conf`

Edit `~/.pip/pip.conf` (Linux/macOS) or `%APPDATA%\pip\pip.ini` (Windows):

```ini
[global]
index-url = https://<project-id>:<token>@pypi.sealsecurity.io/simple
```

### Option 3: `requirements.txt`

Add the `--index-url` directive at the top of the file:

```
--index-url https://<project-id>:<token>@pypi.sealsecurity.io/simple

requests==2.31.0+sp1
```

## Verify

A clean install (`pip install -r requirements.txt` or `pip install --upgrade <package>`) should resolve packages from `pypi.sealsecurity.io`. Run `pip install -v ...` to see the URL pip is fetching from.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/pip): pinning sealed versions in `requirements.txt`.
* [Configuring Poetry](/setup-apps-os/artifact-server/configuring-package-managers/poetry): the Poetry equivalent for the same ecosystem.


# Configuring Poetry

Point Poetry at the Seal Artifact Server using poetry source add.

Poetry configures package sources through the `poetry source` command. Adding Seal as the default source is a one-line operation.

## Configuration

From the project root:

```bash
poetry source add --default seal https://<project-id>:<token>@pypi.sealsecurity.io/simple
```

Replace `<project-id>` with the Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) and `<token>` with your production token. The credentials ride in the URL's userinfo block.

This writes the source to the project's `pyproject.toml`. Commit the change so the configuration is version-controlled with the manifest.

## Verify

```bash
poetry config repositories
```

The output should list `seal` with the `pypi.sealsecurity.io` URL. A `poetry install` then resolves packages from that source.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/poetry): pinning sealed versions in `pyproject.toml`.
* [Configuring pip](/setup-apps-os/artifact-server/configuring-package-managers/pip): the pip equivalent for the same ecosystem.


# Configuring Bundler

Point Bundler at the Seal Artifact Server using a credentialed source in the Gemfile.

Bundler reads gem sources from the `Gemfile`. To replace the default RubyGems source with Seal, swap the `source` line and supply credentials in the URL.

## Configuration

Open the project's `Gemfile`. Find the existing source line, typically:

```ruby
source 'https://rubygems.org'
```

Replace it with the Seal source, reading the credentials from the environment so they do not get checked into source control:

```ruby
source "https://#{ENV['SEAL_PROJECT']}:#{ENV['SEAL_TOKEN']}@ruby.sealsecurity.io"
```

`SEAL_PROJECT` is your Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name). `SEAL_TOKEN` is your production token. Set both in the build environment when running Bundler.

```bash
SEAL_PROJECT=<project-id> SEAL_TOKEN=<token> bundle install
```

## Verify

A clean `bundle install` resolves gems from `ruby.sealsecurity.io` instead of `rubygems.org`. Use `bundle config get sources` or run with `--verbose` to see the resolved-from URL explicitly.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/bundler): pinning sealed versions in `Gemfile`.


# Configuring NuGet

Point NuGet at the Seal Artifact Server using a NuGet.config package source.

NuGet configures package sources through `NuGet.config` files. The Seal Artifact Server is registered as a package source, with credentials supplied either in `NuGet.config` directly or through a credential provider.

## Configuration

Create or edit `NuGet.config` in the project root (or the solution root):

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="seal" value="https://nuget.sealsecurity.io/v3/index.json" />
  </packageSources>
  <packageSourceCredentials>
    <seal>
      <add key="Username" value="<project-id>" />
      <add key="ClearTextPassword" value="<token>" />
    </seal>
  </packageSourceCredentials>
</configuration>
```

Replace `<project-id>` with the Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) and `<token>` with your production token.

`ClearTextPassword` stores the token literally; for CI, prefer passing credentials at runtime through `nuget sources update` or an environment-based credential provider rather than committing them.

## Verify

```bash
dotnet nuget list source
```

The output should include `seal` pointing at `https://nuget.sealsecurity.io/`. A clean `dotnet restore` should then resolve packages from that source.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/nuget): pinning sealed versions in `*.csproj`.


# Configuring Composer

Point Composer at the Seal Artifact Server by replacing the Packagist repository.

Composer configures package sources through the `composer config` command. The Seal source replaces the default Packagist repository, and authentication is set separately as an HTTP Basic credential.

## Configuration

From the project root, run:

```bash
# Configure the Seal repository as the default
composer config repos.packagist composer https://packagist.sealsecurity.io/

# Configure HTTP Basic credentials for the Seal host
composer config --auth http-basic.packagist.sealsecurity.io <project-id> <token>
```

Replace `<project-id>` with the Seal [Project ID](/getting-started/creating-a-seal-project#project-id-and-project-name) and `<token>` with your production token.

The first command writes the repository to the project's `composer.json`. The second writes the credentials to `auth.json` (project-local) or `~/.composer/auth.json` (global). Keep `auth.json` out of version control.

## Verify

A clean `composer install` resolves packages from `packagist.sealsecurity.io`. Run with `-v` to see the URL Composer is fetching from.

## Related

* [Editing dependency files manually](/using-platform/working-with-seal-apps/artifact-server/composer): pinning sealed versions in `composer.json`.




---

[Next Page](/llms-full.txt/1)

