SafeSC
Supply-chain trust auditing for CI pipelines — SafeSC discovers your dependency lockfiles, verifies provenance, and scores every dependency across five trust dimensions (identity, behavior, provenance, popularity, vulnerability). Deterministic signals do the heavy lifting; an LLM is used only to reason about the small, suspicious subset and can only raise severity, never lower it.
- Deterministic spine, agentic fan-out. Stages 0–3 (discover → parse → verify hashes → cheap signals) always run in a fixed order. Only gray-zone dependencies fan out to LLM specialists (name-squatting, install-script intent, provenance gaps).
- Bring-your-own-key (BYOK). You supply your own LLM key, provider, and model. SafeSC holds no server-side key; keys never enter logs, reports, or persisted state.
- One-step CI gate. A single GitHub Action installs SafeSC, runs the audit, uploads a SARIF report to code scanning, archives artifacts, and fails the build on a critical finding.
Quick start — GitHub Action
Add the following workflow to a consumer repository (e.g. .github/workflows/safesc.yml)
and create a repository secret named SAFESC_LLM_API_KEY with your BYOK LLM key. There is
no default provider — you must choose one:
name: SafeSC
on: [push]
permissions:
actions: read
contents: read
security-events: write # required to upload the SARIF report
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: JAAAACCCCCCKKKK/SafeSC@v1
with:
llm-api-key: ${{ secrets.SAFESC_LLM_API_KEY }}
llm-provider: anthropic # required: anthropic | openai
To pin a specific model or route to a custom endpoint, add the optional inputs:
- uses: JAAAACCCCCCKKKK/SafeSC@v1
with:
target: "." # repo path, lockfile, or git URL
llm-api-key: ${{ secrets.SAFESC_LLM_API_KEY }}
llm-provider: openai # required: anthropic | openai
llm-model: gpt-4o # blank = provider default
llm-base-url: https://your-gateway/v1 # any OpenAI-compatible endpoint
format: all # all | json | markdown | sarif
report-dir: safesc-reports
Action inputs
| Input | Required | Default | Description |
|---|---|---|---|
llm-api-key |
✅ | — | BYOK reasoning-LLM API key for your chosen provider. Pass a secret. |
llm-provider |
✅ | — | anthropic or openai (also any OpenAI-compatible endpoint via llm-base-url). No default. |
llm-model |
provider default | Model id, e.g. claude-sonnet-5, gpt-4o. Blank = provider default. |
|
llm-base-url |
— | Override the LLM base URL (proxy / gateway / Bedrock / Azure / OpenAI-compatible). | |
target |
. |
Repo path, lockfile, or git URL to audit. | |
format |
all |
Report format(s): all | json | markdown | sarif. |
|
report-dir |
safesc-reports |
Directory to write JSON / Markdown / SARIF artifacts. | |
python-version |
3.12 |
Python version used to run SafeSC. | |
upload-sarif |
true |
Upload the SARIF report to GitHub code scanning. | |
upload-artifact |
true |
Archive report-dir as a build artifact. |
|
artifact-name |
safesc-reports |
Name for the archived artifact. |
Output: exit-code — 0 = gate pass, 1 = gate fail on a critical finding.
SARIF upload (code scanning).
upload-sarif: trueneeds the job to grantpermissions: security-events: writeand a repo where code scanning is available (public repos, or private repos with GitHub Advanced Security). If either is missing, GitHub returnsResource not accessible by integration; SafeSC treats this as non-fatal — it prints a warning, still archives the report artifact, and the audit's exit code is unaffected. Setupload-sarif: falseto skip the upload entirely.
Choosing your model & provider
SafeSC is provider-agnostic for the reasoning LLM. A provider is required (there is no default) — pick one, optionally a model, and pass your own key via the Action inputs above, environment variables (CLI/CI), or API headers.
| Provider | llm-provider |
Default model | Notes |
|---|---|---|---|
| Anthropic | anthropic |
claude-sonnet-5 |
Native Claude API. |
| OpenAI | openai |
gpt-4o |
Native OpenAI API. |
| OpenAI-compatible | openai + llm-base-url |
(set your own) | Azure OpenAI, OpenRouter, Together, Groq, Ollama, vLLM, LiteLLM proxy… |
Need another provider? Register one at runtime without editing SafeSC:
from safesc.graph.llm_client import register_llm_provider
register_llm_provider("my-provider", my_factory) # my_factory(LLMCredentials) -> LLMClient
CLI usage
Install the CI tier (deterministic spine + LLM specialists, no Redis/Postgres required):
Install the orchestration extra plus the SDK for your chosen provider (there is no default provider, so no provider SDK is bundled):
pip install "safesc[agent,anthropic]" # Anthropic provider
pip install "safesc[agent,openai]" # OpenAI / OpenAI-compatible provider
Then supply your key and provider via the environment and run:
export SAFESC_LLM_API_KEY=sk-ant-...
export SAFESC_LLM_PROVIDER=anthropic # required — no default
# Full-repo audit (produces a CI exit code)
safesc audit . --report-dir safesc-reports --format all
# Single-package investigation (evidence only, never fails CI)
safesc query npm:left-pad@1.3.0
Use a different provider/model entirely through the environment:
export SAFESC_LLM_PROVIDER=openai
export SAFESC_LLM_MODEL=gpt-4o
export SAFESC_LLM_API_KEY=sk-...
# Or a local OpenAI-compatible server (e.g. Ollama):
export SAFESC_LLM_PROVIDER=openai
export SAFESC_LLM_BASE_URL=http://localhost:11434/v1
export SAFESC_LLM_MODEL=mixtral
The frozen Stage 0–3 tools are also exposed as standalone commands: index (discover /
parse) and scan (verify / signals).
Environment variables
| Variable | Required | Description |
|---|---|---|
SAFESC_LLM_API_KEY |
✅ | BYOK reasoning-LLM key. |
SAFESC_LLM_PROVIDER |
✅ | anthropic or openai — required, no default. |
SAFESC_LLM_MODEL |
Model id (blank = provider default). | |
SAFESC_LLM_BASE_URL |
Override the LLM base URL. | |
SAFESC_EMBEDDING_API_KEY |
Only if the optional memory layer is enabled. | |
SAFESC_EMBEDDING_BASE_URL / SAFESC_EMBEDDING_MODEL |
Embedding provider overrides. |
Supported ecosystems
Python (uv / poetry / pip), npm / pnpm, Cargo (Rust), Go modules, and Maven / Gradle (Java).
Reports
Every run can emit SARIF (for GitHub code scanning), Markdown (human-readable), and
JSON (machine-readable), written as safesc-report.{sarif,md,json}.
Optional extras
| Extra | Installs | Purpose |
|---|---|---|
agent |
LangGraph | CI-tier orchestration: spine + LLM specialists (no provider SDK). |
anthropic |
Anthropic SDK | Anthropic (Claude) provider. |
openai |
OpenAI SDK | OpenAI and OpenAI-compatible providers. |
memory |
Redis + Postgres/PGVector | Optional long-term memory (retrieval grounding only; never changes a verdict). |
Security
SafeSC is a security tool and treats your credentials as load-bearing: keys are held as
SecretStr, threaded by injection only, and never enter the audit state (which may be
checkpointed to Redis), logs, reports, or the vector store. There is no ambient/shared key
fallback — a missing key is a hard error.
License
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file safesc-1.2.0.tar.gz.
File metadata
- Download URL: safesc-1.2.0.tar.gz
- Upload date:
- Size: 318.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd340a8a111605e27769bd7d1cfa615a76d83ee1562feb36ab5616b27e61d166
|
|
| MD5 |
1479a88c6f7a1c6dff454fb9cb0abfe2
|
|
| BLAKE2b-256 |
e688c6984244549b6ceff340448fa94a5e682ec9131500d82b64fc55b9f4191d
|
Provenance
The following attestation bundles were made for safesc-1.2.0.tar.gz:
Publisher:
publish.yml on JAAAACCCCCCKKKK/SafeSC
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
safesc-1.2.0.tar.gz -
Subject digest:
fd340a8a111605e27769bd7d1cfa615a76d83ee1562feb36ab5616b27e61d166 - Sigstore transparency entry: 2391736207
- Sigstore integration time:
-
Permalink:
JAAAACCCCCCKKKK/SafeSC@5f75ae418eb32eb7a013e6ce0824c952621711e5 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/JAAAACCCCCCKKKK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5f75ae418eb32eb7a013e6ce0824c952621711e5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file safesc-1.2.0-py3-none-any.whl.
File metadata
- Download URL: safesc-1.2.0-py3-none-any.whl
- Upload date:
- Size: 167.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94f1165fd4ae30800298d9c71389eecfaf01fb70ef9a1ebb8afd4c726f57cbd2
|
|
| MD5 |
781075fe3f8a995677903a876d5b33e6
|
|
| BLAKE2b-256 |
1a24b5fd57f128a292ee45c417935540e69678d31286aa584ccbdda5b528f3f7
|
Provenance
The following attestation bundles were made for safesc-1.2.0-py3-none-any.whl:
Publisher:
publish.yml on JAAAACCCCCCKKKK/SafeSC
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
safesc-1.2.0-py3-none-any.whl -
Subject digest:
94f1165fd4ae30800298d9c71389eecfaf01fb70ef9a1ebb8afd4c726f57cbd2 - Sigstore transparency entry: 2391736966
- Sigstore integration time:
-
Permalink:
JAAAACCCCCCKKKK/SafeSC@5f75ae418eb32eb7a013e6ce0824c952621711e5 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/JAAAACCCCCCKKKK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5f75ae418eb32eb7a013e6ce0824c952621711e5 -
Trigger Event:
release
-
Statement type: