COBOL · JCL · CICS
Security analysis that reads COBOL the way the compiler does.
cobolwork finds where untrusted data reaches an operating-system command, dynamic SQL, a program transfer or a file name, following it from the command line, a job’s PARM, a CICS terminal or a web request across program boundaries.
npm install -g @portll/cobolwork
- Runtime dependencies
- 0
- Node
- 22 or later
- Licence
- AGPL-3.0-or-later
critargv-or-env-to-os-commandCWE-78
Line 10 of pos/P2.cbl in front, line 8 of pos/P1.cbl behind, each punched in IBM 029 card code. The command line read on the back card reaches CALL 'SYSTEM' on the front card in 4 hops.
Why it exists
COBOL in open‑source security tooling
Nothing open source reads COBOL for security.
VisualCodeGrepper, the one open-source COBOL scanner, matches regular expressions within a single file. A Semgrep run over a COBOL-only repository loads three thousand rules, reads none of its COBOL, exits zero and reports a clean result.
Measured: 2026-09-16
- 0SemgrepCOBOL rules
- 0CodeQLCOBOL rules
- 0SonarQube Community EditionCOBOL rules
- 0PMDCOBOL rules
- 0NIST SARDCOBOL test cases
- 0gitleaks, TruffleHogrules for a RACF password, a JCL
PASSWORD=or a TSO logon
Features
What cobolwork gives a COBOL estate
Each feature below has a section of its own on the Features page.
Cross-program data flow
Finds injection that crosses program boundaries.
Untrusted input is followed from the command line, a job’s PARM, a CICS terminal, a web request or a CICS queue, through CALL … USING in COBOL and PL/I, to the command, SQL statement, program transfer or file name it reaches.
The estate beside its COBOL
The rest of a mainframe estate is read beside its COBOL.
PL/I programs join the data flow, IMS DBDs and PSBs, Db2 DDL and HLASM are read by rule sets of their own, and a z/OS download is read as its data sets.
Findings with their route
Each finding shows its route from input to operation, and how to fix it.
It carries the trace, the impact and remedy for its rule, and a fingerprint that code added above it leaves unchanged.
Evidence beside severity
Each finding says who should act on it.
Every rule declares what it established: a traced path, a defective construct, tampering, an advisory, an exposure, a change, an outcome seen in a run, a coverage gap or context.
Coverage with every scan
A short list of findings over unread source does not pass for a clean result.
coverageIncomplete is set by an unresolved copybook, an unreadable file, a symlink leading out of the tree, or a statement a reader refuses.
Build gate
A build that adds a route to a command, a program, SQL or a job stops before it ships.
cobolwork build is a CI step, and its exit status is its verdict; a change is judged by the policy of its base, and --precompile checks that CICS and SQL programs compile once translated.
Parser graded against GnuCOBOL
Findings rest on a parser that matches the compiler on every data item, size and call.
It was measured on 21,707 files in 500 repositories never used while building it, and differs on one label of 146,004.
Compliance mappings
Each finding carries the clause that makes it an obligation, in each framework that has one.
DORA, FFIEC and NIST SP 800-53 are quoted verbatim; COBIT 2019 is mapped by identifier.
Install
One package and no dependencies
Nothing else to install or vet: cobolwork has no dependencies, runtime or development.
npm install -g @portll/cobolwork or pip install cobolwork puts cobolwork on your PATH; the PyPI package runs the same files with the Node.js on your PATH. Each release, and what it brought, is on Releases.
Limit: Node 22 or later. GnuCOBOL is needed only to regrade the parser or validate benchmark cases.
pip install cobolwork
To run from a checkout instead: git clone https://github.com/Portll/cobolwork, then npm link in it. In a GitHub workflow, uses: Portll/cobolwork@main runs the build gate on a pull request and writes SARIF for code scanning. Every document cobolwork writes or reads has a JSON Schema under schema/, and STABILITY.md lists what a release keeps.
| Command | Information |
|---|---|
cobolwork scan <path> | Every rule set, as JSON or SARIF--format --out --repos --only --quiet --full-trace --all-routes --baseline --no-baseline --advisories --copylib --pds-export --mvs38-forms --no-mvs38-forms --hlasm-optable --evidence |
cobolwork flow <path> | Where untrusted data reaches a sensitive operation, with the path it took--out --repos --quiet --full-trace --all-routes --baseline --no-baseline --copylib --evidence |
cobolwork build <repo> | The build gate’s verdict, with every finding ranked LOW to KNOWN-EXPLOITABLE--base --head --policy --provenance --provenance-format --artifact --equivalence --allowed-signers --ironwork --precompile --advisories --copylib --pds-export --no-baseline --format --out --evidence |
cobolwork diff <repo> --base <ref> | What a change reaches: layouts it moves in programs nobody edited, new call targets, findings it adds or removes--head --format --out --only --quiet --full-trace --copylib --pds-export --evidence |
cobolwork baseline <path> | Findings already judged, each with a reason, who judged it and an expiry--reason --who --expires --action --rule --out --repos --only --advisories --copylib --evidence |
cobolwork inventory <path> | The inventory, and what could not be read--out --quiet --copylib --evidence |
cobolwork parse <file> | One file’s structure, for debugging--out |
Licence
Running cobolwork over your own source triggers nothing in the AGPL that unmodified internal use does not already satisfy.
AGPL-3.0-or-later. Other terms are available on application for organisations where policy refuses AGPL; LICENSING.md says what they are and what a grant does and does not reach.
Reports
A false positive or a missed finding is the most useful report to send: precision and recall are measured and published, and a report can move either.
File it as an ordinary issue. Vulnerabilities in cobolwork go through SECURITY.md, privately.