Implementation Guide

    Blocking SSPL Matches from Copilot, Cursor, Claude Code, and Amazon Q with One CI Policy

    Define one SSPL deny rule that does not depend on which assistant wrote the code. Evaluate every pull request in CI with license and origin detection, block on a match, route exceptions to a named human approver, and store a decision record for every outcome. CI is a late checkpoint: it cannot see code that is never committed, and it can only evaluate what its detectors can recognize.

    Where the check runs and how it decides

    1. 1

      1. Collect the change

      Extract added and modified hunks and any changed dependency manifests from the pull request.

    2. 2

      2. Detect license signals

      Scan for license headers, license files, and declared package licenses in the changed content and in newly added dependencies.

    3. 3

      3. Detect origin signals

      Run snippet-level matching against a reference corpus to find code that resembles known licensed sources.

    4. 4

      4. Evaluate the rule

      Compare each finding with the deny list and confidence thresholds to produce allow, block, or escalate.

    5. 5

      5. Route the outcome

      Fail the check on block, open an approval request on escalate, and pass on allow.

    6. 6

      6. Write the record

      Persist the decision record and attach its identifier to the pull request.

    Exceptions, escalation, and the decision record

    • Timestamp, repository, pull request, commit, and the path and lines evaluated
    • Detected license and detector confidence
    • Suspected origin and the detector and corpus version that produced it
    • Policy rule identifier and policy version that was applied
    • Outcome: allow, block, or escalate
    • Approver identity, rationale, and expiry for any exception, plus any assistant label supplied as context

    Treat it as a policy-consistency problem

    GitHub Copilot, Cursor, Claude Code, and Amazon Q Developer each ship their own controls for handling code that resembles public sources. Those controls differ in scope, in how they are configured, and in whether an administrator can enforce them centrally. Choosing the tool with the best filter does not solve the problem for a team that uses several assistants at once, because the weakest setting on any one of them becomes the effective policy.

    The SSPL adds service-source-disclosure obligations that create legal and distribution risk for organizations that ship or host software. Whether your organization should treat it as a deny-listed license is a decision for your legal and security owners. Many teams that allow only OSI-approved licenses will find the SSPL already falls outside their allowlist, and the point is to make that decision explicit and apply it uniformly.

    The practical consequence is that the policy should be written once, in vendor-neutral terms, and applied at a stage every assistant's output must pass through. For most teams that stage is the merge gate in CI. The policy should not assume it knows which assistant produced a change, because commit metadata rarely says so reliably.

    Express the policy as data your CI can evaluate

    Keep the policy in a version-controlled file that is reviewed like any other change. A rule has a small number of fields, and the same file is read by every repository's pipeline. Avoid per-repository copies, which drift.

    The fields below are enough for a first version. Use SPDX identifiers where your detector emits them, since they give the rule an unambiguous license name.

    • Denied licenses: A list that includes SSPL-1.0, plus any other license your legal owners classify as denied.
    • Scope: All added and modified lines in a pull request, including generated files and vendored directories unless explicitly excluded.
    • Match types: License headers and files, dependency manifests, and snippet-level origin matches, each with its own confidence threshold.
    • Outcome by confidence: Block on high-confidence matches, escalate on medium-confidence matches, and allow with a record below the threshold.
    • Exception rule: Who may approve, for how long, and for which repository or path.
    • Required record fields: What every evaluation must write, whether the outcome is allow, block, or escalate.

    What detection can and cannot tell you

    License detection and origin detection answer different questions. License detection reads what the code or its package declares. Origin detection estimates whether a snippet resembles code from a known source and then maps that source to a license. The second step depends on the reference corpus, so a license can be missed when the corpus does not contain the source.

    Expect both false positives and false negatives. Short snippets, common idioms, and boilerplate can match many sources without being derived from any of them. Code that has been renamed, reformatted, or restructured may stop matching. For that reason, tune thresholds on your own repositories before enforcing, and treat the medium-confidence band as a human decision instead of forcing it to allow or block.

    Attribution has the same limit. Unless a tool records its involvement, CI usually cannot tell which assistant wrote a hunk. This is why the rule is written against the content of the change and not the assistant. If your teams add a commit trailer or label naming the assistant, store it in the record as context, but never make enforcement depend on it.

    The limits of CI-stage enforcement

    A CI gate sees only what reaches the repository. Code that a developer pastes locally and never commits is outside its reach. Code that is committed after being altered enough to defeat snippet matching may pass. A gate also acts after generation, so the developer has already received and possibly built on the suggestion by the time the check fails.

    There is also a separate risk surface earlier in the path. The inputs an assistant consumes can themselves be a vulnerability, as shown by a published CVE in which exploitation requires adding untrusted content to a Claude Code context window. That record concerns security, not licensing, but it illustrates that the assistant's execution path has its own exposure that a pull request check does not observe.

    The sensible conclusion is layered control. Keep the CI check as the common, vendor-neutral backstop, and add enforcement closer to where code is generated for the cases it cannot reach.

    Extending the same policy into the execution path

    Trussed enforces policy in the execution path across models, agents, tools, MCP servers, and coding assistants. Decisions are allow, redact, block, rate limit, or escalate for human approval, and they apply to individual interactions and tool calls. Trussed also provides code provenance, covering the origin, licence, and security context of code, and enforcement generates audit-ready evidence as it happens.

    For a regulated enterprise, this means the SSPL rule defined for CI can also be applied at runtime, not reviewed after the fact, and the evidence format can stay consistent between the two stages. The CI check remains useful as a merge-time backstop. Trussed can be deployed self-managed in the customer cloud, with configurable retention and data residency.

    One policy, four assistants, one decision record

    Define

    A single SSPL deny rule, independent of assistant.

    Detect

    License and origin signals on every changed file and hunk.

    Decide

    Allow, block, or escalate to a human approver.

    Record

    A decision record for each outcome, retained for audit.

    Apply one license policy across every assistant

    Talk to an expert about extending a single SSPL rule from the CI gate into the execution path, with audit-ready evidence for each decision.

    Talk to an Expert
    Next step

    How does your AI governance program compare?

    See where your program has gaps in less than 2 minutes.