modstitch-origin

RFC 0001: Modstitch Origin Manifest v1.0


1. Summary

The Modstitch Origin Manifest is a JSON document that allows Minecraft mod authors to declare how their release artifacts can be verified as author-approved.

It is intended for authors who want to take additional responsibility for the integrity of their release pipeline, especially in an ecosystem where distribution platforms may not yet provide first-class artifact signing or attestation enforcement.

This specification defines:

This specification provides origin assurance, not safety assurance.

A successful verification means:

This artifact satisfied the author’s declared origin policy.

It does not mean:

This artifact is safe, non-malicious, open source, reproducible, or free from vulnerabilities.


2. Motivation

Minecraft mods have previously been affected by supply-chain attacks where malicious artifacts were uploaded to legitimate mod distribution pages.

One known attack vector is the theft of publishing credentials for platforms such as Modrinth or CurseForge. If an attacker obtains a publishing token, they may be able to upload a poisoned artifact directly to an existing project. From a user’s perspective, the file may appear to come from the correct platform, the correct author, and the correct project page.

The ideal solution is for distribution platforms to support opt-in artifact verification natively. For example, a platform could allow authors to require signed or attested uploads, store trusted public keys, reject invalid artifacts at upload time, and restrict publishing tokens so they cannot disable those protections.

However, authors and launcher developers should not have to wait for every platform to implement this perfectly.

Modstitch Origin is a client-verifiable, author-controlled mechanism that lets authors publish an origin policy independently. It is not a replacement for platform enforcement, but it gives authors a practical way to start protecting their own release artifacts today.


3. Goals

The goals of Modstitch Origin v1.0 are:

  1. Provide a simple manifest format for declaring artifact origin verification policy.
  2. Allow authors to opt in without requiring platform-side enforcement.
  3. Support both open-source and closed-source projects.
  4. Support both CI-based provenance and author-controlled signing keys.
  5. Allow clients to determine whether an artifact satisfies the author’s declared policy.
  6. Avoid describing verified artifacts as “safe” or “trusted”.
  7. Keep the first version simple enough for authors and launcher developers to implement.

4. Non-goals

4.1 Malware detection

This specification does not attempt to detect malware.

A malicious author can sign their own malicious artifact. A compromised build pipeline can produce a malicious artifact that still satisfies the declared verifiers.

Modstitch Origin answers only:

Did this artifact satisfy the author’s declared origin policy?

It does not answer:

Is this artifact safe?

4.2 Mandatory launcher enforcement

This specification does not require launchers to block artifacts that fail verification.

A client may block, warn, log, mark the artifact as unverified, ask for explicit confirmation, or expose the result to a modpack management layer.

However, clients are encouraged not to silently ignore verification failure for projects that have opted into Modstitch Origin.

4.3 Platform-side upload enforcement

This specification does not require Modrinth, CurseForge, or any other platform to reject artifacts that fail verification.

Platform-side enforcement remains the preferred long-term solution. Platforms should support opt-in signing requirements, restrict publishing token scopes, require re-authentication or second-factor confirmation for disabling verification requirements, and consider mandatory signing or attestation for large projects.

Modstitch Origin is a deployable client-side mechanism for the current ecosystem, not an argument against platform-native protections.

4.4 Protection against badly scoped publishing tokens

Version 1.0 does not protect against an attacker who can both publish artifacts and alter security-sensitive project metadata.

For example, if a stolen publishing token can remove or change the project’s source repository URL or dedicated Modstitch manifest URL, then a client may no longer be able to discover the manifest.

Authors should scope publishing tokens narrowly. A token used by CI to publish artifacts should not be able to:

Platforms should separate artifact publishing permissions from project configuration permissions.

4.5 Downgrade protection

Version 1.0 does not define policy pinning, client-side manifest history, transparency logs, downgrade detection, or protection against a manifest being removed or weakened after a client has previously seen it.

Future versions may define these behaviours.

Projects are still encouraged to monitor changes to their manifest, but this is not part of the v1.0 verification algorithm.

4.6 Local development builds

This specification applies to artifacts obtained from declared distribution sources.

