diff --git a/.agents/skills/supply-chain-guard/SKILL.md b/.agents/skills/supply-chain-guard/SKILL.md new file mode 100644 index 0000000..d5ef7c8 --- /dev/null +++ b/.agents/skills/supply-chain-guard/SKILL.md @@ -0,0 +1,138 @@ +--- +name: supply-chain-guard +description: Use before installing, updating, auditing, or executing dependencies, package-manager commands, project generators, CI actions/workflows, release jobs, IDE extensions, MCP servers, or AI-agent tools. +--- + +# Supply Chain Guard + +Use this skill for every task that can add, remove, update, install, sync, scaffold, generate, execute, publish, or approve dependencies or dependency-provided tooling. In general project work, keep it available and invoke it as soon as the task touches packages, package managers, CI/release automation, IDE/MCP/agent tooling, or installer scripts. + +This skill is a policy and workflow layer. It does not replace package-manager controls, endpoint protection, registry malware feeds, repository rules, code review, secret scanning, or incident response. + +## Load deeper guidance when needed + +Keep this file active for every dependency-related task. Load these references only when the task needs their detail: + +- `references/ecosystem-playbooks.md`: exact safe commands, lockfile rules, and package-age metadata by ecosystem. +- `references/attack-patterns.md`: compromise indicators and suspicious dependency patterns to search for. +- `references/incident-response.md`: suspected compromise triage, containment, token rotation, and recovery. +- `references/ci-and-repository-hardening.md`: repository rules, CI permissions, dependency review, secret scanning, and release hardening. +- `references/package-manager-configs.md`: durable secure defaults for common package managers. +- `references/tooling.md`: optional scanners and guards such as install-time blockers, OSV-Scanner, OpenSSF Scorecard, SBOM tools, and container scanners. + +## Non-negotiable defaults + +- Prefer the standard library, existing dependencies, or in-repo code over adding a package. +- Treat every package provider and transport the same: npm, npx, pnpm, pnpm dlx, Yarn Classic, Yarn Berry, yarn dlx, Corepack, Bun, bunx, Deno, JSR, uv, pip, pip-tools, pipenv, poetry, hatch, rye, conda, cargo, go modules, Maven, Gradle, Kotlin DSL, NuGet, Paket, CocoaPods, Carthage, Swift Package Manager, Homebrew, MacPorts, Nix, Chocolatey, winget, Scoop, MSIX/App Installer, PowerShell Gallery, vcpkg, Git URLs, tarballs, container images, IDE/editor extensions, browser extensions used for development, MCP servers, AI-agent tools, and project generators. +- Treat CI actions, reusable workflows, workflow templates, build caches, build artifacts, and release automation as dependencies. Pin third-party actions and reusable workflows to immutable full-length commit SHAs where the platform supports it; review tag or branch references like floating package versions. +- Never install `latest`, floating ranges, unpinned Git branches, or unverified tarballs for new dependencies. +- Pin exact versions and preserve/update the lockfile intentionally. +- Never disable security checks, provenance/signature checks, lockfile checks, or TLS verification to make an install work. +- Never run dependency lifecycle/build scripts from newly introduced packages until the package/version has passed the checks below. Use `--ignore-scripts` or the package-manager equivalent when available. +- Treat package-manager commands, project generators, and one-line installers as code execution. Do not run them from an untrusted working directory or with broad credentials present. +- Treat signatures, provenance, trusted publishing, and attestations as identity and integrity signals, not proof that code is safe. Verify the expected repository, workflow, ref, environment, builder, and artifact digest, then still inspect dependency, workflow, cache, and release behavior. + +## Recommended machine hardening + +When helping a user set up a workstation or CI runner, recommend layered controls before dependency work: + +- Consider install-time malware blocking, registry proxying, or package intelligence controls where appropriate for the user's environment. +- Prefer pinned releases and reviewed installers for any security tool. Do not pipe remote installer scripts into a shell without explicit user approval. +- Set secure package-manager defaults in user and project config where supported: exact saved versions, lifecycle scripts disabled by default, frozen/locked installs, and checked-in lockfiles. +- Do risky installs and dependency triage in an isolated dev container, Codespace, VM, or short-lived runner with minimal mounted files and scoped credentials. +- Keep long-lived publish tokens, cloud credentials, SSH keys, and production secrets out of local shells and dependency install jobs whenever possible. +- Use repository rules, signed commits, required pull requests, required status checks, dependency review, code scanning, secret scanning with push protection, vulnerability/malware alerts, and provenance/signature checks where the platform supports them. +- If the user asks for setup commands, load `references/tooling.md` and `references/package-manager-configs.md`. + +## Conservative package age delay + +- Default minimum age for any newly introduced package version: **7 full days since publication/upload/release**. This is an organization policy and may be stricter than package-manager defaults. +- Prefer **14 days** for runtime, privileged, build-tooling, CI/CD, auth, crypto, networking, installer, postinstall, native binary, or transitive-heavy packages. +- Where supported, enforce this policy with native package-manager age gates as well as manual review. Load `references/package-manager-configs.md` for current configuration examples. +- If a package is younger than the required delay, choose an older compatible version that satisfies the requirement. +- If no compatible version satisfies the delay, do not install it automatically. Explain the block and request explicit user approval before proceeding. +- If publication time cannot be verified from registry/API metadata, treat the package as untrusted and do not install it automatically. + +## Cooldown exceptions + +Urgent security fixes may bypass the package-age delay only with explicit justification. Document the advisory ID, affected versions, exact fixed version, why no older fixed version is available, scanner/advisory evidence, the narrow package-manager-specific bypass, and post-install lockfile/script/provenance review. Never lower or disable the global age gate silently. + +## Required dependency intake checklist + +Before adding or upgrading any dependency, verify and document the result in your working notes/final summary: + +1. **Need:** why the dependency is necessary and why existing code/deps are insufficient. +2. **Identity:** exact package name, ecosystem, registry/source URL, selected exact version, and lockfile impact. +3. **Age:** selected version publication/upload/release time meets the 7-day minimum, or 14-day preference for high-risk cases. +4. **Source trust:** repository URL matches package metadata, recent maintainers/releases look plausible, and the package is not an obvious typo-squat or namespace confusion. +5. **Execution risk:** install/build/postinstall scripts, native binaries, prebuilt downloads, and code generation are reviewed before execution. +6. **Integrity:** lockfile hashes/checksums/signatures/provenance are preserved or verified when the ecosystem supports them. +7. **Scope:** dependency is added to the narrowest correct scope (`dev`, optional, workspace package, extras group, etc.). + +## Active incident workflow + +When the user asks about a named attack, compromised package set, malware campaign, or suspicious dependency: + +1. Fetch current advisories from primary or reputable sources instead of relying on memory or a stale embedded list. +2. Compare the repository's manifest and lockfile entries against exact compromised package names, versions, tarball URLs, Git URLs, and integrity hashes. +3. Search for known campaign indicators such as unexpected lifecycle hooks, new Git-hosted dependencies, injected `optionalDependencies`, obfuscated install-time JavaScript, unknown binary downloads, credential enumeration, package tarball rewrites, CI action tag rewrites, cache poisoning, or new AI-agent/MCP/IDE tooling permissions. +4. If exposure is possible, stop all installs/builds in that environment, preserve evidence, remove the compromised versions, rotate potentially exposed tokens, invalidate CI credentials, and review recent publish/release activity before resuming work. +5. Document exact matches, non-matches, dates checked, advisory URLs, and remediation steps in the final summary. + +For concrete search patterns, containment, and recovery steps, load `references/attack-patterns.md` and `references/incident-response.md`. + +## Existing-project install policy + +For normal installs in existing projects, avoid dependency graph changes: + +- npm: prefer `npm ci --ignore-scripts`; only use `npm install` when intentionally updating the lockfile. +- pnpm: prefer `pnpm install --frozen-lockfile --ignore-scripts`. +- Yarn Classic: prefer `yarn install --frozen-lockfile --ignore-scripts`; do not run `yarn upgrade` unless intentionally updating. +- Yarn Berry/Modern: prefer `yarn install --immutable --immutable-cache --check-cache`; keep `.yarnrc.yml`, `.pnp.cjs`, `.yarn/cache`, and `yarn.lock` changes intentional. +- Corepack: do not auto-activate a floating package-manager version; respect the pinned `packageManager` field or pin Corepack-prepared versions explicitly. +- Bun: prefer `bun install --frozen-lockfile --ignore-scripts` where supported. +- Deno/JSR: prefer checked-in lockfiles (`deno.lock`) and exact `jsr:`/`npm:` specifiers; do not refresh the lock unless intentionally changing dependencies. +- uv: prefer `uv sync --locked` or `uv sync --frozen` depending on project policy; do not refresh the lock unless intentionally changing dependencies. +- pip/requirements/pip-tools: prefer hash-checked installs (`--require-hashes`) when hashes are available; keep pinned requirements files authoritative. +- poetry/pipenv/hatch/rye/conda: prefer locked/frozen/sync modes and do not refresh lockfiles or solve to newer packages unless intentionally changing dependencies. +- .NET/NuGet/Paket: prefer locked restore (`dotnet restore --locked-mode` where available), exact `PackageReference`/central package versions, and trusted package sources only. +- Java/Kotlin Maven: prefer dependency lock or checksum verification where configured; avoid changing `pom.xml` ranges or plugin versions without explicit intent. +- Java/Kotlin Gradle: prefer dependency locking / verification metadata (`gradle.lockfile`, `verification-metadata.xml`) and exact plugin/library versions. +- CocoaPods/Carthage/SPM: prefer `pod install`, existing `Cartfile.resolved`, and `Package.resolved` with exact package pins/resolved files; avoid `pod update`, `carthage update`, or resolver refresh unless intentional. +- Homebrew/MacPorts/Nix/Chocolatey/winget/Scoop/PowerShell Gallery/vcpkg: avoid broad upgrade commands; install explicit formula/cask/package IDs and versions where supported, and verify source URLs/checksums/manifests/derivations. + +If scripts are required for a known trusted package already in the lockfile, run the minimal necessary rebuild command after reviewing what will execute. + +## Project secure defaults + +When allowed to update project configuration, prefer durable defaults over relying on every command being remembered: + +- npm project `.npmrc`: `ignore-scripts=true` and `save-exact=true` unless the project has documented exceptions. +- Yarn Berry `.yarnrc.yml`: `enableScripts: false`, `enableImmutableInstalls: true`, and exact semver prefix policy. +- GitHub Actions and other CI: install with scripts disabled by default, use least-privilege tokens, avoid exposing secrets to pull requests, and require dependency/security checks before merge. +- Commit documented exceptions for packages that truly need lifecycle scripts; rebuild only those packages after review. +- For exact config snippets, load `references/package-manager-configs.md`. + +## Adding packages safely + +- Query registry metadata before install. Examples: npm registry `time`, PyPI JSON `upload_time_iso_8601`, NuGet registration `published`, Maven Central `timestamp`, Gradle Plugin Portal metadata, CocoaPods specs commit/tag time, Carthage/SPM Git tag or release time, Homebrew formula/cask history, winget/Chocolatey/Scoop manifest commit time, PowerShell Gallery publish time, crates.io `created_at`, GitHub release `published_at`, container image digest timestamps/provenance. +- Install exact versions only, e.g. npm/pnpm/bun `pkg@x.y.z`, uv/pip `pkg==x.y.z`, NuGet `PackageReference Version="x.y.z"`, Maven/Gradle `group:artifact:x.y.z`, CocoaPods `pod 'Name', 'x.y.z'`, SPM/Carthage resolved commits/tags, Homebrew bundle pins or versioned formulae where available, winget/Chocolatey/Scoop/PowerShell Gallery explicit versions where supported, cargo `crate@x.y.z`, Go module version tags, image digests. +- Use package-manager flags that reduce surprise where available: `--save-exact`, `--ignore-scripts`, frozen/locked mode, offline/cache verification, signatures/provenance/audit commands. +- Re-run lockfile-aware install/test/build after changes and inspect unexpected transitive additions. + +## Baseline review records + +- Do not create marker files or policy artifacts in a user's repository unless they ask for a baseline review, hardening PR, or durable documentation. +- When asked for a baseline review, record the detected ecosystems, manifests, lockfiles, package-manager versions, risky findings, commands run, dates checked, and unresolved risks in the requested format. +- A baseline review does **not** waive checks for new dependency additions, upgrades, lockfile rewrites, new package managers, or new executable tooling. +- If a repository has multiple package roots/workspaces, cover all detected package roots before calling the baseline complete. + +## High-risk source rules + +- Avoid Git URL, branch, tarball, curl-pipe-shell, and binary-download dependencies. If unavoidable, pin to an immutable commit or digest and verify provenance. +- Avoid packages with recent ownership transfer, sudden maintainer expansion, unusual postinstall scripts, obfuscated/minified source in source packages, or metadata/repository mismatch. +- For CLIs and project generators (`npm create`, `npx`, `pnpm dlx`, `yarn dlx`, `bunx`, `deno run`, `uvx`, `pipx`, `dotnet tool install`, `mvn archetype:generate`, `gradle init`, `cargo install`, `brew install`, `choco install`, `winget install`, `scoop install`, `Install-Module`, `vcpkg install`, etc.), apply the same age, pinning, and script-execution rules before running generated code. + +## When blocked + +Do not bypass this guard silently. Either choose an older verified version, implement without the new dependency, or stop and ask for explicit approval with the exact risk and package/version named. diff --git a/.agents/skills/supply-chain-guard/references/attack-patterns.md b/.agents/skills/supply-chain-guard/references/attack-patterns.md new file mode 100644 index 0000000..97637e2 --- /dev/null +++ b/.agents/skills/supply-chain-guard/references/attack-patterns.md @@ -0,0 +1,108 @@ +# Attack Patterns and Review Checks + +Use this reference when reviewing a dependency change, investigating a named campaign, or checking whether a repository was exposed. + +## High-signal suspicious changes + +- A patch or minor release published very recently for a popular package. +- A package version whose tarball, integrity hash, or registry source changed unexpectedly. +- New or modified `preinstall`, `install`, `postinstall`, `prepare`, `prepack`, `build`, or equivalent lifecycle scripts. +- New `optionalDependencies`, platform-specific packages, or binary downloader packages. +- Newly added Git, tarball, HTTP, file path, or branch-based dependencies. +- Obfuscated JavaScript, packed/minified installer code, base64 payloads, dynamic `eval`, `Function`, shell command construction, or environment-variable enumeration. +- Code that reads home directories, shell history, `.npmrc`, `.pypirc`, `.netrc`, cloud credentials, SSH keys, kubeconfigs, package-manager tokens, GitHub tokens, CI variables, or password-manager exports. +- Network calls from install-time scripts, especially to paste sites, object storage, newly registered domains, URL shorteners, raw gist URLs, or unknown analytics endpoints. +- Sudden maintainer additions, ownership transfers, new publishing automation, or repository metadata changes near the suspicious release. +- Package metadata pointing to a repository that does not match the package name, scope, maintainers, or release history. +- Generated files or lockfile entries that introduce a second package manager. +- Valid provenance from an unexpected workflow, ref, environment, builder, or repository. +- A package or artifact that used to have stronger trust evidence and now has weaker or missing provenance/signature evidence. +- Privileged release jobs restoring caches or artifacts created by pull request workflows. +- Package-manager-native warnings about blocked young versions, unreviewed build scripts, trust downgrades, ignored builds, or exotic sources. +- Age-gate or script-approval bypass lists growing without documented review. + +## JavaScript-specific checks + +Search manifests and lockfiles for: + +- Lifecycle scripts in `package.json`. +- `optionalDependencies`, `bundleDependencies`, `bundledDependencies`, and `overrides` that change install behavior. +- `git+`, `github:`, `http:`, `https:`, `file:`, `link:`, `workspace:*`, `patch:`, and `portal:` specifiers. +- New `.npmrc`, `.yarnrc`, `.yarnrc.yml`, `.pnpmfile.cjs`, `patches/`, `.pnp.cjs`, or package-manager hook files. +- Lockfile entries with changed `resolved`, `integrity`, `checksum`, `dependencies`, `optionalDependencies`, or package registry host. + +Useful local searches: + +```sh +rg -n '"(preinstall|install|postinstall|prepare|prepack|postpack)"|optionalDependencies|bundleDependencies|bundledDependencies' package.json '**/package.json' +rg -n 'git\\+|github:|https?:|file:|link:|patch:|portal:' package.json package-lock.json pnpm-lock.yaml yarn.lock bun.lockb +rg -n 'process\\.env|\\.npmrc|GITHUB_TOKEN|NPM_TOKEN|AWS_|AZURE_|GOOGLE_|KUBECONFIG|id_rsa|\\.ssh|child_process|exec\\(|spawn\\(|eval\\(|Function\\(' . +rg -n 'minimumReleaseAgeExclude|minimumReleaseAgeExcludes|npmPreapprovedPackages|trustPolicyExclude|allowBuilds|trustedDependencies|allowScripts' package.json pnpm-workspace.yaml .yarnrc.yml bunfig.toml deno.json +``` + +## Python-specific checks + +Search manifests and lockfiles for: + +- Direct URLs, VCS requirements, editable installs, path dependencies, extras that pull large dependency sets, and custom indexes. +- `setup.py`, `setup.cfg`, `pyproject.toml` build backends, plugin entry points, and native extensions. +- New `pip.conf`, `pip.ini`, `uv.toml`, `poetry.toml`, or index credentials. + +Useful local searches: + +```sh +rg -n 'git\\+|https?://|--extra-index-url|--index-url|--trusted-host|-e\\s|editable|path\\s*=|url\\s*=' requirements*.txt pyproject.toml poetry.lock uv.lock Pipfile.lock +rg -n 'os\\.environ|subprocess|base64|eval\\(|exec\\(|\\.pypirc|\\.netrc|AWS_|AZURE_|GOOGLE_|GITHUB_TOKEN|NPM_TOKEN|KUBECONFIG|id_rsa|\\.ssh' . +rg -n 'exclude-newer|exclude-newer-package|uploaded-prior-to|extra-index-url|trusted-host|explicit\\s*=\\s*true|tool\\.uv\\.index' pyproject.toml uv.toml requirements*.txt +``` + +## CI and repository checks + +Review: + +- Workflows that run installs on pull requests with secrets available. +- New or modified workflow permissions, OIDC configuration, publish jobs, release jobs, and registry login steps. +- Self-hosted runner usage and whether untrusted code can run on persistent machines. +- Package publishing provenance and whether releases can be overwritten or mutated. +- Branch protection or ruleset changes around the suspicious time window. +- Third-party actions or reusable workflows pinned to tags/branches instead of full-length commit SHAs. +- Newly introduced reusable workflows from third-party repositories. +- Cache keys, restore keys, and artifact paths that cross from untrusted pull request jobs into trusted release/deploy jobs. +- Release/tag rewrite behavior in CI dependencies. + +Useful local searches: + +```sh +rg -n 'pull_request_target|permissions:|id-token:|secrets:|GITHUB_TOKEN|npm publish|pypi|twine|docker login|gh release|actions/checkout|self-hosted' .github/workflows +rg -n 'uses:\\s*[^#\\n]+@((main|master|HEAD|latest|v?[0-9]+(\\.[0-9]+){0,2})\\b|\\$\\{\\{)' .github/workflows +rg -n 'jobs\\.[A-Za-z0-9_-]+\\.uses|uses:\\s*[^\\s]+/.github/workflows/.+@' .github/workflows +rg -n 'actions/cache|cache:|restore-keys|upload-artifact|download-artifact|package-manager-cache' .github/workflows +rg -n 'curl .*\\|.*(sh|bash)|wget .*\\|.*(sh|bash)|Invoke-WebRequest|iwr |iex |Set-ExecutionPolicy' . +``` + +## IDE and AI-tooling checks + +Review new or changed: + +- `.vscode/extensions.json`, `.vscode/settings.json`, Open VSX or VSIX manifests, JetBrains plugin config, browser extensions used for development, and extension lockfiles where present. +- `.mcp.json`, `mcp.json`, `claude_desktop_config.json`, `.claude/`, `.cursor/`, `.windsurf/`, agent tool manifests, and local tool permission files. +- Extension manifests containing `extensionPack`, `extensionDependencies`, broad activation events, bundled JavaScript, hidden Unicode, native binaries, or marketplace publisher changes. +- MCP/agent tool configs granting shell execution, broad filesystem access, network access, environment-variable access, or access to credential stores. + +Useful local searches: + +```sh +rg -n 'extensionPack|extensionDependencies|activationEvents|contributes|main|browser' .vscode '**/package.json' '*.vsixmanifest' +rg -n 'mcpServers|command|args|env|allow|permissions|filesystem|shell|stdio|sse|http' .mcp.json mcp.json claude_desktop_config.json .claude .cursor .windsurf +rg -n '[\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u206F]' . +``` + +## Review result standard + +When reporting findings, include: + +- exact file and line where the risk appears +- package name, selected version, source URL, and lockfile entry +- whether the finding is known-malicious, suspicious, or expected +- whether install-time execution was possible +- whether credentials or release permissions may have been exposed diff --git a/.agents/skills/supply-chain-guard/references/ci-and-repository-hardening.md b/.agents/skills/supply-chain-guard/references/ci-and-repository-hardening.md new file mode 100644 index 0000000..1061ca1 --- /dev/null +++ b/.agents/skills/supply-chain-guard/references/ci-and-repository-hardening.md @@ -0,0 +1,80 @@ +# CI and Repository Hardening + +Use this reference when asked to harden a repository, CI pipeline, release workflow, or organization settings. + +## Repository controls + +- Require pull requests before merge and protect default and release branches. +- Require status checks that include tests, dependency review, secret scanning or equivalent, and relevant code scanning. +- Require review from code owners for dependency manifests, lockfiles, CI workflows, release scripts, package-manager config, and infrastructure credentials. +- Require signed commits or verified branch rules where practical. +- Prevent force pushes and branch deletion on protected branches. +- Restrict who can edit workflows, environments, deploy keys, webhooks, package settings, and release jobs. +- Use security policies and private vulnerability reporting channels for public projects. + +## Dependency controls + +- Enable dependency inventory, vulnerability alerts, malware alerts where available, and dependency review for pull requests. +- Require dependency review as a PR gate for manifests, lockfiles, CI workflow files, reusable workflow references, third-party actions, container build definitions, and package-manager config. +- Require lockfile changes to be included with manifest changes. +- Block dependency changes that introduce unpinned versions, mutable URLs, untrusted registries, mutable CI action refs, reusable workflow refs, or lifecycle scripts without review. +- Prefer automated dependency update PRs that are small, grouped by ecosystem/risk, and reviewed before merge. + +## Secret controls + +- Enable secret scanning and push protection where available. +- Add custom secret patterns for internal tokens, private registries, package publish tokens, deployment keys, and cloud account formats. +- Do not expose secrets to untrusted pull request workflows. +- Prefer short-lived OIDC credentials over long-lived cloud keys, registry tokens, and deploy keys. +- Keep publish tokens separate from install tokens and give them the smallest possible scope. +- Keep secrets out of dependency install jobs unless the install itself strictly requires them. + +## CI permissions + +- Set default workflow token permissions to read-only. +- Grant write permissions per job only where required. +- Use environment protection rules for production deploys and package publishing. +- Avoid `pull_request_target` or equivalent privileged fork events for workflows that check out, install, build, cache, or execute untrusted code. If unavoidable, do not check out the pull request head/merge ref, do not run package-manager commands, do not restore shared caches, and grant no write token or OIDC permission. +- Pin third-party actions and reusable workflows to full-length commit SHAs. A tag or branch is mutable and should be reviewed like a floating dependency version. +- Avoid persistent self-hosted runners for untrusted code. Use ephemeral runners or isolated job environments. +- Clear package-manager caches after confirmed compromise and avoid sharing writable caches between trusted and untrusted jobs. + +## Cache and artifact trust boundaries + +- Never let untrusted pull request code write caches or artifacts that privileged base-branch, release, publish, or deploy jobs can later restore. +- Do not share package-manager caches across fork PR jobs and privileged jobs unless the cache is read-only, content-addressed, and scoped by trusted ref/event. +- Release and publish jobs should prefer clean dependency installs from reviewed lockfiles over restoring mutable caches. +- Treat caches, build artifacts, generated files, tool directories, and restored package-manager stores as executable inputs. +- Disable package-manager caches in publish jobs where practical, especially for registry trusted-publishing workflows. + +## Provenance and attestation policy + +- Require provenance, signatures, or artifact attestations where registries and build platforms support them. +- Do not treat valid provenance as a malware verdict. Valid provenance can still describe malicious output from a compromised legitimate workflow. +- Verify provenance against an expected policy: repository, workflow file, protected ref or tag, protected environment, builder identity, triggering event, and artifact digest. +- Release jobs must be clean, isolated, and protected from untrusted PR code, poisoned caches, restored artifacts, mutable third-party actions, and unreviewed reusable workflows. +- Verify consumed attestations, not just produced attestations. For GitHub artifact attestations, use `gh attestation verify` and inspect the predicate when policy decisions depend on it. + +## Release and publishing hardening + +- Use trusted publishing, provenance, attestations, and immutable releases where supported by the package registry and hosting platform. +- Separate build, test, sign, and publish credentials. +- Require human approval or protected environments before publishing packages and production artifacts. +- Prefer trusted publishing/OIDC over long-lived registry automation tokens, with OIDC permission granted only to the publish job. +- For npm publishing, prefer trusted publishing where available, require 2FA and disallow legacy publish tokens after migration where feasible, and disable package-manager caches in publish jobs unless there is a documented reason. +- For PyPI publishing, prefer Trusted Publishers, job-level `id-token: write`, protected environments, and default digital attestations from the official publishing flow where available. +- Verify package contents before publishing: no secrets, unexpected generated files, test fixtures with credentials, or local config files. +- Generate SBOMs for release artifacts where useful and attach them to releases. + +## Pull request review checklist + +For every dependency or CI change, answer: + +- Does this change alter the dependency graph, lockfile, install behavior, registry, or executable lifecycle hooks? +- Does any new code run during install, build, test, release, or deployment? +- Does the workflow expose secrets or write tokens to code from forks or untrusted branches? +- Can untrusted jobs write caches or artifacts consumed by privileged jobs? +- Are third-party actions and reusable workflows pinned to immutable refs? +- Is provenance valid for the expected workflow/ref/environment, and is the release path itself trustworthy? +- Are versions pinned and old enough under the package-age policy? +- Can the same result be achieved with an existing dependency or standard library? diff --git a/.agents/skills/supply-chain-guard/references/ecosystem-playbooks.md b/.agents/skills/supply-chain-guard/references/ecosystem-playbooks.md new file mode 100644 index 0000000..bba4f42 --- /dev/null +++ b/.agents/skills/supply-chain-guard/references/ecosystem-playbooks.md @@ -0,0 +1,192 @@ +# Ecosystem Playbooks + +Use this reference when a task touches a specific package manager, lockfile, project generator, or installer. Prefer the project's existing package manager and pinned version. Do not introduce a second manager for convenience. + +## Universal flow + +1. Detect manifests, lockfiles, toolchain pins, workspaces, and CI install commands. +2. Use frozen or locked install modes for existing dependencies. +3. Disable dependency lifecycle scripts by default when installing or refreshing dependencies. +4. Before adding or upgrading, query registry metadata for exact version, publication time, source repository, integrity, signatures, provenance, and deprecation or malware status. +5. Prefer an older compatible version if the newest version fails the package-age policy. +6. Use native age gates, script approvals, trust policy, and provenance checks where the pinned package-manager version supports them. +7. Review lockfile diffs for unexpected transitive additions, source changes, Git/tarball URLs, script-bearing packages, and registry changes. + +## JavaScript and TypeScript + +Detect: `package.json`, `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `.yarnrc.yml`, `bun.lock`, `bun.lockb`, `deno.json`, `deno.lock`, `jsr.json`. + +Safe existing installs: + +- npm: `npm ci --ignore-scripts` +- pnpm: `pnpm install --frozen-lockfile --ignore-scripts` +- Yarn Classic: `yarn install --frozen-lockfile --ignore-scripts` +- Yarn Berry: `yarn install --immutable --immutable-cache --check-cache` +- Bun: `bun install --frozen-lockfile --ignore-scripts` +- Deno: use checked-in `deno.lock`; avoid lockfile refresh unless intentional. + +Before adding packages: + +- Query npm metadata with `npm view @ time dist.tarball dist.integrity repository maintainers scripts --json` or the registry API. +- Install exact versions only, for example `npm install --save-exact --ignore-scripts @`. +- Use native package-age gates where available: npm `min-release-age`, pnpm `minimumReleaseAge`, Yarn `npmMinimalAgeGate`, Bun `minimumReleaseAge`, and Deno `minimumDependencyAge` / `--minimum-dependency-age`. +- Use native script approval where available: pnpm `approve-builds` / `allowBuilds`, Deno `approve-scripts`, Yarn `enableScripts: false` plus per-package `dependenciesMeta`, and Bun `trustedDependencies` after review. +- Run provenance/signature checks where supported, such as `npm audit signatures`, but treat valid provenance as identity evidence rather than a safety verdict. +- Treat `npx`, `npm create`, `pnpm dlx`, `yarn dlx`, `bunx`, `deno run`, and generator templates as code execution. Pin exact package versions or immutable URLs before use. +- Inspect `scripts`, `bin`, `optionalDependencies`, `peerDependenciesMeta`, `install`, `postinstall`, `preinstall`, `prepare`, and native binary download paths. +- Watch lockfiles for registry host changes, tarball URL changes, integrity changes without version changes, and newly introduced Git dependencies. + +## Python + +Detect: `pyproject.toml`, `requirements*.txt`, `constraints*.txt`, `poetry.lock`, `uv.lock`, `Pipfile.lock`, `environment.yml`, `conda-lock.yml`, `hatch.toml`. + +Safe existing installs: + +- uv: `uv sync --locked` or `uv sync --frozen` +- pip with hashes: `pip install --require-hashes -r requirements.txt` +- pip 26.1+ with upload-time metadata: add `--uploaded-prior-to=P7D` or `P14D` for high-risk surfaces. +- pip without hashes: install only in isolated environments and prefer adding hashes before broad changes. +- Poetry: `poetry sync` without refreshing the lock unless dependency changes are intentional. +- Pipenv: `pipenv sync` rather than `pipenv install` for existing locks. +- Conda: use locked environment files where available; avoid unconstrained solves in privileged environments. + +Before adding packages: + +- Query PyPI JSON metadata for `upload_time_iso_8601`, file hashes, yanked status, project URLs, and classifiers. +- Pin exact versions with `==` in requirements or exact lock entries. +- Use uv `exclude-newer` / `exclude-newer-package` where appropriate, and map private indexes explicitly to reduce dependency-confusion risk. +- Avoid `setup.py` execution paths, arbitrary build backends, and source builds until reviewed; prefer wheels only (`--only-binary=:all:`) for high-risk installs when feasible. +- Prefer PyPI Trusted Publishers and digital attestations for publishing, but still verify the expected workflow identity and source path. +- Treat `pipx`, `uvx`, `python -m pip`, `poetry run`, and project scaffolding tools as code execution. + +## Go + +Detect: `go.mod`, `go.sum`, `go.work`, `vendor/`. + +Safe existing installs: + +- Prefer `go mod download` or normal test/build commands without changing `go.mod` or `go.sum`. +- Use `go mod verify` after dependency changes. +- Avoid broad `go get -u` or toolchain-wide updates. + +Before adding modules: + +- Pin semantic import versions explicitly, for example `go get example.com/module@v1.2.3`. +- Verify module path ownership, proxy/checksum behavior, `go.sum` changes, and repository tags. +- Be cautious with private module configuration, `GONOSUMDB`, `GONOPROXY`, and `GOPRIVATE`; do not disable public checksum verification for public modules. + +## Rust + +Detect: `Cargo.toml`, `Cargo.lock`, `.cargo/config.toml`. + +Safe existing installs: + +- Prefer `cargo fetch --locked`, `cargo build --locked`, `cargo test --locked`. +- Avoid `cargo update` unless updating dependencies intentionally. + +Before adding crates: + +- Query crates.io metadata for `created_at`, repository, owners, features, and yanked status. +- Pin exact versions where risk is high and inspect feature expansion. +- Treat `build.rs`, proc macros, native linking, and downloaded binaries as high risk. +- Use `cargo vet` or `cargo crev` where the project already uses them. + +## JVM: Maven and Gradle + +Detect: `pom.xml`, `mvnw`, `.mvn/`, `build.gradle`, `build.gradle.kts`, `settings.gradle`, `gradle.lockfile`, `gradle/verification-metadata.xml`, `gradle/wrapper/gradle-wrapper.properties`. + +Safe existing installs: + +- Maven: prefer pinned plugin versions, repository governance, checksum fail-closed policy, and Maven Enforcer rules such as `banDynamicVersions`. +- Gradle: use dependency locking and dependency verification metadata for application builds. +- Do not update wrappers, plugins, or dependency ranges casually. + +Before adding dependencies: + +- Pin exact `group:artifact:version`; avoid dynamic versions such as `+`, `latest.release`, version ranges, and changing plugin portals without review. +- Review repositories in build files; avoid adding broad public mirrors or untrusted custom repositories. +- Treat Gradle plugins and Maven plugins as executable code. + +## .NET + +Detect: `.csproj`, `.fsproj`, `.vbproj`, `Directory.Packages.props`, `packages.lock.json`, `NuGet.config`, `paket.dependencies`, `paket.lock`. + +Safe existing installs: + +- `dotnet restore --locked-mode` when lockfiles are present. +- Keep central package management versions exact. + +Before adding packages: + +- Pin exact versions and trusted package sources. +- Use Package Source Mapping when multiple feeds are configured. +- Review `NuGet.config` for unexpected feeds or embedded credentials. +- Treat analyzers, source generators, MSBuild targets, and native assets as executable code. + +## Ruby + +Detect: `Gemfile`, `Gemfile.lock`, `.ruby-version`, `.tool-versions`. + +Safe existing installs: + +- `bundle config set --local deployment true`, `bundle config set --local frozen true`, then `bundle install`. +- Avoid `bundle update` unless intentionally updating. + +Before adding gems: + +- Pin exact versions when risk is high, check release age, source, authors, and native extensions. +- Review `post_install` hooks and gems that alter build or deployment behavior. + +## PHP + +Detect: `composer.json`, `composer.lock`. + +Safe existing installs: + +- `composer install --no-scripts --no-plugins` for first-pass dependency restoration. +- Run required trusted scripts/plugins only after review. +- Use `composer audit` and Composer policy/security blocking where available. + +Before adding packages: + +- Pin versions, review Packagist metadata, repository URLs, abandoned status, plugins, and autoload changes. +- Treat Composer plugins and scripts as code execution. + +## CI actions, reusable workflows, and release automation + +Detect: `.github/workflows/`, GitLab CI config, CircleCI config, Buildkite pipelines, reusable workflow references, third-party CI actions, release scripts, cache steps, artifact download/upload steps. + +Safe defaults: + +- Pin third-party actions and reusable workflows to immutable commit SHAs where the platform supports it. +- Treat tag and branch references as mutable dependency versions. +- Avoid `pull_request_target` or equivalent privileged fork events for workflows that check out, install, build, cache, or run untrusted code. +- Do not let untrusted pull request jobs write caches or artifacts that privileged release/deploy jobs later restore. +- Prefer clean release installs from reviewed lockfiles over restored mutable caches. +- Use OIDC/trusted publishing with protected environments and tightly scoped publish jobs, but do not treat valid provenance as proof the workflow was safe. + +## IDE extensions, MCP servers, and AI-agent tooling + +Detect: `.vscode/extensions.json`, `.vscode/settings.json`, Open VSX/VSIX manifests, JetBrains plugin config, browser extensions used for development, `.mcp.json`, `mcp.json`, `claude_desktop_config.json`, `.claude/`, `.cursor/`, `.windsurf/`, agent tool manifests, and local tool permission files. + +Safe defaults: + +- Treat extensions, MCP servers, and agent tools as executable dependencies with access to source files, shells, networks, credentials, or editors. +- Pin versions or immutable releases where supported. +- Review extension dependencies, extension packs, activation events, bundled JavaScript, hidden Unicode, native binaries, and marketplace publisher changes. +- Review tool permissions for shell execution, filesystem access, network access, and environment-variable access. + +## Containers and OS packages + +Detect: `Dockerfile`, `Containerfile`, `docker-compose.yml`, Helm charts, Kustomize, `apk`, `apt`, `dnf`, `brew`, `choco`, `winget`, `scoop`, `nix`, `vcpkg`, `install.sh`. + +Safe existing installs: + +- Pin base images by digest where practical. +- Avoid `curl | sh`, `latest` tags, broad OS upgrades, and unverified binary downloads. +- Review added repositories, signing keys, install scripts, and downloaded archives. + +Before adding images or system packages: + +- Verify publisher, digest, signature/attestation where available, and release age. +- Treat package-manager repository additions and GPG key imports as trust-boundary changes. diff --git a/.agents/skills/supply-chain-guard/references/incident-response.md b/.agents/skills/supply-chain-guard/references/incident-response.md new file mode 100644 index 0000000..19ba8c9 --- /dev/null +++ b/.agents/skills/supply-chain-guard/references/incident-response.md @@ -0,0 +1,65 @@ +# Incident Response + +Use this reference when a repository may have installed, built, published, or executed a compromised dependency or project generator. + +## First response + +1. Stop dependency installs, builds, release jobs, and publish jobs in the affected environment. +2. Preserve evidence before cleanup: manifests, lockfiles, package-manager caches if relevant, CI logs, shell history snippets, suspicious package tarballs, process listings, network indicators, and timestamps. +3. Identify the exposure window: first possible install time, CI jobs that ran during that window, developer machines that ran installs, and releases published afterward. +4. Compare exact package names, versions, tarball URLs, hashes, and advisory timestamps against current advisories. +5. Assume any secret available to install/build scripts, CI actions, MCP servers, IDE extensions, or release jobs may be compromised until proven otherwise. +6. Do not assume a package or artifact is safe because it has valid provenance, signatures, or trusted-publishing metadata. Verify the expected workflow/ref/environment and inspect the release path. + +## Containment + +- Remove or pin away from compromised versions and regenerate lockfiles only after deciding the safe target versions. +- Disable or pause publish workflows, package release automation, and deployment jobs until credentials are rotated. +- Revoke or rotate registry tokens, Git hosting tokens, cloud credentials, SSH deploy keys, CI secrets, OIDC trust relationships, kubeconfigs, Vault tokens, package signing keys, and deployment credentials that were available to affected jobs or machines. +- Invalidate persistent self-hosted runners that executed untrusted installs. Rebuild them from a clean image. +- Rebuild affected self-hosted runner images, dev containers, workstations, or CI runner templates if install-time code may have executed with sensitive access. For hosted runners, discard artifacts/caches and rerun from clean jobs after controls are fixed. +- Invalidate package-manager caches, CI caches, build caches, restored tool directories, and derived artifacts that may contain attacker-controlled files. +- Check for malicious releases, tags, package versions, workflow edits, branch protection changes, deploy keys, webhooks, OAuth apps, personal access tokens, and machine users created during the exposure window. + +## Investigation checklist + +- Which manifest and lockfile entries pulled the suspicious package? +- Was the dependency direct, transitive, optional, platform-specific, generated, or introduced by a tool? +- Did any lifecycle script run? +- Which environment variables, token files, credentials, and mounted directories were available? +- Did the environment have publish, release, deploy, cloud, Kubernetes, or repository administration permissions? +- Did the package make outbound network requests? Capture domains, IPs, URLs, and payload indicators when available. +- Were any downstream artifacts created after exposure: releases, container images, package publishes, binaries, SBOMs, or deployment bundles? +- Did privileged jobs restore caches, artifacts, tool directories, or package-manager stores written by untrusted jobs? +- Did provenance/attestation subjects, workflow identities, builder identities, refs, commits, environments, or triggering events differ from expected release policy? +- Did workflow logs or build artifacts expose secrets, OIDC tokens, publish tokens, environment variables, config files, or credential paths? +- Did SCM, registry, cloud, package-hosting, or CI audit logs show activity during the exposure window? + +## CI cache and provenance triage + +During suspected compromise, preserve and review: + +- CI cache keys, restore keys, cache scopes, and cache save/restore logs +- artifacts uploaded before release jobs and artifacts downloaded by release jobs +- provenance/attestation subjects, workflow identity, builder identity, ref, commit, environment, triggering event, and artifact digest +- OIDC token permissions, environment protection settings, and registry trusted-publisher bindings +- package-manager caches and stores used by publish jobs +- workflow run attempts and reruns, because later attempts may restore state from earlier compromised jobs + +## Recovery + +- Restore dependencies to known-good versions and keep lockfile diffs reviewable. +- Rebuild all releases, container images, packages, binaries, SBOMs, and deployment bundles produced after exposure from clean infrastructure after credential rotation. +- Re-enable CI and release workflows only after least-privilege permissions and dependency checks are in place. +- Add durable controls that would have reduced the incident: frozen installs, disabled lifecycle scripts, dependency review, secret scanning with push protection, package-age policy, install-time malware guard, provenance, isolated runners, and protected release rules. +- Document final known impact, rotated credentials, cleaned artifacts, remaining unknowns, and monitoring follow-up. + +## Human escalation + +Stop and ask the user or incident owner before: + +- deleting evidence or package-manager caches +- rotating production credentials that could cause downtime +- revoking organization-wide tokens or deploy keys +- deleting public package versions, releases, tags, or container images +- notifying customers, maintainers, registries, or security teams diff --git a/.agents/skills/supply-chain-guard/references/package-manager-configs.md b/.agents/skills/supply-chain-guard/references/package-manager-configs.md new file mode 100644 index 0000000..a8f08b5 --- /dev/null +++ b/.agents/skills/supply-chain-guard/references/package-manager-configs.md @@ -0,0 +1,280 @@ +# Package Manager Configs + +Use this reference when the user asks for durable project or workstation defaults. Apply changes only when they match the project's workflow and after explaining tradeoffs. + +## Native package-age gates + +Where supported, enforce the 7-day/14-day age policy in package-manager configuration as well as in agent review: + +- npm v11+: `.npmrc` `min-release-age=7` or `min-release-age=14` in days. Do not combine with `before`. +- pnpm v10.16+/v11: `pnpm-workspace.yaml` `minimumReleaseAge: 10080` for 7 days or `20160` for 14 days in minutes. +- Yarn Berry 4.12+: `.yarnrc.yml` `npmMinimalAgeGate: 7d` or `14d`. +- Bun: `bunfig.toml` `[install] minimumReleaseAge = 604800` for 7 days or `1209600` for 14 days in seconds. +- Deno: `deno.json` `minimumDependencyAge` or CLI `--minimum-dependency-age=P7D` / `P14D` where supported by the pinned Deno version. +- uv: `exclude-newer = "7 days"` or `"14 days"`. +- pip 26.1+: `--uploaded-prior-to=P7D` or `P14D` where the package index provides upload-time metadata. + +Cooldowns can delay urgent vulnerability fixes. Use the security-fix exception path from `SKILL.md` instead of globally lowering gates. + +## npm + +Project `.npmrc`: + +```ini +save-exact=true +ignore-scripts=true +fund=false +audit=true +min-release-age=7 +allow-git=root +``` + +Use `min-release-age=14` for high-risk runtime, CI/CD, auth, crypto, networking, native-binary, installer, or transitive-heavy dependency surfaces. + +Use `npm ci --ignore-scripts` for existing projects. If lifecycle scripts are required, review them first and run the narrowest trusted rebuild command. Run `npm audit signatures` where supported to verify registry signatures and provenance attestations for installed packages. + +## pnpm + +Project `pnpm-workspace.yaml`: + +```yaml +minimumReleaseAge: 10080 +minimumReleaseAgeIgnoreMissingTime: false +minimumReleaseAgeStrict: true +trustPolicy: no-downgrade +blockExoticSubdeps: true +strictDepBuilds: true +verifyDepsBeforeRun: error +savePrefix: "" +``` + +For high-risk repos: + +```yaml +minimumReleaseAge: 20160 +``` + +Use: + +```sh +pnpm install --frozen-lockfile --ignore-scripts +pnpm approve-builds +``` + +Review lifecycle/build scripts with `pnpm approve-builds` and commit reviewed `allowBuilds` decisions in `pnpm-workspace.yaml`. Do not enable `dangerouslyAllowAllBuilds` for normal projects. + +Review `pnpm-workspace.yaml`, `.pnpmfile.cjs`, `patches/`, overrides, catalog entries, exotic sources, and registry aliases. + +## Yarn Berry + +Project `.yarnrc.yml`: + +```yaml +enableImmutableInstalls: true +enableScripts: false +enableHardenedMode: true +checksumBehavior: throw +defaultSemverRangePrefix: "" +npmMinimalAgeGate: 7d +npmPreapprovedPackages: [] +approvedGitRepositories: [] +npmPublishProvenance: true +``` + +Use `npmMinimalAgeGate: 14d` for high-risk dependency surfaces. Use `yarn install --immutable --immutable-cache --check-cache`; use hardened mode especially for pull requests that modify manifests or lockfiles. Review `dependenciesMeta` script approvals, `packageExtensions`, `patch:` dependencies, plugins, `.pnp.cjs`, and approved Git repositories. + +## Bun + +Project or user `bunfig.toml`: + +```toml +[install] +frozenLockfile = true +minimumReleaseAge = 604800 +``` + +For high-risk repos, use `1209600`. Prefer: + +```sh +bun install --frozen-lockfile --ignore-scripts +``` + +Keep `bun.lock` or `bun.lockb` committed when the project uses Bun. Review `trustedDependencies` before allowing dependency lifecycle scripts. Bun's script behavior has changed over time; verify behavior against the pinned Bun version in use and avoid relying on unreviewed automatic script execution. + +## Deno and JSR + +Prefer exact versions, checked-in `deno.lock`, and frozen lockfile configuration: + +```json +{ + "lock": { + "path": "./deno.lock", + "frozen": true + }, + "minimumDependencyAge": "P7D" +} +``` + +For high-risk repos, use `"P14D"`. Deno blocks npm lifecycle scripts by default; review and persist exceptions with: + +```sh +deno approve-scripts +``` + +Treat `deno x` / `dx` as equivalent to `npx`: it runs npm or JSR package binaries and can request broad permissions. Review permission flags such as `--allow-env`, `--allow-read`, `--allow-write`, `--allow-net`, `--allow-run`, and `--allow-all`. + +## pip + +Prefer hashed requirements for deployed applications: + +```sh +python -m pip install --require-hashes --uploaded-prior-to=P7D -r requirements.txt +``` + +Use `P14D` for high-risk dependency surfaces. `--uploaded-prior-to` only works with package indexes that provide upload-time metadata and should fail closed otherwise. + +When feasible for high-risk installs, prefer wheels over source builds: + +```sh +python -m pip install --only-binary=:all: --require-hashes --uploaded-prior-to=P7D -r requirements.txt +``` + +Requirements pattern: + +```text +package-name==1.2.3 \ + --hash=sha256: +``` + +Avoid `--trusted-host`, broad `--extra-index-url`, and unpinned VCS requirements unless the project has a reviewed reason. + +## uv + +Use locked syncs: + +```sh +uv sync --locked +uv sync --frozen +``` + +Project `uv.toml` or `pyproject.toml` policy: + +```toml +exclude-newer = "7 days" +``` + +For high-risk repos: + +```toml +exclude-newer = "14 days" +``` + +Use `exclude-newer-package` only for documented security-fix exceptions. For private indexes, prefer explicit package-to-index mappings and avoid dependency-confusion fallbacks: + +```toml +[[tool.uv.index]] +name = "internal" +url = "https://packages.example.com/simple" +explicit = true +``` + +Use exact pins for high-risk additions and review `uv.lock` diffs before execution. + +## Poetry + +Use: + +```sh +poetry sync +``` + +Avoid `poetry update` unless intentionally updating. Review dependency groups and source repositories in `pyproject.toml`. + +## Cargo + +Use locked builds: + +```sh +cargo build --locked +cargo test --locked +cargo fetch --locked +``` + +Review `build.rs`, proc macros, feature flags, native links, `cargo install`, and `.cargo/config.toml`. Use `cargo vet`, `cargo audit`, or project-standard review tooling where already adopted. + +## Go + +Use: + +```sh +go mod verify +go test ./... +``` + +Avoid disabling checksum verification for public modules. Review `replace` directives, private module settings, `GONOSUMDB`, `GONOPROXY`, and `GOPRIVATE`. + +## Gradle + +Prefer dependency locking and verification metadata by default for application builds: + +```sh +./gradlew --write-locks +./gradlew --write-verification-metadata sha256 help +``` + +Only run these update commands when intentionally changing baseline metadata. Review dynamic versions, plugin repositories, wrapper changes, init scripts, and custom repository additions. + +## Maven + +Maven does not have a first-party lockfile model equivalent to pnpm, uv, Cargo, NuGet, or Gradle. Prefer: + +- pinned plugin and dependency versions +- repository manager governance and checksum fail-closed policy +- Maven Enforcer rules such as `banDynamicVersions` +- bans on `LATEST`, `RELEASE`, ranges, snapshots in release builds, and unapproved repositories +- Maven wrapper checksums where the project uses the wrapper + +Treat Maven plugins as executable code. + +## .NET + +Prefer locked restore: + +```sh +dotnet restore --locked-mode +``` + +Use `packages.lock.json`, central package management, and trusted package sources. Add Package Source Mapping when multiple feeds are configured to reduce dependency-confusion risk. Review `NuGet.config` for unexpected feeds and credentials. + +## Composer and PHP + +Use first-pass installs without scripts/plugins: + +```sh +composer install --no-scripts --no-plugins +composer audit +``` + +Use Composer's modern `config.policy` / security blocking controls where available so insecure versions are blocked during update/require/delete operations. Review Composer plugins, scripts, repositories, path repositories, and autoload changes before enabling scripts/plugins. + +## Bundler and Ruby + +Prefer persistent locked/deployment settings instead of deprecated transient flags: + +```sh +bundle config set --local deployment true +bundle config set --local frozen true +bundle install +``` + +Avoid `bundle update` unless intentionally updating. Review native extensions, gem sources, and plugin behavior. + +## Containers + +Prefer digest-pinned base images: + +```Dockerfile +FROM registry.example.com/image@sha256: +``` + +Avoid `latest`, unverified install scripts, broad package upgrades, and adding package repositories without key and source review. diff --git a/.agents/skills/supply-chain-guard/references/tooling.md b/.agents/skills/supply-chain-guard/references/tooling.md new file mode 100644 index 0000000..1386b8e --- /dev/null +++ b/.agents/skills/supply-chain-guard/references/tooling.md @@ -0,0 +1,73 @@ +# Tooling + +Use this reference when the user asks what tools to run or install. Tools are optional layers; do not make any single provider mandatory. + +## Install-time guards + +Install-time guards sit between package-manager commands and registries to block known malicious packages and, in some cases, packages that are too new. + +- Treat install-time blocking and package-age enforcement as design patterns, not as a recommendation for one provider. +- Options may include open-source registry proxies, hosted package intelligence platforms, endpoint controls, package-manager plugins, or organization-managed artifact repositories. +- Keep this skill's 7-day/14-day package-age policy at the agent decision layer unless the user explicitly chooses otherwise. +- Prefer pinned releases and reviewed installers in high-security environments. Do not pipe remote installer scripts into a shell without explicit approval. +- If naming a specific tool, explain why it fits the user's constraints and mention neutral alternatives when practical. + +## Vulnerability and malware scanning + +Use more than one data source when the risk justifies it: + +- OSV-Scanner for lockfile and SBOM vulnerability scanning against OSV data. +- Platform-native dependency review, vulnerability alerts, and malware alerts where available. +- Registry-native audit tools such as `npm audit`, `npm audit signatures`, `pnpm audit`, `yarn npm audit`, `deno audit`, `pip-audit`, `cargo audit`, `cargo vet`, `bundle audit`, `composer audit`, `dotnet list package --vulnerable`, and ecosystem equivalents. +- Additional package intelligence tools when already available to the user. + +Treat scanner output as input to review, not an automatic fix instruction. Do not run broad update commands just because a scanner reports a vulnerability. + +## First-party trust and provenance checks + +- npm: use `npm audit signatures` where supported to verify registry signatures and provenance attestations for installed packages. +- PyPI: prefer Trusted Publishers and digital attestations for publishing; verify expected publisher identity where tooling supports it. +- JSR/Deno: prefer provenance-capable publishing and `deno audit` where applicable. +- GitHub artifacts: verify consumed attestations with `gh attestation verify` and inspect signer repository/workflow, ref, environment, and artifact digest against policy. +- Composer: use Composer's security blocking / policy configuration where available, in addition to `composer audit`. + +Valid provenance is not proof that the code is benign. It only tells you where and how the artifact claims to have been built. + +## CI workflow scanners + +- Use `zizmor` or an equivalent GitHub Actions security scanner to detect unsafe `pull_request_target`, template injection, excessive permissions, credential persistence, and confusable references. +- Use `actionlint` or an equivalent workflow linter for syntax and common workflow mistakes. +- Treat scanner output as review input, not an automatic fix instruction. + +## Dependency-bot cooldown alignment + +- Configure dependency bot cooldowns to match the repository's package-age policy where the bot supports it. +- Do not let automated update bots bypass `min-release-age`, `minimumReleaseAge`, `npmMinimalAgeGate`, `minimumDependencyAge`, `exclude-newer`, `--uploaded-prior-to`, or equivalent gates unless the PR is an approved security-fix exception. +- Keep bot PRs small enough for meaningful lockfile and provenance review. + +## Project health signals + +Use health and provenance signals to prioritize review: + +- OpenSSF Scorecard for repository security posture signals. +- Maintainer and publisher history. +- Release cadence and recent ownership changes. +- Signed tags, signed commits, attestations, and trusted publishing. +- SBOMs and package provenance when provided by the project. + +Low scores or missing signals are not proof of compromise, but they increase review depth. + +## SBOM and artifact inspection + +When asked for release or deployment hardening: + +- Generate SBOMs with tools such as Syft, CycloneDX generators, package-manager-native export commands, or platform-native SBOM export. +- Scan containers and filesystems with tools such as Trivy, Grype, or equivalent scanners already used by the project. +- Compare SBOMs across releases to detect unexpected dependency additions. + +## Running tools safely + +- Prefer tools already pinned in the repo. +- If installing a scanner, apply this skill's dependency intake checklist to the scanner itself. +- Run scanners in isolated environments when they must inspect untrusted code. +- Preserve raw outputs for incident response, but avoid committing noisy reports unless the user asked for artifacts. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..c65f1f6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,7 @@ +# Repository Instructions + +## Supply Chain Guard + +Before any install, update, scaffold, package-manager command, CI action/workflow change, IDE/MCP/agent-tool change, release job, or dependency-provided tool execution, read and follow `.agents/skills/supply-chain-guard/SKILL.md`. + +For deeper guidance, load only the relevant file from `.agents/skills/supply-chain-guard/references/`.