Audit a CI workflow for what it leaves movable or undeclared
Audit a CI workflow for what it leaves movable or undeclared. Reports actions pinned to a tag rather than a commit - a tag can be moved by whoever owns the action, so the code a step runs can change without this file changing - missing permissions and timeouts, a job depending on one that is not declared, a pull_request_target trigger, and an expression interpolated straight into a shell command.
Paid test badge: not yet. The checks above are free: we call the tool without paying and read the payment request it sends back. The Verified badge needs paid calls whose answers match the promised output, and nobody can buy a badge.
Endpoint
POST https://api.zfinia.com/x402/v1/ci-workflow-contract-audit
| Category | Code and developer |
|---|---|
| Provider host | api.zfinia.com |
| Networks | eip155:8453 |
| Payment schemes | exact |
| Self-reported calls, 30 days | 1 from 1 payers (the provider's figure, not ours) |
Our checks, last 30 days
We never call tools that send, buy, move money or file anything, not even without paying.
Example input (from the provider)
{
"body": {
"contract": {
"required_jobs": [
"build",
"publish",
"lint"
]
},
"workflow": {
"jobs": {
"build": {
"runs-on": "ubuntu-latest",
"steps": [
{
"uses": "actions/checkout@v4"
},
{
"uses": "actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8"
},
{
"name": "Greet",
"run": "echo \"Building ${{ github.event.pull_request.title }}\""
},
{
"run": "npm ci && npm test"
}
]
},
"notify": {
"needs": [
"publish",
"lint"
],
"runs-on": "ubuntu-latest",
"steps": [
{
"run": "echo done"
}
]
},
"publish": {
"needs": "build",
"permissions": {
"contents": "read",
"packages": "write"
},
"runs-on": "ubuntu-latest",
"steps": [
{
"uses": "actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3"
}
],
"timeout-minutes": 15
}
},
"name": "release",
"on": {
"pull_request_target": {},
"push": {
"branches": [
"main"
]
}
}
}
},
"bodyType": "json",
"method": "POST",
"type": "http"
}
Promised output schema (from the provider)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"input": {
"additionalProperties": false,
"properties": {
"body": {
"additionalProperties": false,
"properties": {
"contract": {
"additionalProperties": false,
"properties": {
"forbid_pull_request_target": {
"type": "boolean"
},
"require_permissions": {
"type": "boolean"
},
"require_pinned_actions": {
"type": "boolean"
},
"require_timeout": {
"type": "boolean"
},
"required_jobs": {
"items": {
"maxLength": 128,
"type": "string"
},
"maxItems": 200,
"minItems": 1,
"type": "array"
}
},
"type": "object"
},
"workflow": {
"type": "object"
}
},
"required": [
"workflow"
],
"type": "object"
},
"bodyType": {
"enum": [
"json",
"form-data",
"text"
],
"type": "string"
},
"method": {
"enum": [
"POST"
],
"type": "string"
},
"type": {
"const": "http",
"type": "string"
}
},
"required": [
"type",
"method",
"bodyType",
"body"
],
"type": "object"
},
"output": {
"properties": {
"example": {
"type": "object"
},
"type": {
"type": "string"
}
},
"required": [
"type"
],
"type": "object"
}
},
"required": [
"input"
],
"type": "object"
}