It does not define verification behaviour for manually imported local files, development builds, locally compiled mods, or files obtained from undeclared sources.

A locally compiled mod may be perfectly legitimate while having no Modstitch verification result.

4.7 Reproducible builds

This specification does not require artifacts to be reproducible.

Some verifiers may provide evidence about a build process, but v1.0 does not require independent byte-for-byte rebuildability.


5. Terminology

Artifact

A release file distributed by a mod project, usually a .jar.

Source

A distribution location from which artifacts may be obtained.

In v1.0, the defined source types are:

modrinth
curseforge

Future versions may define additional source types, such as GitHub Releases.

Source-provided publication timestamp

The timestamp reported by the distribution source for when the artifact/version/file was published.

All time-based validity checks in this specification use the source-provided publication timestamp.

Clients MUST NOT use timestamps from:

JAR entries
ZIP entries
filesystem metadata
artifact manifests
artifact filenames
embedded build metadata
detached signature creation time
attestation creation time

Artifact-controlled timestamps may be spoofed, normalised, or intentionally rewritten for reproducible builds. They MUST NOT be used to decide whether a source or verifier was valid for an artifact.

Manifest

A JSON document matching this specification.

The conventional filename is:

.modstitch-origin.json

Verifier

A declared method for verifying that an artifact is author-approved.

Examples:

openpgp-signature
github-attestation

Tag

A string used by the verification rule.

A verifier satisfies its own id as an implicit tag. A verifier may also declare additional explicit tags.

Satisfied tag

A tag is satisfied when at least one applicable verifier providing that tag successfully verifies the artifact.


6. Manifest discovery

A client may discover a Modstitch Origin Manifest in either of the following ways.

6.1 Dedicated manifest URL

A distribution platform SHOULD expose a dedicated relationship/link to a Modstitch Origin Manifest.

This link may point to any HTTPS URL serving a JSON document matching this schema.

Example conceptual relation:

modstitch-origin

This specification does not require platforms to use that exact relation name, but platforms adding first-class support should expose a dedicated, machine-readable manifest URL rather than relying only on repository conventions.

6.2 Repository fallback convention

If a platform does not expose a dedicated manifest URL, a client MAY attempt repository-based discovery.

Given a source project with an associated repository URL, the client MAY look for the following file at the root of the repository’s default branch:

.modstitch-origin.json

This filename is a convention for repository fallback discovery. It is not the only valid location for a manifest when a platform provides an explicit manifest URL.

6.3 Applicability check

Finding a manifest is not enough.

A manifest applies to an artifact only if:

  1. the artifact was obtained from a source listed in the manifest;
  2. the listed source has the same source type and project ID;
  3. the source declaration is valid for the artifact’s source-provided publication timestamp.

Clients MUST NOT treat a manifest as applicable merely because it was found in a linked repository.


7. Manifest format

A Modstitch Origin Manifest is a UTF-8 JSON document.

A v1.0 manifest contains the following top-level fields:

{
  "schemaVersion": 1,
  "enforceAfter": "2026-07-01T00:00:00Z",
  "sources": [],
  "verification": {},
  "verifiers": []
}

8. Top-level fields

8.1 schemaVersion

Required.

MUST be:

1

Clients MUST reject unsupported schema versions.

8.2 enforceAfter

Required.

An ISO 8601 timestamp.

Artifacts with a source-provided publication timestamp before enforceAfter are outside the manifest’s enforcement window.

This allows authors to opt into Modstitch Origin without invalidating old releases.

Example:

"enforceAfter": "2026-07-01T00:00:00Z"

8.3 sources

Required.

A non-empty array of source declarations.

Example:

"sources": [
  {
    "type": "modrinth",
    "projectId": "AANobbMI",
    "validFrom": "2026-07-01T00:00:00Z",
    "validUntil": null
  },
  {
    "type": "curseforge",
    "projectId": "123456",
    "validFrom": "2026-07-01T00:00:00Z",
    "validUntil": null
  }
]

Each source declaration MUST contain:

"type"
"projectId"
"validFrom"
"validUntil"

validUntil MUST be present and may be null.

