This document explains our compliance status with OSSF Scorecard checks and documents any accepted risks or false positives.
Install to Claude Code
npx -y skills add tools-only/X-Skills --skill 272-security_scorecard_fed9e50e --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of 272 Security Scorecard Fed9e50e?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-272-security-scorecard-fed9e50e)More formats (shields.io, HTML) on the badges page.
# OSSF Scorecard Compliance Notes
This document explains our compliance status with OSSF Scorecard checks
and documents any accepted risks or false positives.
## Current Score: 8/10 for Pinned-Dependencies
**Summary:**
- ✅ 196/196 GitHub Actions pinned by SHA
- ✅ 4/4 Container images pinned by digest
- ✅ 3/3 Security tools use official SHA-pinned actions (checkov, pip-audit, zizmor)
- ⚠️ 0/17 pip commands pinned by hash (version-pinned only - accepted risk, checkov and pip-audit now use official actions)
- ⚠️ 21/24 npm commands pinned (3 are operational commands)
- ⚠️ 1 false positive for downloadThenRun
- ⚠️ APT packages intentionally unpinned (base image controls versions)
## Pinned-Dependencies
### GitHub Actions: COMPLIANT ✅
All GitHub Actions use commit SHA pinning (40-character hex):
```yaml
# Examples from our workflows:
actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6
step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3
```
### Docker Images: COMPLIANT ✅
All Docker images use SHA256 digest pinning:
```yaml
# Examples from our workflows and docker-compose:
python:3.13.9-slim@sha256:326df678c20c78d465db501563f3492d17c42a4afe33a1f2bf5406a1d56b0e86
redis:alpine@sha256:8360960f5fb56a282d78686203dd875862cd4b52a4184c17ac753690252d6d31
node:20-alpine@sha256:bcd88137d802e2482c9df3cdec71e0431857ebbbdba6973776b5593214056d86
```
### Official GitHub Actions: COMPLIANT ✅
Several security tools now use official GitHub Actions with SHA-pinning,
which provides equivalent security to hash-pinned pip installs:
| Tool | Action | SHA |
|------|--------|-----|
| Checkov | `bridgecrewio/checkov-action` | `5051a5cfc7e4c71d95199f81ffafbb490c7e6213` |
| pip-audit | `pypa/gh-action-pip-audit` | `f9e2142a494d0d5d0d84e508e22a802af02cd086` |
| zizmor | `zizmorcore/zizmor-action` | (container-based with internal hash verification) |
These official actions run their tools in containers with internal integrity verification,
which OSSF Scorecard accepts as equivalent to hash pinning.
### pip install: VERSION-PINNED (Accepted Risk) ⚠️
Scorecard flags `pip install package==version` because it prefers hash pinning.
The remaining pip commands use exact version pinning.
**Flagged commands and their status:**
| File | Line | Command | Status |
|------|------|---------|--------|
| Dockerfile | 47-48 | `pip install pip==24.3.1 pdm==2.26.2 playwright==1.57.0` | Version-pinned |
| check-env-vars.yml | 41 | `pip install loguru==0.7.3 sqlalchemy==2.0.36...` | Version-pinned |
| e2e-research-test.yml | 55 | `pip install -e .` | Local package (N/A) |
| fuzz.yml | 48-49 | `pip install pip==25.0` `pip install pdm==2.26.2` | Version-pinned |
| mypy-type-check.yml | 40,48,49 | `pip install pdm==2.26.2 mypy==1.14.1...` | Version-pinned |
| publish.yml | 137,326 | `pip install pdm==2.26.2` `pip install wheel==0.45.1` | Version-pinned |
| responsive-ui-tests-enhanced.yml | 88-89 | `pip install pip==25.0` `pip install -e .` | Version-pinned + local |
| semgrep.yml | 42 | `pip install semgrep==1.87.0` | Version-pinned |
| update-precommit-hooks.yml | 35-36 | `pip install pip==25.0 pre-commit-update==0.6.2` | Version-pinned |
| validate-image-pinning.yml | 74 | `pip install pyyaml==6.0.2` | Version-pinned |
**Why we don't use hash pinning:**
1. **Platform-specific hashes**: pip package hashes vary by Python version, OS, and architecture.
A single hash won't work across different CI runners.
2. **Maintenance burden**: Every version update requires regenerating hashes for all platforms.
3. **Marginal security benefit**: These are dev/CI tools running in hardened CI environments
(step-security/harden-runner) with egress auditing. Supply chain attacks on PyPI packages
are mitigated by version pinning and short execution windows.
4. **Industry practice**: Version pinning (`==`) is the standard for CI tool installation.
Hash pinning is typically reserved for production dependencies.
5. **Local packages**: `pip install -e .` installs the local source code and cannot be hash-pinned.
### npm Commands: MOSTLY COMPLIANT (21/24) ⚠️
The 3 "unpinned" npm commands are operational commands, not package installations:
| File | Line | Command | Reason Not Pinned |
|------|------|---------|-------------------|
| npm-audit.yml | 56 | `npm i --package-lock-only` | Generates lockfile only |
| npm-audit.yml | 72 | `npm i --package-lock-only` | Generates lockfile only |
| update-npm-dependencies.yml | 74 | `npm update` | Intentionally updates to latest |
These commands don't install packages directly - they either generate lockfiles
or intentionally update packages. They cannot and should not be "pinned".
### downloadThenRun: FALSE POSITIVE ⚠️
**Flagged:** `examples/elasticsearch/test_elasticsearch.sh:60`
```bash
curl -s http://localhost:9200 | python3 -m json.tool | head -10
```
**Why it's a false positive:**
- This fetches JSON from localhost:9200 (local Elasticsearch)
- Pipes to `python3 -m json.tool` (stdlib JSON formatter)
- Shows first 10 lines of pretty-printed output
This is NOT downloading and running a remote script. It's formatting local JSON output.
The scorecard pattern-matches `curl | python` as potentially dangerous, but this
is a safe operation on localhost data.
**OSSF Scorecard Alert:** #4411
### APT Packages: INTENTIONALLY UNPINNED ⚠️
**Files affected:** `publish.yml`, `e2e-research-test.yml`, `responsive-ui-tests-enhanced.yml`, `Dockerfile`
| File | Packages | Runner/Base |
|------|----------|-------------|
| publish.yml | libsqlcipher-dev, patchelf | ubuntu-22.04 |
| e2e-research-test.yml | jq | ubuntu-22.04 |
| responsive-ui-tests-enhanced.yml | wget, gnupg, ca-certificates, fonts-liberation, etc. | ubuntu-latest |
| Dockerfile | curl, git, build-essential, etc. | python:3.13.9-slim@sha256:... |
**Rationale for NOT pinning APT packages:**
1. **Version availability**: Old APT package versions are removed from Ubuntu archives after 6-12 months.
Pinning to `package=1.2.3-1ubuntu1` causes builds to fail when that version is removed.
2. **Base image controls versions**: Docker base images are SHA-pinned, which deterministically controls
which APT package versions are available. The combination of `python:3.13.9-slim@sha256:326df678...`
and `apt-get install curl` produces the same result every time that base image is used.
3. **Runner stability**: GitHub workflow runners use pinned Ubuntu versions (e.g., `ubuntu-22.04`)
which provide consistent package versions throughout the runner's lifecycle.
4. **Version variation**: APT package version strings vary between Ubuntu releases and architectures,
making cross-platform pinning impractical.
5. **Industry consensus**: Security experts recommend pinning the base image/runner rather than
individual packages. Base image pinning provides stronger guarantees with lower maintenance burden.
**Mitigations in place:**
- ✅ Docker base images pinned to SHA256 digests (see Docker Images section above)
- ✅ GitHub runner versions pinned where practical (ubuntu-22.04)
- ✅ Dependabot configured to monitor for security updates
- ✅ Step-security/harden-runner audits all egress traffic
- ✅ Minimal package sets installed (only what's needed)
### Enforcement
We have automated verification for our pinning strategy:
- `.github/workflows/validate-image-pinning.yml` - Validates Docker image digests
- Pre-commit hooks verify action SHA pinning
- All pip install commands use explicit version specifiers
### Review Cadence
These decisions are reviewed quarterly to ensure they remain appropriate:
- **Next review:** Q2 2025
- **Owner:** Security team
## References
- [OSSF Scorecard Pinned-Dependencies Check](https://github.com/ossf/scorecard/blob/main/docs/checks.md#pinned-dependencies)
- [StepSecurity Harden Runner](https://github.com/step-security/harden-runner)
- [pip Hash Checking Mode](https://pip.pypa.io/en/stable/topics/secure-installs/#hash-checking-mode)
Scanned 5/31/2026
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!