If you run the open source program office at a company with a thousand or more engineers, write one intake policy, not three. It should have one request, three rule sets (license, known vulnerabilities, maintainer health), one decision record and one exception process with an expiry date. Then enforce it on the build, not in a wiki.
This guide walks through why legal, security and engineering keep asking you for separate rules, which standards actually require what, and how to write the policy, the decision table, the request form and the exception record so they work with the tools you already have. Safeguard comes in near the end, in a section of its own.
Key takeaways
- One intake policy beats separate license, security and architecture reviews, as long as each rule set has a named owner and a clear outcome: accept, accept with conditions, review or reject.
- ISO/IEC 5230 (OpenChain license compliance) asks for a written policy and a bill of materials with each component's identified licenses. ISO/IEC 18974 (OpenChain security assurance) asks that every component in that bill of materials gets known vulnerability checks and a documented response.
- NIST SP 800-218 task PW.4.4 asks you to verify that open source components meet your requirements "throughout their life cycles", which is why intake cannot be a one-time gate.
- CISA's 2026 Minimum Elements for an SBOM add a Component License element. If your intake records do not carry SPDX license identifiers, fix that first.
- Maintainer health should be judged with a few observable signals (recent commits, recent releases, more than one maintainer, archived or not) plus a plan for when a project goes quiet. Star counts are not one of them.
- Exceptions need a named approver, a justification and an expiry date that actually re-runs the check.
- In Safeguard, the pieces map to license compliance (GA), policies, gates and guardrails (GA), software composition analysis with deep transitive scanning (GA), SBOM generation and analysis (GA), vulnerability management with EPSS and KEV (GA), reachability analysis (GA), Open Source Manager (GA), the Safeguard CLI (GA) and autonomous remediation (GA, ships switched off).
The situation
The request usually arrives as three separate emails in the same month. The general counsel wants a written open source policy that a customer's procurement team or an acquirer's diligence team will accept. The CISO wants new dependencies checked against known exploited vulnerabilities before they reach production, because the last incident review showed a library nobody had approved. And the VP of Engineering wants all of it to be one form and one check on the pull request, because developers are already filling in an architecture review and a security questionnaire for anything new.
You own the open source program office, so all three land on you, usually with a quarter-end date attached.
At a company with a thousand or more engineers, the numbers make the shape of the problem clear. As an illustrative example with round numbers: 400 active repositories, 60 requests a week to add a new direct dependency, and each direct dependency pulling in somewhere between a handful and a few hundred transitive ones. Nobody can read 60 licenses and 60 vulnerability reports a week by hand, and nobody can audit the transitive tail at all without tooling. Redo that sum with your own repository count and your own pull request history before you size anything.
A bad week looks like this. A release candidate for your downloadable SDK picks up a strong copyleft library three levels down, and nobody notices until a customer's legal team runs their own scan. The same week, a service team adds a parsing library whose current version sits on CISA's Known Exploited Vulnerabilities catalog, because the license review approved it and nobody asked about security. The library's last release was two years ago and its only maintainer has moved on. Three reviews, three owners, three gaps, and the developer who added both did nothing wrong under the rules as written.
The fix is not more reviewers. It is one policy with three rule sets, evaluated together, with one record of what was decided and why. If you want the argument for merging license and security rules on its own, read should license and security rules live in one policy; for the wider governance model around it, see how to build an OSPO security governance model.
The standards behind one intake policy
None of this is legal advice. The point of this section is to show which published standards ask for which part of intake, so you can tell legal, security and engineering that the policy is built on something other than preference. Read the standards yourself; the clause numbers below come from their published text.
ISO/IEC 5230: a written policy and a bill of materials with licenses
ISO/IEC 5230:2020 is the international standard version of the OpenChain license compliance specification (the OpenChain Project publishes version 2.1 of the specification as functionally the same text). Three clauses matter most for intake:
- 3.1.1 Policy. "A written open source policy shall exist" that governs license compliance of the supplied software, and it has to be communicated internally. The verification materials are a documented policy and a documented procedure that makes people aware of it.
- 3.3.1 Bill of materials. A process has to exist for "creating and managing a bill of materials" that includes each open source component and its identified licenses. The verification material asks for a documented procedure for "identifying, tracking, reviewing, approving, and archiving" component information, and records that show the procedure was followed.
- 3.3.2 License compliance. The program has to handle common license use cases, including distribution in binary form, distribution in source form, modified open source, incompatible licenses interacting inside the supplied software, and attribution requirements.
Two things follow for an OSPO lead. First, the standard does not tell you which licenses to allow; it tells you to have a policy and a procedure and to keep records. Second, "reviewing, approving, and archiving" is an intake process in all but name. If your intake decisions live in chat threads, you cannot show 3.3.1.2 records.
ISO/IEC 18974: security assurance on the same bill of materials
ISO/IEC 18974:2023 is the OpenChain security assurance specification as an international standard. It mirrors 5230's structure and adds security work on the same inventory. Clause 4.3.2 Security assurance says a process shall exist so that each open source component in the software bill of materials "will have some security assurance activities applied". The listed activities include a method for detecting known vulnerabilities, a risk or impact score for each one, documented remediation or mitigation steps suitable for the use case, and an ability to monitor supplied software after release and respond to new disclosures.
That last item is the reason intake cannot end at the pull request. A component that was clean when it was approved will not stay clean.
NIST SP 800-218: verify components throughout their life cycles
The Secure Software Development Framework, NIST SP 800-218 version 1.1 (February 2022), has a practice for reusing well-secured software, PW.4. Two tasks carry the weight for intake:
- PW.4.1 asks you to acquire and maintain well-secured components from commercial, open source and other third-party developers.
- PW.4.4 asks you to verify that acquired commercial, open source and other third-party components "comply with the requirements, as defined by the organization, throughout their life cycles."
PW.4.4's examples read like an intake checklist. Example 2 is to build automatic detection of known vulnerabilities into the toolchain. Example 4 is to ensure each component "is still actively maintained and has not reached end of life". Example 5 is to determine a plan of action for each component that is no longer maintained. That is the maintainer health rule set, in a federal framework, not just an OSPO preference.
NIST published an initial public draft of SSDF version 1.2 (SP 800-218 Rev. 1) on 17 December 2025, with comments closed on 30 January 2026. Version 1.1 is the final text today. Write your policy against 1.1 and check the final 1.2 text when it lands.
CISA's 2026 Minimum Elements for an SBOM: licenses are now an element
On 29 July 2026 CISA, with the NSA, the FBI and international partners, published the 2026 Minimum Elements for a Software Bill of Materials. It updates and replaces the NTIA minimum elements from 2021. One change matters directly to an OSPO: Component License is a new element. The guidance says the license identifiers should let the receiver find the full license details, should be machine-processable where possible (it points to SPDX license identifiers), should note the existence of proprietary license conditions, and should say the license is unknown when the author does not know it.
If you consume or produce SBOMs, your intake records and your SBOMs now need to agree on licenses, and "unknown" has to be written down as unknown, not left blank.
SPDX license identifiers and expressions
The SPDX License List gives each common license a short identifier (MIT, Apache-2.0, GPL-2.0-only, GPL-2.0-or-later, and so on). The SPDX specification's license expression annex defines how to combine them: OR for a choice between licenses, AND when several apply at once, WITH for a license exception, and LicenseRef- for a license that is not on the list. Your policy should be written in these identifiers, not in free text such as "GPL" or "BSD-style", because "GPL" alone does not tell you which version or whether "or later" applies.
OpenSSF guidance on evaluating a dependency
The OpenSSF Best Practices Working Group's Concise Guide for Evaluating Open Source Software (dated 28 March 2025) is the closest thing to a community checklist for the maintainer and security half of intake. Under "Maintenance and Sustainability" it asks you to confirm significant activity within the previous 12 months, recent releases or announcements, a last release within the previous 12 months, and more than one maintainer, while noting that many widely used projects have one. Under "Security Practices" it asks whether the current version is free of known important vulnerabilities and points to the OpenChain security assurance specification for checking on ingest and as new vulnerabilities appear.
OpenSSF Scorecard turns several of these into automated checks. Its Maintained check gives the highest score to a project with at least one commit per week over the previous 90 days and the lowest to an archived project, and its own documentation says that a lack of activity "is not necessarily always a problem" for small utility code. That caveat belongs in your policy too.
Where the EU fits
If you ship products with digital elements into the EU, the Cyber Resilience Act also bears on how you handle third-party components, open source included. US mandates and standards lead in this guide; treat the EU rules as context, and ask counsel how they apply to your products.
Step by step: build the intake policy, with or without Safeguard
These steps work with any scanner, any ticketing system and any SBOM tool. Each produces something you can use the same day.
1. Decide what counts as an intake event
Most policies fail because they define intake too narrowly. A developer opening a "please approve library X" ticket is one intake event. These are also intake events:
- A pull request that adds a new direct dependency to a manifest.
- A lockfile change that adds a new transitive package, even when no manifest changed.
- A major version bump of an existing dependency (licenses and maintainers change between major versions).
- Vendoring or copying source from an open source project into your repository.
- A new base container image.
- A new CI action, build plugin or code generator.
Write the list into the policy. The automated check should see every one of them, and the human form should only be needed for the ones the automated check cannot decide.
2. Write the license rule set as tiers in SPDX identifiers
Three tiers is enough for most companies: allow, review and deny (we cover the tier model in more depth in a three-tier license policy: allow, review, deny). Write them in SPDX identifiers and get legal to sign them off. The tiers depend on how you ship, so split them by distribution context. A license that is fine inside a hosted service binary can be a problem inside an SDK you distribute.
| Tier | Typical members (legal decides) | SaaS backend | Distributed SDK or on-prem product |
|---|---|---|---|
| Allow | MIT, BSD-2-Clause, BSD-3-Clause, Apache-2.0, ISC | Accept | Accept, with attribution recorded |
| Review | MPL-2.0, LGPL-2.1-only, LGPL-3.0-or-later, EPL-2.0, unknown or custom | Usually accept after review | Review how it is linked and shipped |
| Deny | AGPL-3.0-or-later, SSPL-1.0 for SaaS; GPL-3.0-or-later for distributed code | Reject or exception | Reject or exception |
Two rules make this tier table hold up in practice. First, "unknown" is never "allow". A component with no declared license, or with a license file that disagrees with its manifest, goes to review. Second, for an OR expression, record which license you chose. "MIT OR Apache-2.0" can be accepted under either, but your notices file has to say which.
3. Write the vulnerability rule set around exploitation, not only severity
A rule of "no critical CVEs" blocks too much and too little. It blocks a critical vulnerability in a code path you never call, and it lets through a medium one that is on CISA's Known Exploited Vulnerabilities catalog. A better rule uses three signals together:
- Known exploited. Any vulnerability in the component version that appears in CISA's Known Exploited Vulnerabilities catalog blocks intake, unless a fixed version is chosen.
- Likely to be exploited. FIRST's Exploit Prediction Scoring System publishes, every day, a probability that a published CVE will be exploited in the wild in the next 30 days. Use a threshold you choose to route high-probability findings to review.
- Severity. Critical and high severity findings route to review; below that, record and monitor.
Add one more rule that saves weeks of argument: if a fixed version of the same component exists and is compatible, intake approves the fixed version, not the vulnerable one. The request does not need to come back.
4. Write the maintainer health rule set as observable signals
Maintainer health is where policies get vague. Keep it to signals anyone can check and a decision for each.
| Signal | Where it comes from | Healthy | Route to review when |
|---|---|---|---|
| Archived or deprecated | Repository or registry status | Not archived | Archived, deprecated or marked end of life |
| Recent activity | Commit history | Commits in the last 12 months | No commits in 12 months |
| Recent release | Registry release history | A release in the last 12 months | No release in 12 months |
| Maintainer count | Project governance files, commit authors | More than one maintainer | A single maintainer on a component that will be widely used |
| Security response | Advisories, security policy file | Has a security policy and fixes advisories | Open known vulnerabilities with no response |
| Version stability | Version string | 1.0 or later | 0.x, alpha or beta in production code |
The OpenSSF Concise Guide and Scorecard both warn that inactivity is not always a problem. A small, finished utility library may not need commits. So "route to review" is the outcome here, not "reject". The review question is the one PW.4.4 Example 5 asks: what is the plan if this component is no longer maintained? Acceptable answers include "we can fork and maintain it", "it is small enough to replace in a sprint" or "we will pin it and monitor for advisories".
5. Combine the three into one decision table
This is the core of the policy. Every intake event gets one outcome.
| License tier | Vulnerability state | Maintainer health | Outcome |
|---|---|---|---|
| Allow | No known vulnerabilities, or only low | Healthy | Accept automatically |
| Allow | High or critical with a fixed version | Healthy | Accept the fixed version automatically |
| Allow | Known exploited, no fixed version | Any | Reject, or exception with an expiry and a mitigation |
| Allow | Clean | Review signal | Accept with conditions: named owner and an exit plan |
| Review | Any | Any | Human review by the license owner, then re-run |
| Deny | Any | Any | Reject, or exception approved by legal with an expiry |
| Unknown | Any | Any | Review; never accept automatically |
Most requests should land in the first two rows. If more than a small share of requests need a human, the tiers are too tight or the vulnerability rule is too blunt. Track that share as a metric (step 9).
6. Write a request form that asks only what tooling cannot answer
Tooling can find the license, the vulnerabilities and the maintenance signals. It cannot know why the team needs the component or how it will ship. Ask only that.
| Field | Why it is there |
|---|---|
| Component name, ecosystem and version | Identity; must match the manifest |
| Requesting team and named owner | Someone answers for the component later |
| Purpose, in one sentence | Lets reviewers ask "could an existing component do this?" |
| How it ships: hosted service, distributed binary, SDK, on-prem, internal tool | Picks the license context |
| Modified or unmodified | Changes license obligations |
| Alternatives considered | Speeds up a review that ends in "use X instead" |
| Exit plan if unmaintained | Required only when the maintainer health check routes to review |
Keep it to one screen. Every field you add costs developer time multiplied by your request volume.
7. Write the exception record
Exceptions are where intake policies quietly fail. An exception with no expiry is a permanent approval with worse paperwork. For a fuller treatment of the waiver itself, see a license exception process with expiry. Every exception record should have:
| Field | Rule |
|---|---|
| Component and version | Exact, not "latest" |
| Policy rule it overrides | License, vulnerability or maintainer rule, by name |
| Business justification | Specific, one paragraph |
| Mitigation | What reduces the risk while the exception is open |
| Named approver | Legal for license exceptions, security for vulnerability exceptions |
| Expiry date | Required; 90 days is a common default for vulnerabilities |
| Re-check on expiry | The rule runs again; the exception does not silently renew |
8. Decide what to do with what you already have
On day one your estate already contains thousands of components that never went through intake. If you turn on a blocking rule across all of them, every build fails and the policy dies in its first week. Grandfather existing components at a dated snapshot: record them, run the same rules in report-only mode, and set a date by which deny-tier licenses and known exploited vulnerabilities in existing code must be fixed or covered by an exception. Enforce the full policy on new intake events from day one. The trade-offs are covered in grandfathering existing dependencies when you start intake.
9. Measure the program
Pick numbers that show whether intake is working, not just whether it is busy:
- Share of intake events decided automatically.
- Median time from request to decision for the ones that need a human.
- Open exceptions, and how many are past expiry (the target is zero).
- New deny-tier licenses introduced per month (the target is zero).
- Components in production with a known exploited vulnerability, and how long each has been open.
- Components flagged for maintainer health, and how many have an exit plan.
Report them monthly to legal, security and engineering together. One report is part of the point of one policy.
Who owns which rule set
One policy does not mean one owner for everything. It means one process with clear owners per rule set.
| Rule set | Owner who writes it | Owner who approves exceptions | OSPO's role |
|---|---|---|---|
| License tiers | Legal | Legal | Run the process, keep records, train developers |
| Vulnerability rule | Security | Security | Make sure the rule runs on every intake event |
| Maintainer health | OSPO with engineering | Engineering owner of the component | Publish the signals and the exit plan template |
| Request form and decision table | OSPO | Not applicable | Own it end to end |
| Records and reports | OSPO | Not applicable | Keep the evidence for ISO/IEC 5230 3.3.1 and 18974 4.3.2 |
When legal and security disagree about a component, the decision table decides: the stricter outcome wins, and the exception process is the only way around it.
How strict should the policy be on day one?
Start with Warn for review-tier outcomes, Block only for deny-tier licenses and known exploited vulnerabilities on new intake events, and Notify for maintainer health signals. Tighten after a month of data. A policy that blocks a large share of pull requests in week one gets bypassed; a policy that blocks the two things nobody can defend gets respected.
How Safeguard does this
Everything above works with any tooling. This section shows how the same policy maps onto Safeguard, using only what Safeguard's documentation shows. Where the docs do not show a screen or a command, this guide describes the outcome instead.
-
Build the inventory with licenses. Connect your repositories so Safeguard's software composition analysis (GA), with deep transitive dependency scanning (GA), and SBOM generation and analysis (GA) build the bill of materials. License compliance (GA) identifies licenses from package metadata, SPDX identifiers, full-text matching of LICENSE, COPYING and NOTICE files, source file headers and, in container layers, copyright files. When those signals disagree (for example, a manifest says MIT and the license file says something else), Safeguard raises a license-discrepancy finding, which is exactly the "unknown goes to review" case from step 2. License data lives in the SBOM view, and the Suppliers and Licenses tab on a project shows the license summary, categories and compliance status.
-
Write the license tiers as a policy. Safeguard's license compliance docs show the allow, deny and review tiers declared in YAML, with overrides by context. This is the docs' own example, unchanged:
apiVersion: safeguard.sh/v1
kind: LicensePolicy
metadata:
name: default
spec:
allow:
- MIT
- BSD-2-Clause
- BSD-3-Clause
- Apache-2.0
- ISC
- MPL-2.0
deny:
- GPL-3.0-or-later
- AGPL-3.0-or-later
- SSPL-1.0
require_review:
- GPL-2.0-only
- LGPL-3.0-or-later
- "Custom/*"
context_overrides:
- apply_to: { env: sdk }
deny:
- LGPL-3.0-or-later # LGPL tricky in SDK distribution
- apply_to: { env: server }
allow:
- LGPL-3.0-or-later # fine for a service binary
The docs say policies can be scoped to asset labels, so your SDK repositories and your SaaS backend can carry different tiers, as in step 2. Safeguard parses full SPDX expressions, including OR, AND and WITH; for an OR expression the docs say the most permissive option that matches your policy is chosen automatically. The docs do not spell out what a gate does with a match on the review list, so in your own setup route review-tier licenses to a policy with the Warn action and record each approval as an exception (steps 5 and 7 below). The example above was taken from the docs and was not run for this guide.
-
Add the vulnerability and maintainer rules as policies. Policies, gates and guardrails (GA) are created under Settings, Policies, Create Policy, with a visual builder or YAML. The policy conditions the docs list map onto the three rule sets: license (for example, no GPL licenses), vulnerability severity, CVSS score, EPSS score, component age and maintenance (no abandoned packages). Pre-built templates include License Compliance, No Critical Vulnerabilities and No Abandoned Packages. Safeguard's built-in "Abandoned package" guardrail is defined in the docs as a package with zero commits in 365 days and a CVE open for more than 180 days, which is a narrower test than "no commits in 12 months" and a good fit for a Block rule, with your broader maintainer health check left on Notify. Policy creation from plain English prompts (GA) is also available if your team prefers to describe a rule in words first.
-
Choose an action per policy: Block, Warn or Notify. Each policy has one action that decides what a failed policy does to its gate. Block fails the gate. Warn lets the gate pass with a warning that names the policy. Notify lets the gate pass and sends a notification to the workspace's configured channels, and it only notifies again when the failure changes or new matches appear, so it does not spam. The gate's outcome follows a fixed order: any failed Block policy fails the gate; a policy that could not be evaluated is an Error, which never counts as a pass; a failed Warn policy gives a Warning. This maps directly onto the day-one strictness above: Block for deny-tier licenses and known exploited vulnerabilities, Warn for review-tier licenses, Notify for maintainer health. Policy outcomes are turned on per workspace by Safeguard; if your workspace has no Outcome column on the Gates and Policies tables, the docs say to ask your Safeguard contact.
-
Enforce on every intake event in CI. Gates are evaluated by the platform on the scans it runs for your connected repositories. To make a CI job fail when the intake gate fails, the docs show this command in the Safeguard CLI (GA):
safeguard ci scan --wait --fail-on-gate <gate name or id | all>
It waits for the scan and the gate's policies, exits 0 when the gate is Passed or Warning (printing warnings and notified policies), and exits non-zero when the gate is Failed, Error or Not evaluated, printing why. Because the scan runs on the repository's dependency tree, a lockfile change that adds a transitive package is evaluated the same way as a new direct dependency, which covers the intake events from step 1. The docs also say a new direct dependency with a deny-listed license gets a blocking check at pull request time, and findings show the transitive path so a reviewer can see which direct dependency pulled the license in. The command above was taken from the docs and not run for this guide.
-
Check a component before anyone asks for it. Open Source Manager (GA) has a package security database where you search by package name or CVE. For each package the docs list version history with security status, known vulnerabilities, severity distribution, the SPDX license identifier and a maintainer status indicator. Its "Pre-Installation Review" use case is the intake pre-check: known vulnerabilities, maintenance status and license compatibility before a dependency is added. Point developers there before they open a request, and most requests arrive already answered.
-
Run exceptions with an approver and an expiry. From a failing finding, a developer clicks Request Exception, selects the policy and finding, gives a business justification and sets an expiration date. Approvers are notified, decide, and the decision goes into the audit trail. License exceptions follow the same workflow as vulnerability exceptions, with a named approver, an expiry date, a documented justification, and automatic expiry and re-evaluation at the end. For a blocking guardrail, emergency breakglass exceptions need two-person approval and alert the security channel. This is the exception record from step 7, held in the product rather than a spreadsheet.
-
Prioritise the vulnerability side. Vulnerability management (GA) brings CVE detection with EPSS and CISA KEV enrichment, and reachability analysis (GA) ranks findings by whether your code actually calls the vulnerable path. Use both to keep the vulnerability rule from blocking intake for vulnerabilities in code you never call, while still blocking known exploited ones.
-
Produce the records and notices. The Licenses dashboard shows license distribution across your fleet, new license introductions over time (new obligations adopted), and policy violation count and trend, with a per-asset license manifest you can export to Excel, CSV, SPDX or CycloneDX. For redistributed artifacts, Safeguard generates a NOTICE or THIRD-PARTY-NOTICES file, a licenses directory with each required license text, and an SPDX document per release. Policy compliance reports cover status by policy, exception history and violation trends. Together these are the ISO/IEC 5230 3.3.1.2 records and the monthly metrics from step 9.
-
Fix what intake finds in existing code. For the grandfathered backlog (step 8), autonomous remediation (GA) can open fix pull requests, including in a License category alongside dependencies and findings. It ships switched off, with every category set to Manual, so nothing changes until your team turns it on and chooses how much runs on its own.
-
Apply the same tiers to vendor software. If your intake also covers commercial components that arrive with SBOMs, Safeguard runs the same license classification on vendor SBOMs, flags deny-listed licenses and license changes between versions, and feeds that into the Third-Party Risk Manager (GA) assessments.
Policy section to Safeguard feature, at a glance
| Policy section | What Safeguard does | What you still own |
|---|---|---|
| Intake events | Scans connected repositories; gate runs on each scan | Defining which repositories and branches are in scope |
| License tiers | LicensePolicy allow, deny and review lists, context overrides by label | Legal's choice of tiers |
| Vulnerability rule | Severity, CVSS and EPSS conditions; KEV and reachability context | Thresholds and the fixed-version rule |
| Maintainer health | Maintenance condition, No Abandoned Packages template, OSM maintainer status | The exit plan and the judgment call |
| Decision table | Block, Warn and Notify actions per policy, gate outcome order | Mapping your table onto actions |
| Exceptions | Request Exception flow, approver, expiry, audit trail | Who approves and what justification is enough |
| Records | Licenses dashboard, exports, attribution files, compliance reports | Keeping the policy document and training records |
What Safeguard does not do
- It does not choose your license tiers or interpret licenses for you. The classifications and explanations help, but which licenses your company allows, and how a given license applies to how you ship, is legal's decision. Safeguard enforces the tiers you write.
- The CLI does not evaluate license policy yet. The docs say there is no CLI command for license listing, reports or policy evaluation;
safeguard scanwrites a license.json with the licenses it found, and it does not fail the build on findings. Gate enforcement in CI runs throughsafeguard ci scan --wait --fail-on-gateagainst platform gates. There is also no CLI command for generating attribution files yet. - Kubernetes admission enforcement is not available yet. The guardrails docs say the admission controller is not published, so "denied licenses cannot deploy to production" at admission is not something to plan around today. Enforce at CI and pull request time.
- Policy outcomes are switched on per workspace. Until Safeguard turns them on for your workspace, the Outcome column and gate-based CI failure are not there.
- The documented REST endpoints for suppliers and licenses are not live. The Suppliers and Licenses docs carry a banner that the
/v1paths return 404 today. Use the app, the CLI and CI instead of building on those endpoints. - Maintainer health is a signal, not a verdict. A maintenance condition or an abandoned package template cannot tell whether a quiet project is finished or abandoned, or whether its single maintainer is reliable. The exit plan is still your team's work.
- It does not run your outbound open source work. Contributing upstream, contributor license agreement review and releasing your own projects are OSPO duties this guide does not cover and the Safeguard docs used here do not describe.
- It does not ship notices into your product for you. Safeguard generates attribution files; putting them in the installer, the about screen or the documentation, and keeping them current, is a release task.
Common mistakes
- Three policies with three owners and no shared record. Each review passes the component for its own reasons and nobody sees the whole picture. One decision record per intake event fixes most of this.
- Writing licenses in free text. "No GPL" does not say which versions or whether LGPL counts. Use SPDX identifiers and expressions.
- Treating unknown as permissive. A missing license is not permission. Route it to review and record it as unknown, which is also what CISA's 2026 minimum elements expect in an SBOM.
- One license tier table for SaaS and distributed code. Network copyleft is the concern for hosted services; strong copyleft in distributed binaries is the concern for SDKs and on-prem products. Split by context.
- A vulnerability rule built only on CVSS. It blocks unreachable criticals and misses known exploited mediums. Combine KEV, EPSS and severity, and approve the fixed version automatically.
- Exceptions with no expiry. They become permanent approvals. Every exception needs an end date that re-runs the rule.
- Blocking everything on day one. Grandfather existing components at a dated snapshot and enforce strictly on new intake events.
- Checking only manifests. Lockfile changes, vendored code, base images and CI actions are intake events too.
- Judging maintainers by stars or downloads. Popularity says nothing about whether someone will ship a fix next month. Use activity, releases, maintainer count and security response.
- Keeping the policy in a wiki only. If the build does not enforce it, it is a suggestion.
FAQ
What is an open source intake policy?
It is the written rule set a company uses to decide whether a new open source component can be used, and under what conditions. A complete one covers licenses, known vulnerabilities and maintainer health, defines which events count as intake, and says who approves exceptions and for how long.
Should license and security review be one process or two?
One process with two rule sets and two owners. Legal owns the license tiers and security owns the vulnerability rule, but the developer files one request, the build runs one check, and the company keeps one decision record. Separate processes produce gaps where each side assumes the other looked.
Does ISO/IEC 5230 tell me which licenses to allow?
No. Clause 3.1.1 requires a written open source policy and 3.3.1 requires a bill of materials with each component's identified licenses, but the standard does not prescribe which licenses are acceptable. That choice belongs to your legal team and depends on how you ship.
What is the difference between ISO/IEC 5230 and ISO/IEC 18974?
ISO/IEC 5230 covers open source license compliance; ISO/IEC 18974 covers security assurance for open source. They share a structure, and 18974's clause 4.3.2 asks that each component in the software bill of materials gets known vulnerability detection, a risk score, documented remediation or mitigation, and monitoring after release.
How do I measure maintainer health for an open source dependency?
Use a few signals you can observe: whether the project is archived, commits in the last 12 months, a release in the last 12 months, more than one maintainer, and whether it responds to security advisories. The OpenSSF Concise Guide and Scorecard both use signals like these. Treat a weak signal as a reason for review and an exit plan, not an automatic rejection.
Should a high-severity CVE block a new dependency?
Not on severity alone. Block when the vulnerable version is on CISA's Known Exploited Vulnerabilities catalog and no usable fixed version exists, route high EPSS or high severity findings to review, and approve the fixed version automatically when one exists and is compatible.
How long should an open source exception last?
Long enough to fix the issue and no longer. Many teams use 90 days for vulnerability exceptions and tie license exceptions to a specific release. The important part is that the exception expires and the rule runs again; an exception that silently renews is a permanent approval.
Do transitive dependencies need to go through intake?
Their licenses and vulnerabilities do, because they ship in your product. Developers should not file a form for each one; the automated check should evaluate the full tree on every build and only send a transitive component to a human when it hits a review or deny outcome.
What should an OSPO do about dependencies that existed before the policy?
Grandfather them at a dated snapshot, run the rules in report-only mode, and set a deadline for deny-tier licenses and known exploited vulnerabilities in existing code to be fixed or covered by an exception. Enforce the full policy on new intake events from the first day.
Do SBOMs need license information now?
CISA's 2026 Minimum Elements for an SBOM, published 29 July 2026, add Component License as a new element, recommend machine-processable identifiers such as SPDX license identifiers, and say an unknown license should be recorded as unknown.
After intake: fixing what gets through
An intake policy decides what gets in; it does not fix what is already in, or what turns vulnerable after approval. The section below covers how Safeguard closes the gap between a finding and a fix, which is the follow-through clause 4.3.2 of ISO/IEC 18974 and task PW.4.4 of the SSDF both expect.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.
3. Gold Registry: start from components that are already fixed
Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | Safeguard policies and gates in CI |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real Safeguard CLI session. It installs the CLI, opens the interactive terminal with safeguard, and asks it to fix a lodash CVE in a repository; the CLI reads the finding and advisory, asks before any command that changes something, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing. It then shows /permissions, /model and /scan. For an OSPO, it shows the developer side of the "approve the fixed version" rule: the fix happens in the repository, with a person approving each change.
Click through it at your own pace, or open it full screen.
The second demo sets up the local runner on your own machine, approves it with its device code, then scans from the terminal. It is the quickest way to see what the inventory step looks like on a repository before you connect anything centrally, and to show developers what the intake check will see.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and chooses which tools Claude can use. For an OSPO that answers a stream of "can we use this library?" questions, it shows how an assistant can be given scoped access, tool by tool, to the same data the policy uses, so answers come from your records rather than from memory.
Click through it at your own pace, or open it full screen.
Quick check
A pull request only changes a lockfile and adds a new transitive package under AGPL-3.0-or-later to a SaaS service. Is that an intake event?
Yes. A lockfile change that adds a new transitive package is an intake event, and AGPL-3.0-or-later is a deny-tier license for hosted services in most policies. The automated check should catch it and the outcome is reject, or an exception approved by legal with an expiry.
A candidate library has no commits for 14 months but is small, finished and has no known vulnerabilities. Should intake reject it?
Not automatically. Inactivity routes it to review, and the review asks for an exit plan, as SSDF task PW.4.4 Example 5 suggests. If the team can fork or replace it quickly and pins the version, accept it with conditions and a named owner.
Sources
- OpenChain Specification 2.1 (ISO/IEC 5230:2020 text), OpenChain Project
- ISO/IEC 18974:2023 OpenChain security assurance specification, OpenChain Project
- NIST SP 800-218, Secure Software Development Framework version 1.1 (PDF)
- NIST SP 800-218 publication page
- NIST SP 800-218 Rev. 1, SSDF version 1.2 initial public draft
- CISA, 2026 Minimum Elements for a Software Bill of Materials
- CISA, 2026 Minimum Elements for an SBOM (PDF)
- CISA Known Exploited Vulnerabilities Catalog
- FIRST, Exploit Prediction Scoring System
- SPDX License List
- SPDX specification 3.0.1, license expressions annex
- OpenSSF, Concise Guide for Evaluating Open Source Software
- OpenSSF Scorecard checks documentation
- Safeguard docs: License Compliance
- Safeguard docs: Policies and Gates
- Safeguard docs: Policy outcomes and actions
- Safeguard docs: Guardrails and Enforcement
- Safeguard docs: Suppliers and Licenses
- Safeguard docs: Open Source Manager
- Safeguard docs: OSM License Compliance
- Safeguard docs: CLI usage
To try the flow on your own repositories, download Safeguard and read the Safeguard docs.
Last reviewed: 25 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.