A source declaration is applicable to an artifact if:

validFrom <= sourcePublishedAt

and either:

validUntil is null

or:

sourcePublishedAt < validUntil

projectId SHOULD be encoded as a string, even if the platform internally represents IDs numerically.

Slugs, names, and display titles SHOULD NOT be used as the primary source binding because they may be mutable.

8.4 verification

Required.

Defines which tags must be satisfied.

Example:

"verification": {
  "mode": "anyOf",
  "tags": [
    "release"
  ]
}

or:

"verification": {
  "mode": "allOf",
  "tags": [
    "ci",
    "author-signature"
  ]
}

mode MUST be one of:

anyOf
allOf

tags MUST be a non-empty array of strings.

For anyOf, verification succeeds if at least one listed tag is satisfied.

For allOf, verification succeeds only if every listed tag is satisfied.

8.5 verifiers

Required.

A non-empty array of verifier declarations.

Every verifier MUST contain:

"id"
"type"
"validFrom"
"validUntil"

A verifier MAY contain:

"tags"

id MUST be unique within the manifest.

A verifier always provides its own id as an implicit tag.

If tags is present, the verifier also provides each listed tag.

Example:

{
  "id": "release-key-2026",
  "type": "openpgp-signature",
  "tags": [
    "author-signature",
    "release"
  ],
  "validFrom": "2026-07-01T00:00:00Z",
  "validUntil": null
}

This verifier provides the following tags:

release-key-2026
author-signature
release

validUntil MUST be present and may be null.

A verifier is applicable to an artifact if:

validFrom <= sourcePublishedAt

and either:

validUntil is null

or:

sourcePublishedAt < validUntil

Verifier validity is evaluated against the source-provided publication timestamp of the artifact, not the current time and not any timestamp embedded in the artifact.


9. Verification algorithm

Given an artifact and a discovered manifest, a client determines the verification result as follows.

9.1 Check source applicability

The client identifies the artifact’s source type and project ID.

The manifest is applicable only if it contains a source declaration with:

matching type
matching projectId
valid source validity period for sourcePublishedAt

If no matching source declaration exists, the manifest does not apply to the artifact.

9.2 Check enforcement window

If:

sourcePublishedAt < enforceAfter

then the artifact is outside the manifest’s enforcement window.

The client SHOULD report this as not-applicable.

9.3 Evaluate verifier tags

The client evaluates each tag listed in verification.tags.

A tag is satisfied when at least one applicable verifier providing that tag succeeds.

A verifier provides:

  1. its own id as an implicit tag;
  2. any explicit tags listed in tags.

9.4 Apply verification mode

If mode is anyOf, verification succeeds if at least one listed tag is satisfied.

If mode is allOf, verification succeeds only if every listed tag is satisfied.


10. Verification result states

Clients SHOULD be able to represent at least the following states:

no-manifest
manifest-invalid
source-not-listed
not-applicable
verification-succeeded
verification-failed
verification-indeterminate

10.1 no-manifest

No Modstitch Origin Manifest was discovered.

10.2 manifest-invalid

A manifest was discovered but could not be parsed or did not satisfy the v1.0 schema.

10.3 source-not-listed

A manifest was discovered, but it did not contain an applicable source declaration for the artifact’s source type, project ID, and source-provided publication timestamp.

10.4 not-applicable

The artifact was published before enforceAfter.

10.5 verification-succeeded

The artifact satisfied the manifest’s verification rule.

10.6 verification-failed

The artifact did not satisfy the manifest’s verification rule.

10.7 verification-indeterminate

The client could not complete verification because required information was unavailable.

Examples include:

source-provided publication timestamp unavailable
signature sidecar unavailable
keyserver unavailable
GitHub attestation unavailable
unsupported verifier type
unsupported repository host
network failure

11. OpenPGP signature verifier

The openpgp-signature verifier verifies an artifact using a detached OpenPGP signature.

11.1 Example

