software-intake-gatekeeper 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- software_intake_gatekeeper-0.2.1/.gitignore +15 -0
- software_intake_gatekeeper-0.2.1/CHANGELOG.md +57 -0
- software_intake_gatekeeper-0.2.1/LICENSE +21 -0
- software_intake_gatekeeper-0.2.1/PKG-INFO +407 -0
- software_intake_gatekeeper-0.2.1/README.md +369 -0
- software_intake_gatekeeper-0.2.1/SECURITY.md +28 -0
- software_intake_gatekeeper-0.2.1/action-requirements.txt +38 -0
- software_intake_gatekeeper-0.2.1/action.yml +93 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/dist/settings.min.js +2 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/main.js +26 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/node_modules/@demo/ui-kit/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/node_modules/lodash/index.js +2 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/node_modules/lodash/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/node_modules/minimist/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/package.json +8 -0
- software_intake_gatekeeper-0.2.1/examples/demo-app-src/preload.js +2 -0
- software_intake_gatekeeper-0.2.1/examples/go-demo/go.mod +5 -0
- software_intake_gatekeeper-0.2.1/examples/go-demo/go.sum +2 -0
- software_intake_gatekeeper-0.2.1/examples/go-demo/main.go +16 -0
- software_intake_gatekeeper-0.2.1/examples/intake-policy.toml +27 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v1/resources/app/main.js +4 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v1/resources/app/node_modules/lodash/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v1/resources/app/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v2/resources/app/main.js +5 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v2/resources/app/node_modules/axios/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v2/resources/app/node_modules/fast-native/build/Release/addon.node +0 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v2/resources/app/node_modules/lodash/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/update-demo/v2/resources/app/package.json +5 -0
- software_intake_gatekeeper-0.2.1/examples/vulnerable-demo/dotnet/IntakeDemo.deps.json +41 -0
- software_intake_gatekeeper-0.2.1/examples/vulnerable-demo/dotnet/IntakeDemo.runtimeconfig.json +9 -0
- software_intake_gatekeeper-0.2.1/examples/vulnerable-demo/resources/app.asar +0 -0
- software_intake_gatekeeper-0.2.1/pyproject.toml +90 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/__init__.py +3 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/__main__.py +3 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/asar.py +117 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/cli.py +149 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/diff.py +154 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/electron.py +190 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/engine.py +93 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/golang.py +143 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/model.py +207 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/osv.py +302 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/output.py +618 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/policy.py +192 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/py.typed +0 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/rules.py +156 -0
- software_intake_gatekeeper-0.2.1/src/intake_gatekeeper/scanner.py +477 -0
- software_intake_gatekeeper-0.2.1/tests/conftest.py +56 -0
- software_intake_gatekeeper-0.2.1/tests/test_asar.py +106 -0
- software_intake_gatekeeper-0.2.1/tests/test_cli.py +122 -0
- software_intake_gatekeeper-0.2.1/tests/test_diff.py +161 -0
- software_intake_gatekeeper-0.2.1/tests/test_electron.py +84 -0
- software_intake_gatekeeper-0.2.1/tests/test_golang.py +109 -0
- software_intake_gatekeeper-0.2.1/tests/test_live_osv.py +29 -0
- software_intake_gatekeeper-0.2.1/tests/test_osv.py +193 -0
- software_intake_gatekeeper-0.2.1/tests/test_output.py +113 -0
- software_intake_gatekeeper-0.2.1/tests/test_policy.py +167 -0
- software_intake_gatekeeper-0.2.1/tests/test_scanner.py +148 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
.venv/
|
|
4
|
+
/build/
|
|
5
|
+
/dist/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.coverage
|
|
11
|
+
# Built in CI/tests from examples/go-demo; never committed.
|
|
12
|
+
examples/vulnerable-demo/bin/
|
|
13
|
+
tests/.go-fixtures/
|
|
14
|
+
reports/
|
|
15
|
+
intake-gatekeeper.*
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are recorded here. The project follows [Semantic Versioning](https://semver.org/);
|
|
4
|
+
while the major version is 0, minor releases may change behaviour.
|
|
5
|
+
|
|
6
|
+
## [0.2.1] - 2026-10-15
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Published on PyPI: `python -m pip install software-intake-gatekeeper`. Releases are uploaded by
|
|
11
|
+
the release workflow through PyPI trusted publishing, without a stored token.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- README links are absolute so they also work on the PyPI project page.
|
|
16
|
+
|
|
17
|
+
## [0.2.0] - 2026-10-14
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `intake-gatekeeper diff OLD NEW`: compares two versions and decides on what the update adds.
|
|
22
|
+
It reports new and resolved findings, component changes, Electron version and fuse changes
|
|
23
|
+
(flagging weakened fuses), new or removed network endpoints and new, removed or changed
|
|
24
|
+
executables and native modules. SARIF contains only the new findings.
|
|
25
|
+
- `compare-to` input for the GitHub Action to run the update check.
|
|
26
|
+
- Scan reports now list network endpoints referenced by app code and SHA-256 fingerprints of
|
|
27
|
+
executables and native modules.
|
|
28
|
+
- Fictional two-version update demo in `examples/update-demo`.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- The CLI shares its output options between `scan` and `diff`.
|
|
33
|
+
|
|
34
|
+
## [0.1.0] - 2026-10-14
|
|
35
|
+
|
|
36
|
+
First public release and first GitHub Marketplace listing.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Read-only scanner for directories, Electron `.asar` archives and executables (PE, ELF, Mach-O).
|
|
41
|
+
- Inventories: Go build info (Go 1.18+), npm packages on disk and inside ASAR, NuGet `.deps.json`
|
|
42
|
+
packages and runtime packs, .NET `runtimeconfig.json` frameworks, Electron runtime version.
|
|
43
|
+
- Electron hardening: fuse-wire decoding (9 fuses) and `webPreferences` rules with line, column and snippet evidence.
|
|
44
|
+
- Opt-in OSV.dev lookup: batching, pagination, retries, alias grouping, GHSA severity resolution and nearest fixed version.
|
|
45
|
+
- Policy file with thresholds, rule overrides and expiring, component-scoped waivers. APPROVE / REVIEW / REJECT decision; blocking coverage gaps prevent APPROVE.
|
|
46
|
+
- Reports: JSON, CycloneDX 1.6, SARIF 2.1.0 (paths relative to the working directory for code scanning) and Markdown.
|
|
47
|
+
- Composite GitHub Action with hash-pinned dependencies, job summary and `decision`, `sarif` and `sbom` outputs.
|
|
48
|
+
|
|
49
|
+
### Known limitations
|
|
50
|
+
|
|
51
|
+
- Version-level matching, not reachability analysis.
|
|
52
|
+
- No Rust `cargo auditable`, Python wheel, Java or native C/C++ inventories yet.
|
|
53
|
+
- Electron code rules detect literal settings only.
|
|
54
|
+
|
|
55
|
+
[0.2.1]: https://github.com/Sushant-Nemade/software-intake-gatekeeper/releases/tag/v0.2.1
|
|
56
|
+
[0.2.0]: https://github.com/Sushant-Nemade/software-intake-gatekeeper/releases/tag/v0.2.0
|
|
57
|
+
[0.1.0]: https://github.com/Sushant-Nemade/software-intake-gatekeeper/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sushant Nemade
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: software-intake-gatekeeper
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Local, evidence-first intake checks for third-party apps and binaries: SBOM, known vulnerabilities and Electron hardening.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Sushant-Nemade/software-intake-gatekeeper
|
|
6
|
+
Project-URL: Source, https://github.com/Sushant-Nemade/software-intake-gatekeeper
|
|
7
|
+
Project-URL: Changelog, https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/Sushant-Nemade/software-intake-gatekeeper/issues
|
|
9
|
+
Project-URL: GitHub Marketplace, https://github.com/marketplace/actions/software-intake-gatekeeper
|
|
10
|
+
Author: Sushant Nemade
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: cyclonedx,electron,osv,sarif,sbom,security,supply-chain
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Security
|
|
24
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.11
|
|
27
|
+
Requires-Dist: httpx<1,>=0.28
|
|
28
|
+
Requires-Dist: truststore>=0.10
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: cyclonedx-python-lib[json-validation]>=9; extra == 'dev'
|
|
32
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
33
|
+
Requires-Dist: pip-audit>=2.7; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
36
|
+
Requires-Dist: twine>=6; extra == 'dev'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# Software Intake Gatekeeper
|
|
40
|
+
|
|
41
|
+
[](https://github.com/Sushant-Nemade/software-intake-gatekeeper/actions/workflows/ci.yml)
|
|
42
|
+
[](https://github.com/marketplace/actions/software-intake-gatekeeper)
|
|
43
|
+
[](https://pypi.org/project/software-intake-gatekeeper/)
|
|
44
|
+
[](https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/LICENSE)
|
|
45
|
+
|
|
46
|
+
**Before you install, approve or ship a third-party app, find out what is inside it.**
|
|
47
|
+
|
|
48
|
+
Software Intake Gatekeeper reads an installed application, an Electron `.asar` archive or a
|
|
49
|
+
compiled binary. It never runs or unpacks it. It produces:
|
|
50
|
+
|
|
51
|
+
- a **CycloneDX 1.6 SBOM** of the components that are actually bundled,
|
|
52
|
+
- **known vulnerabilities** for those exact versions from [OSV.dev](https://osv.dev) (only when you opt in),
|
|
53
|
+
- **Electron hardening checks** for the fuse wire inside the executable and risky `BrowserWindow`
|
|
54
|
+
settings in the app code,
|
|
55
|
+
- an **APPROVE / REVIEW / REJECT** decision from a versioned policy, with expiring waivers,
|
|
56
|
+
- an **update check** that compares two versions and gates on what the update *adds*: new
|
|
57
|
+
vulnerabilities, weakened Electron fuses, new network endpoints, new native modules,
|
|
58
|
+
- **SARIF** for GitHub code scanning, a **Markdown** summary for pull requests and a full **JSON** evidence report.
|
|
59
|
+
|
|
60
|
+
Every finding names the file and, for scripts, the line, column and snippet that produced it.
|
|
61
|
+
Anything the scanner could not verify is reported as a **coverage gap**. A blocking gap can
|
|
62
|
+
never lead to APPROVE: an unknown result is not treated as safe.
|
|
63
|
+
|
|
64
|
+
> Status: [v0.2.1](https://github.com/Sushant-Nemade/software-intake-gatekeeper/releases/tag/v0.2.1),
|
|
65
|
+
> an alpha release on [PyPI](https://pypi.org/project/software-intake-gatekeeper/) and the
|
|
66
|
+
> [GitHub Marketplace](https://github.com/marketplace/actions/software-intake-gatekeeper). The CLI is
|
|
67
|
+
> tested on Windows and Linux with real Go binaries in three object formats, an ASAR archive packed
|
|
68
|
+
> by the official `@electron/asar` tool and the live OSV API; the action also runs on macOS. The
|
|
69
|
+
> results are static, version-level evidence, not proof of exploitability.
|
|
70
|
+
|
|
71
|
+
Part of a small **software trust toolkit** with
|
|
72
|
+
[Privacy Flow Inspector](https://github.com/Sushant-Nemade/privacy-flow-inspector): this tool checks
|
|
73
|
+
what is **inside** an app; the inspector checks which personal data the app **sends out**.
|
|
74
|
+
|
|
75
|
+

|
|
76
|
+
|
|
77
|
+
## Where it helps
|
|
78
|
+
|
|
79
|
+
| Who | Situation | What they get |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| IT / security intake | An employee requests a desktop tool (an Electron or Go CLI) | An SBOM, known CVEs and Electron hardening issues before approval, with a decision a reviewer can sign off |
|
|
82
|
+
| Product teams shipping Electron | A release candidate is ready | A CI gate that fails when `contextIsolation` is off, `RunAsNode` is enabled or bundled packages have critical advisories |
|
|
83
|
+
| Supply-chain / compliance (EU CRA, medical-device SBOM expectations) | A vendor delivers a binary without an SBOM | A CycloneDX SBOM built from evidence inside the binary, with occurrences pointing to the source files |
|
|
84
|
+
| Procurement / vendor review | Comparing two vendor builds | Reproducible JSON and SBOM output that can be compared across versions |
|
|
85
|
+
|
|
86
|
+
## Quick start
|
|
87
|
+
|
|
88
|
+
Install from [PyPI](https://pypi.org/project/software-intake-gatekeeper/) (Python 3.11+):
|
|
89
|
+
|
|
90
|
+
```powershell
|
|
91
|
+
python -m pip install software-intake-gatekeeper
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To verify build provenance first, install the wheel from the GitHub release instead:
|
|
95
|
+
|
|
96
|
+
```powershell
|
|
97
|
+
gh release download v0.2.1 -R Sushant-Nemade/software-intake-gatekeeper -p "*.whl"
|
|
98
|
+
gh attestation verify software_intake_gatekeeper-0.2.1-py3-none-any.whl -R Sushant-Nemade/software-intake-gatekeeper
|
|
99
|
+
python -m pip install software_intake_gatekeeper-0.2.1-py3-none-any.whl
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Or install from a clone (needed for the demo below):
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
git clone https://github.com/Sushant-Nemade/software-intake-gatekeeper
|
|
106
|
+
cd software-intake-gatekeeper
|
|
107
|
+
python -m pip install .
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then scan:
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
# Offline inventory and Electron checks (no network):
|
|
114
|
+
intake-gatekeeper scan "C:\Program Files\SomeApp"
|
|
115
|
+
|
|
116
|
+
# Add known-vulnerability lookup and write every report:
|
|
117
|
+
intake-gatekeeper scan "C:\Program Files\SomeApp" --osv `
|
|
118
|
+
--json reports/report.json --sarif reports/report.sarif `
|
|
119
|
+
--cyclonedx reports/sbom.cdx.json --markdown reports/summary.md
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Exit status: `0` the decision passed the `--fail-on` threshold (default `reject`), `1` the gate
|
|
123
|
+
failed, `2` usage or input error. Run `intake-gatekeeper rules` to list the configuration rules.
|
|
124
|
+
|
|
125
|
+
### Try the fictional vulnerable demo
|
|
126
|
+
|
|
127
|
+
`examples/vulnerable-demo` is a deliberately insecure, **fictional** target. It contains an ASAR
|
|
128
|
+
archive packed by the official `@electron/asar` tool, a `.deps.json` file and, after the build
|
|
129
|
+
step, a real Go binary and a synthetic Electron executable stand-in.
|
|
130
|
+
|
|
131
|
+
```powershell
|
|
132
|
+
python scripts/build_demo.py # Go is optional; it builds the real Go demo binary
|
|
133
|
+
intake-gatekeeper scan examples/vulnerable-demo --osv --policy examples/intake-policy.toml
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Real output (2026-10-14, live OSV):
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
Decision: REJECT
|
|
140
|
+
- 19 finding(s) at or above high.
|
|
141
|
+
- 41 finding(s) between low and high.
|
|
142
|
+
Target: vulnerable-demo | files 5 | archive entries 8 | lookup osv
|
|
143
|
+
Components: Go 3, NuGet 2, npm 5
|
|
144
|
+
Findings: critical 1, high 18, medium 31, low 10, info 0
|
|
145
|
+
Electron 28.0.0 at bin/electron-runtime-stand-in.bin
|
|
146
|
+
[CRITICAL] GHSA-xvch-5gv4-984h minimist 1.2.5: Prototype Pollution in minimist @ resources/app.asar!/node_modules/minimist/package.json
|
|
147
|
+
[HIGH ] EGK-FUSE-RUN-AS-NODE RunAsNode fuse is enabled @ bin/electron-runtime-stand-in.bin
|
|
148
|
+
[HIGH ] EGK-JS-CONTEXT-ISOLATION-OFF Context isolation is disabled @ resources/app.asar!/main.js:12
|
|
149
|
+
[HIGH ] EGK-JS-NODE-INTEGRATION Renderer has Node.js integration enabled @ resources/app.asar!/main.js:11
|
|
150
|
+
[HIGH ] GHSA-5crp-9r3c-p9vr Newtonsoft.Json 12.0.1: Improper Handling of Exceptional Conditions in Newtonsoft.Json @ dotnet/IntakeDemo.deps.json
|
|
151
|
+
[HIGH ] GHSA-69ch-w2m2-3vjp golang.org/x/text v0.3.7: golang.org/x/text/language Denial of service via crafted Accept-Languag... @ bin/intake-demo-tool.exe
|
|
152
|
+
...
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The Markdown summary also includes a table of components with known vulnerabilities and the
|
|
156
|
+
smallest listed fixed version above the current one (for example `minimist 1.2.6`,
|
|
157
|
+
`Newtonsoft.Json 13.0.1`). One lodash advisory shows as *waived* because the example policy
|
|
158
|
+
accepts it until 2026-12-31 with a written reason.
|
|
159
|
+
|
|
160
|
+
### Check an update before rolling it out
|
|
161
|
+
|
|
162
|
+
`diff` scans the version you run today and the new one, then decides on **what the update adds**.
|
|
163
|
+
Persisting issues are listed but do not block the update; run `scan` for an absolute assessment.
|
|
164
|
+
|
|
165
|
+
```powershell
|
|
166
|
+
intake-gatekeeper diff examples/update-demo/v1 examples/update-demo/v2 --osv `
|
|
167
|
+
--json reports/update.json --markdown reports/update.md --sarif reports/update.sarif
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Real output for the fictional [update demo](https://github.com/Sushant-Nemade/software-intake-gatekeeper/tree/main/examples/update-demo) (2026-10-14, live OSV). Version 2
|
|
171
|
+
fixes a `nodeIntegration` setting and upgrades lodash, but adds axios 0.21.1, a telemetry endpoint and
|
|
172
|
+
a native module:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
Update decision: REJECT
|
|
176
|
+
- 12 new finding(s) at or above high.
|
|
177
|
+
- 13 new finding(s) between low and high.
|
|
178
|
+
- 1 new network endpoint(s) referenced by app code.
|
|
179
|
+
- 1 new executable(s) or native module(s).
|
|
180
|
+
- 1 new component(s).
|
|
181
|
+
Findings: 25 new, 4 resolved, 1 persisting
|
|
182
|
+
Components changed: 2 | endpoints +1/-0 | binaries +1/-0/~0
|
|
183
|
+
NEW [HIGH ] GHSA-cph5-m8f7-6c5x axios 0.21.1: axios Inefficient Regular Expression Complexity vulnerability
|
|
184
|
+
...
|
|
185
|
+
NEW endpoint collect.metrics-collector.example
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| The update check reports | How it is matched |
|
|
189
|
+
|---|---|
|
|
190
|
+
| New and resolved findings | Advisory id plus package name (so a version bump that keeps the bug counts as persisting), or rule plus file |
|
|
191
|
+
| Component changes | Added, removed or changed versions per ecosystem and name |
|
|
192
|
+
| Electron | Runtime version change and every fuse change; a fuse moving into its risky state is **weakened** |
|
|
193
|
+
| Network endpoints | Hosts in `http(s)://` and `ws(s)://` URLs in app code (outside `node_modules`), without XML namespaces or local addresses |
|
|
194
|
+
| Executables and native modules | Added, removed or changed (SHA-256) PE, ELF and Mach-O files, including `.node` modules |
|
|
195
|
+
|
|
196
|
+
**REJECT** if a new finding reaches `reject_at`. **REVIEW** for new findings at `review_at`, weakened
|
|
197
|
+
fuses, new endpoints, new binaries, new components or blocking gaps in the new version.
|
|
198
|
+
**APPROVE** otherwise. The SARIF output contains only the new findings.
|
|
199
|
+
|
|
200
|
+
## What it inspects
|
|
201
|
+
|
|
202
|
+
| Evidence | Source inside the target | Output |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| Go modules and toolchain | Build info embedded by the Go linker (Go 1.18+) in PE, ELF and Mach-O executables | `pkg:golang/...` components, including `stdlib` and `replace` directives |
|
|
205
|
+
| npm packages | `node_modules/**/package.json` on disk and inside `.asar` archives | `pkg:npm/...` components; the app's own manifest is recorded but not queried |
|
|
206
|
+
| NuGet packages | `*.deps.json` (`package` and self-contained `runtimepack` entries) | `pkg:nuget/...` components |
|
|
207
|
+
| .NET shared framework | `*.runtimeconfig.json` | Minimum framework version, plus a note that the host runtime decides the patch level |
|
|
208
|
+
| Electron runtime | The fuse sentinel and `Electron/x.y.z` string in the executable | Electron version (queried as npm `electron`) and the fuse states |
|
|
209
|
+
| Electron app code | `.js/.cjs/.mjs/.ts` files outside `node_modules`, on disk or in `.asar` | `webPreferences` rule findings with line, column and snippet |
|
|
210
|
+
| Network endpoints | `http(s)://` and `ws(s)://` hosts referenced by that app code | Host list with up to three source files each (used by the update check) |
|
|
211
|
+
| Executables and native modules | PE, ELF and Mach-O files, including `.node` add-ons | Path, size, SHA-256 and kind (Go, Electron, native) |
|
|
212
|
+
|
|
213
|
+
### Electron rules
|
|
214
|
+
|
|
215
|
+
| Rule | Default | Detects |
|
|
216
|
+
|---|---|---|
|
|
217
|
+
| `EGK-JS-NODE-INTEGRATION` | high | `nodeIntegration: true` (also minified `!0`) |
|
|
218
|
+
| `EGK-JS-CONTEXT-ISOLATION-OFF` | high | `contextIsolation: false` |
|
|
219
|
+
| `EGK-JS-WEB-SECURITY-OFF` | high | `webSecurity: false` |
|
|
220
|
+
| `EGK-JS-INSECURE-CONTENT` | high | `allowRunningInsecureContent: true` |
|
|
221
|
+
| `EGK-JS-SANDBOX-OFF` | medium | `sandbox: false` within a `webPreferences` object |
|
|
222
|
+
| `EGK-JS-NODE-INTEGRATION-EXTENDED` | medium | Node.js in sub-frames or workers |
|
|
223
|
+
| `EGK-JS-REMOTE-MODULE` | medium | `enableRemoteModule: true` |
|
|
224
|
+
| `EGK-JS-WEBVIEW-TAG` / `EGK-JS-EXPERIMENTAL-FEATURES` | low | `<webview>` or experimental features enabled |
|
|
225
|
+
| `EGK-JS-OPEN-EXTERNAL` | info | `shell.openExternal(` call sites to review |
|
|
226
|
+
| `EGK-FUSE-RUN-AS-NODE`, `-NODE-OPTIONS`, `-NODE-INSPECT` | medium | Fuses that let a trusted binary run arbitrary Node.js code |
|
|
227
|
+
| `EGK-FUSE-ASAR-INTEGRITY-OFF`, `-LOAD-OUTSIDE-ASAR`, `-COOKIE-ENCRYPTION-OFF`, `-FILE-PROTOCOL-PRIVILEGES` | low | Integrity and hardening fuses left at their defaults |
|
|
228
|
+
|
|
229
|
+
Each rule links to the matching section of Electron's
|
|
230
|
+
[security checklist](https://www.electronjs.org/docs/latest/tutorial/security) or
|
|
231
|
+
[fuses guide](https://www.electronjs.org/docs/latest/tutorial/fuses).
|
|
232
|
+
|
|
233
|
+
## Decision model
|
|
234
|
+
|
|
235
|
+
```mermaid
|
|
236
|
+
flowchart LR
|
|
237
|
+
T[Target: folder / .asar / binary] --> S[Read-only scanner]
|
|
238
|
+
S --> C[Components + evidence]
|
|
239
|
+
S --> F[Electron findings]
|
|
240
|
+
S --> G[Coverage gaps]
|
|
241
|
+
C -->|--osv, opt-in| O[OSV.dev: ecosystem, name, version only]
|
|
242
|
+
O --> V[Alias-grouped advisories + nearest fix]
|
|
243
|
+
F --> P[Policy: thresholds, overrides, expiring waivers]
|
|
244
|
+
V --> P
|
|
245
|
+
G --> P
|
|
246
|
+
P --> D{APPROVE / REVIEW / REJECT}
|
|
247
|
+
D --> R[JSON, SARIF, CycloneDX, Markdown]
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
- **REJECT**: any unwaived finding at or above `reject_at` (default `high`).
|
|
251
|
+
- **REVIEW**: findings at or above `review_at` (default `low`), or any blocking coverage gap,
|
|
252
|
+
such as a skipped lookup, an OSV failure, a size or file limit, an unparseable artifact or no
|
|
253
|
+
recognised content.
|
|
254
|
+
- **APPROVE**: none of the above.
|
|
255
|
+
|
|
256
|
+
Advisories that describe the same issue (for example `GHSA-69ch-w2m2-3vjp` and `GO-2022-1059`) are
|
|
257
|
+
merged into one finding. Severity comes from the GitHub-reviewed database rating, including linked
|
|
258
|
+
GHSA aliases. Advisories that no database rates (common for Go) are treated as
|
|
259
|
+
`unrated_vulnerability` (default `medium`) and labelled as such.
|
|
260
|
+
|
|
261
|
+
### Policy
|
|
262
|
+
|
|
263
|
+
See [examples/intake-policy.toml](https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/examples/intake-policy.toml). Unknown keys are rejected. Every waiver
|
|
264
|
+
needs an id or alias, a written reason and an expiry date, and may be limited to one package URL.
|
|
265
|
+
Expired or unused waivers are reported.
|
|
266
|
+
|
|
267
|
+
## GitHub Action
|
|
268
|
+
|
|
269
|
+
Available on the [GitHub Marketplace](https://github.com/marketplace/actions/software-intake-gatekeeper).
|
|
270
|
+
It runs on Linux, Windows and macOS runners; CI exercises all three.
|
|
271
|
+
|
|
272
|
+
### Gate a packaged Electron app and publish alerts to code scanning
|
|
273
|
+
|
|
274
|
+
```yaml
|
|
275
|
+
name: Intake gate
|
|
276
|
+
on: [pull_request, workflow_dispatch]
|
|
277
|
+
|
|
278
|
+
permissions:
|
|
279
|
+
contents: read
|
|
280
|
+
security-events: write # only needed for the SARIF upload step
|
|
281
|
+
|
|
282
|
+
jobs:
|
|
283
|
+
intake:
|
|
284
|
+
runs-on: ubuntu-latest
|
|
285
|
+
steps:
|
|
286
|
+
- uses: actions/checkout@v7
|
|
287
|
+
# ... build or download the app you want to check into dist/linux-unpacked ...
|
|
288
|
+
- name: Software Intake Gatekeeper
|
|
289
|
+
id: intake
|
|
290
|
+
uses: Sushant-Nemade/software-intake-gatekeeper@v0
|
|
291
|
+
with:
|
|
292
|
+
path: dist/linux-unpacked
|
|
293
|
+
fail-on: reject
|
|
294
|
+
- name: Upload SARIF
|
|
295
|
+
if: always() && steps.intake.outputs.sarif != ''
|
|
296
|
+
uses: github/codeql-action/upload-sarif@v4
|
|
297
|
+
with:
|
|
298
|
+
sarif_file: ${{ steps.intake.outputs.sarif }}
|
|
299
|
+
category: software-intake-gatekeeper
|
|
300
|
+
- name: Keep the SBOM and evidence
|
|
301
|
+
if: always()
|
|
302
|
+
uses: actions/upload-artifact@v7
|
|
303
|
+
with:
|
|
304
|
+
name: intake-gatekeeper-reports
|
|
305
|
+
path: intake-gatekeeper-reports/
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
For supply-chain hardening, pin the action to the full commit SHA of a release instead of `@v0`.
|
|
309
|
+
|
|
310
|
+
### Inputs
|
|
311
|
+
|
|
312
|
+
| Input | Default | Description |
|
|
313
|
+
|---|---|---|
|
|
314
|
+
| `path` | (required) | Installed app directory, `.asar` archive or executable to scan. |
|
|
315
|
+
| `compare-to` | `""` | Previous version of the same app. When set, the action runs the update check and gates on what the update adds. |
|
|
316
|
+
| `osv` | `true` | Look up known vulnerabilities on OSV.dev. Sends only ecosystem, name and version. Set `false` for fully offline runs. |
|
|
317
|
+
| `policy` | `""` | Path to a policy TOML file (see [examples/intake-policy.toml](https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/examples/intake-policy.toml)). |
|
|
318
|
+
| `fail-on` | `reject` | Decision that fails the step: `reject`, `review` or `never`. |
|
|
319
|
+
| `output-dir` | `intake-gatekeeper-reports` | Where `report.json`, `report.sarif`, `sbom.cdx.json` and `summary.md` are written. |
|
|
320
|
+
|
|
321
|
+
### Outputs
|
|
322
|
+
|
|
323
|
+
| Output | Description |
|
|
324
|
+
|---|---|
|
|
325
|
+
| `decision` | `approve`, `review` or `reject` (`error` if no report was produced). |
|
|
326
|
+
| `sarif` | Path to the SARIF 2.1.0 report. Paths inside it are relative to the workspace so code scanning can link them. |
|
|
327
|
+
| `sbom` | Path to the CycloneDX 1.6 SBOM. |
|
|
328
|
+
|
|
329
|
+
The Markdown summary is appended to the job summary. The action installs hash-pinned
|
|
330
|
+
dependencies into a private virtual environment under `RUNNER_TEMP`, so it does not change the
|
|
331
|
+
job's Python. Inputs reach the script only through environment variables and are never
|
|
332
|
+
interpolated into shell code. No token or secret is required.
|
|
333
|
+
|
|
334
|
+
### Versioning
|
|
335
|
+
|
|
336
|
+
Releases follow [Semantic Versioning](https://semver.org/) and are listed in [CHANGELOG.md](https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/CHANGELOG.md).
|
|
337
|
+
`v0` always points to the latest `v0.x.y` release. Release artifacts carry
|
|
338
|
+
[build provenance attestations](https://github.com/Sushant-Nemade/software-intake-gatekeeper/attestations)
|
|
339
|
+
and a `SHA256SUMS` file.
|
|
340
|
+
|
|
341
|
+
## Privacy and network use
|
|
342
|
+
|
|
343
|
+
- Without `--osv` the tool makes **no network requests**.
|
|
344
|
+
- With `--osv`, it sends only `{ecosystem, name, version}` for each queryable component to
|
|
345
|
+
`https://api.osv.dev` (or a mirror set with `--osv-url`). It sends no file paths, hashes or file
|
|
346
|
+
contents. Private package names are sent as well, so use an internal OSV mirror if those names
|
|
347
|
+
are sensitive.
|
|
348
|
+
- TLS verification uses the operating-system trust store through
|
|
349
|
+
[truststore](https://pypi.org/project/truststore/), so corporate TLS inspection works without
|
|
350
|
+
disabling verification.
|
|
351
|
+
|
|
352
|
+
## Verification
|
|
353
|
+
|
|
354
|
+
| Check | How |
|
|
355
|
+
|---|---|
|
|
356
|
+
| Go build info decoding | Compared with `go version -m` on real binaries built in CI for Windows PE, Linux ELF and macOS Mach-O |
|
|
357
|
+
| ASAR parsing | Fixture packed by `@electron/asar` 4.3.1; listing matches the official tool |
|
|
358
|
+
| Fuse decoding | Wire layout taken from `@electron/fuses`. A read-only local check on an installed Electron app (VS Code) matched `npx @electron/fuses read` for all 9 fuses |
|
|
359
|
+
| Output formats | CycloneDX validated with `cyclonedx-python-lib` against the 1.6 schema in tests. SARIF validated against the OASIS 2.1.0 schema during development |
|
|
360
|
+
| OSV client | Mocked transport tests (batching, pagination, retries, alias grouping, withdrawn advisories) plus an opt-in live test (`INTAKE_LIVE_OSV=1`) |
|
|
361
|
+
| Scale | Read-only scan of a locally installed VS Code: 3,243 files and 5,451 archive entries in about 19 s with a warm file cache |
|
|
362
|
+
| CI | Ubuntu (Python 3.11 and 3.13) and Windows (3.13): pytest, ruff, mypy `--strict`, build, twine, pip-audit. The action itself runs on Ubuntu, Windows and macOS against the demo with live OSV, plus fail-on, invalid-input and update-check (`compare-to`) runs |
|
|
363
|
+
|
|
364
|
+
No third-party application files are committed. The local real-app checks are listed for
|
|
365
|
+
transparency only.
|
|
366
|
+
|
|
367
|
+
## Limitations
|
|
368
|
+
|
|
369
|
+
- Version matching is not reachability. A vulnerable function may never be called; use waivers
|
|
370
|
+
with reasons when you have checked this.
|
|
371
|
+
- It reads Go build info only for Go 1.18+ (older binaries are reported as gaps). It does not yet
|
|
372
|
+
read Rust `cargo auditable` sections, Python wheels, Java JARs or native C/C++ libraries.
|
|
373
|
+
- Electron code rules are pattern-based. They catch literal settings, including minified ones,
|
|
374
|
+
but not values computed at runtime.
|
|
375
|
+
- Installers (`.exe`/`.msi`/`.dmg`) must be extracted or installed first. The tool does not unpack
|
|
376
|
+
archives to disk.
|
|
377
|
+
- Electron versions are detected from the `Electron/x.y.z` string; if none or several are found,
|
|
378
|
+
this is reported as a gap.
|
|
379
|
+
|
|
380
|
+
## Roadmap
|
|
381
|
+
|
|
382
|
+
1. Rust `cargo auditable`, Python `*.dist-info` and Java `pom.properties` inventories.
|
|
383
|
+
2. Signature and publisher changes (Authenticode, code signing) in the update check.
|
|
384
|
+
3. An optional adapter for reverse-engineering evidence tools behind an approval gate.
|
|
385
|
+
|
|
386
|
+
Shipped from earlier roadmap items: the version-to-version update check (v0.2.0) and the
|
|
387
|
+
PII-in-HAR inspector, released as the separate
|
|
388
|
+
[Privacy Flow Inspector](https://github.com/Sushant-Nemade/privacy-flow-inspector).
|
|
389
|
+
|
|
390
|
+
## Development
|
|
391
|
+
|
|
392
|
+
```powershell
|
|
393
|
+
python -m pip install uv
|
|
394
|
+
uv sync --frozen --extra dev
|
|
395
|
+
$env:INTAKE_GO = "C:\path\to\go.exe" # optional; enables real Go binary tests
|
|
396
|
+
uv run --frozen --extra dev pytest -q
|
|
397
|
+
uv run --frozen --extra dev ruff check .
|
|
398
|
+
uv run --frozen --extra dev mypy
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Background and license
|
|
402
|
+
|
|
403
|
+
The idea came from studying evidence-first reverse-engineering tools, which show the evidence for
|
|
404
|
+
every conclusion and state what they could not determine. This project applies that approach to
|
|
405
|
+
software intake. All code here is original; no third-party tool source is included.
|
|
406
|
+
|
|
407
|
+
[MIT](https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/LICENSE) © 2026 Sushant Nemade. See [SECURITY.md](https://github.com/Sushant-Nemade/software-intake-gatekeeper/blob/main/SECURITY.md) for vulnerability reporting.
|