{
  "id": "release-key-2026",
  "type": "openpgp-signature",
  "tags": [
    "release"
  ],
  "validFrom": "2026-07-01T00:00:00Z",
  "validUntil": null,
  "fingerprint": "0123456789ABCDEF0123456789ABCDEF01234567",
  "keyservers": [
    "hkps://keyserver.ubuntu.com",
    "https://keys.openpgp.org"
  ]
}

11.2 Required fields

An openpgp-signature verifier MUST contain:

"fingerprint"

It MUST contain at least one of:

"publicKey"
"keyservers"

11.3 fingerprint

The expected OpenPGP public key fingerprint.

A detached signature MUST NOT be accepted merely because it is cryptographically valid. It MUST verify against a public key whose fingerprint exactly matches the declared fingerprint.

11.4 publicKey

Optional.

An ASCII-armoured OpenPGP public key.

If present, the client MUST calculate the key’s fingerprint and compare it to fingerprint.

If the calculated fingerprint does not match, the verifier fails.

11.5 keyservers

Optional.

An array of keyserver URLs.

Keyservers are key distribution mechanisms, not trust authorities.

A fetched public key is trusted only if its calculated fingerprint exactly matches fingerprint.

11.6 Signature sidecar discovery

For an artifact named:

example.jar

clients SHOULD look for detached signatures using the following sidecar filenames:

example.jar.asc
example.jar.sig

The sidecar filenames are not configurable in v1.0.

11.7 Verification

An openpgp-signature verifier succeeds if:

  1. the verifier is applicable to the artifact’s source-provided publication timestamp;
  2. a detached signature sidecar is available;
  3. a public key is available from publicKey or keyservers;
  4. the public key fingerprint exactly matches fingerprint;
  5. the detached signature verifies against the exact artifact bytes.

12. GitHub attestation verifier

The github-attestation verifier verifies an artifact using a GitHub artifact attestation.

This verifier is intended for artifacts produced by GitHub Actions.

12.1 Example

{
  "id": "github-actions-release",
  "type": "github-attestation",
  "tags": [
    "release"
  ],
  "validFrom": "2026-07-01T00:00:00Z",
  "validUntil": null,
  "repository": "owner/project",
  "allowedWorkflows": [
    ".github/workflows/release.yml"
  ],
  "allowedRefs": [
    "refs/tags/*"
  ]
}

12.2 Required fields

A github-attestation verifier MUST contain:

"repository"

12.3 Optional fields

A github-attestation verifier MAY contain:

"allowedWorkflows"
"allowedRefs"

12.4 repository

The GitHub repository expected to have produced the attestation.

Format:

owner/name

The attestation MUST identify this repository as the source repository.

12.5 allowedWorkflows

Optional.

An array of workflow paths allowed to produce release artifacts.

Example:

"allowedWorkflows": [
  ".github/workflows/release.yml"
]

If present, the attestation MUST identify one of these workflow paths.

If absent, any workflow in the declared repository may satisfy this verifier.

12.6 allowedRefs

Optional.

An array of ref globs allowed to produce release artifacts.

Example:

"allowedRefs": [
  "refs/tags/*"
]

If present, the attestation MUST identify a ref matching one of these patterns.

If absent, any ref in the declared repository may satisfy this verifier.

12.7 Verification

A github-attestation verifier succeeds if:

  1. the verifier is applicable to the artifact’s source-provided publication timestamp;
  2. the client obtains an attestation for the artifact digest;
  3. the attestation cryptographically verifies;
  4. the attestation subject digest matches the exact artifact bytes;
  5. the attestation identifies the declared GitHub repository;
  6. if allowedWorkflows is present, the attestation identifies one of the allowed workflow paths;
  7. if allowedRefs is present, the attestation identifies a ref matching one of the allowed ref globs.

Clients SHOULD verify the attestation cryptographically rather than relying only on the presence of an attestation in an API response.


13. Example manifests

13.1 Simple OpenPGP project

{
  "schemaVersion": 1,
  "enforceAfter": "2026-07-01T00:00:00Z",

  "sources": [
    {
      "type": "modrinth",
      "projectId": "AANobbMI",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null
    }
  ],

  "verification": {
    "mode": "anyOf",
    "tags": [
      "release-key-2026"
    ]
  },

  "verifiers": [
    {
      "id": "release-key-2026",
      "type": "openpgp-signature",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null,
      "fingerprint": "0123456789ABCDEF0123456789ABCDEF01234567",
      "keyservers": [
        "hkps://keyserver.ubuntu.com"
      ]
    }
  ]
}

In this example, the verifier does not declare explicit tags.

The verifier ID release-key-2026 acts as an implicit tag.

13.2 GitHub attestation project

{
  "schemaVersion": 1,
  "enforceAfter": "2026-07-01T00:00:00Z",

  "sources": [
    {
      "type": "modrinth",
      "projectId": "AANobbMI",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null
    },
    {
      "type": "curseforge",
      "projectId": "123456",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null
    }
  ],

  "verification": {
    "mode": "anyOf",
    "tags": [
      "release"
    ]
  },

  "verifiers": [
    {
      "id": "github-actions-release",
      "type": "github-attestation",
      "tags": [
        "release"
      ],
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null,
      "repository": "owner/project",
      "allowedWorkflows": [
        ".github/workflows/release.yml"
      ],
      "allowedRefs": [
        "refs/tags/*"
      ]
    }
  ]
}

13.3 CI attestation plus author signature

{
  "schemaVersion": 1,
  "enforceAfter": "2026-07-01T00:00:00Z",

  "sources": [
    {
      "type": "modrinth",
      "projectId": "AANobbMI",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null
    },
    {
      "type": "curseforge",
      "projectId": "123456",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null
    }
  ],

  "verification": {
    "mode": "allOf",
    "tags": [
      "ci",
      "author-signature"
    ]
  },

  "verifiers": [
    {
      "id": "github-actions-release",
      "type": "github-attestation",
      "tags": [
        "ci"
      ],
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null,
      "repository": "owner/project",
      "allowedWorkflows": [
        ".github/workflows/release.yml"
      ],
      "allowedRefs": [
        "refs/tags/*"
      ]
    },
    {
      "id": "release-key-2026",
      "type": "openpgp-signature",
      "tags": [
        "author-signature"
      ],
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null,
      "fingerprint": "0123456789ABCDEF0123456789ABCDEF01234567",
      "keyservers": [
        "hkps://keyserver.ubuntu.com",
        "https://keys.openpgp.org"
      ]
    }
  ]
}

Clients should avoid language that implies safety, malware scanning, reputation, or endorsement.

14.1 Preferred terms

Clients SHOULD prefer terms such as:

Origin verified
Origin verification failed
Author-origin verification failed
Satisfies the project's Modstitch Origin policy
Does not satisfy the project's Modstitch Origin policy
Unverified against the author's origin policy

14.2 Terms to avoid

Clients SHOULD avoid terms such as:

Safe
Trusted
Malware-free
Approved by Modstitch
Verified mod
Secure mod
Clean

14.3 Suggested success message

Origin verified

This artifact satisfies the project's Modstitch Origin policy.
This means it matched the author's declared release-origin requirements.
It does not guarantee that the mod is safe or free from vulnerabilities.

14.4 Suggested failure message

Origin verification failed

This project declares a Modstitch Origin policy, but this artifact did not satisfy it.

This does not necessarily mean the artifact is malicious, but it means the file could not be verified as matching the author's declared release-origin requirements.

14.5 Suggested bypass wording

Install anyway

I understand that this artifact did not satisfy the project's declared Modstitch Origin policy.

Clients may choose different wording, but should preserve the distinction between origin assurance and safety assurance.


15. Client handling recommendations

This specification does not mandate enforcement behaviour.

Clients may choose to:

block failed artifacts
warn before installation
show a passive warning
log verification results
expose results to modpack tooling
allow user bypass
ignore verification results by default

Clients are encouraged to make verification failure visible when a project has opted into Modstitch Origin.

Clients SHOULD expose enough diagnostic information for authors and users to understand failures.

Useful diagnostics include:

source type
source project ID
source-provided publication timestamp
artifact filename
artifact digest
manifest URL
manifest discovery method
failed tag
failed verifier ID
missing sidecar signature
missing public key
wrong OpenPGP fingerprint
missing GitHub attestation
attestation from unexpected repository
attestation from unexpected workflow
attestation from unexpected ref

16. Security considerations

16.1 Origin assurance only

Modstitch Origin provides author-origin assurance.

It does not prove that an artifact is safe.

16.2 Optional adoption

Absence of a Modstitch Origin Manifest is not suspicious by itself.

Most projects may not opt in, especially early in adoption. A missing manifest should therefore not be treated as evidence that a mod is malicious.

The manifest only becomes meaningful when a project has opted in and a client can discover the manifest.

16.3 Malicious projects can satisfy their own policy

A malicious project can publish a manifest and produce artifacts that satisfy it.

This is expected.

The purpose of Modstitch Origin is not to distinguish good projects from bad projects. Its purpose is to distinguish artifacts that satisfy an author-declared origin policy from artifacts that do not.

16.4 Source metadata compromise

If an attacker can alter the platform metadata used for manifest discovery, they may be able to prevent clients from finding the manifest.

Authors should scope publishing tokens narrowly and avoid giving CI tokens permission to edit source URLs, manifest URLs, project ownership, or team membership.

16.5 Manifest compromise

If an attacker can modify the manifest, they may be able to weaken the policy or replace verifiers.

Projects should treat .modstitch-origin.json, or any dedicated manifest URL, as security-sensitive.

Recommended mitigations include:

branch protection
required pull request review
CODEOWNERS for the manifest
restricted write access
two-factor authentication for maintainers
signed release tags

16.6 Monitoring manifest changes

Version 1.0 does not define downgrade protection, but projects are encouraged to monitor manifest changes.

Useful ad-hoc mitigations include:

post to a Discord channel when the manifest changes
send an email notification when the manifest changes
require CODEOWNER approval for manifest changes
include manifest changes in release notes
monitor source repository URL changes on distribution platforms

These measures do not provide cryptographic protection, but they increase visibility.

16.7 Signed commits

Projects may require signed commits or signed tags for manifest changes.

Clients may choose to display whether the latest commit touching the manifest is signed, but this is not part of v1.0 verification.

Signed commits are advisory unless the client also knows which signing identities are trusted for the project.

16.8 Multiple verifiers and shared compromise boundaries

A manifest may require multiple tags, such as both:

ci
author-signature

This only provides meaningful extra protection if the underlying secrets and systems are independent.

For example, requiring both GitHub attestation and OpenPGP signing is less useful if the OpenPGP private key is stored in the same GitHub Actions environment that produces the attestation.


17. Future work

Future versions may define:

downgrade protection
client-side manifest pinning
signed manifests
manifest transparency logs
artifact-bound manifest references
GitHub Releases as a source type
GitLab attestation support
Codeberg or Forgejo support
Sigstore keyless signing
modpack lockfile integration
platform-native verification relations
platform-native upload enforcement

18. Complete minimal example

{
  "schemaVersion": 1,
  "enforceAfter": "2026-07-01T00:00:00Z",

  "sources": [
    {
      "type": "modrinth",
      "projectId": "AANobbMI",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null
    }
  ],

  "verification": {
    "mode": "anyOf",
    "tags": [
      "release-key"
    ]
  },

  "verifiers": [
    {
      "id": "release-key",
      "type": "openpgp-signature",
      "validFrom": "2026-07-01T00:00:00Z",
      "validUntil": null,
      "fingerprint": "0123456789ABCDEF0123456789ABCDEF01234567",
      "keyservers": [
        "hkps://keyserver.ubuntu.com"
      ]
    }
  ]
}

19. Version 1.0 security claim

The security claim of Modstitch Origin v1.0 is intentionally narrow:

If a project publishes a valid Modstitch Origin Manifest, and an attacker can upload artifacts to a listed source but cannot alter the manifest, cannot prevent manifest discovery, and cannot satisfy the declared verifiers, then the attacker’s artifact will fail Modstitch Origin verification.

This is not a complete solution to Minecraft mod malware.

It is a practical mechanism for authors to take additional control over their own release origin assurance, and for clients to recognise when an artifact does or does not match the author’s declared release policy.