codex-plugin-scanner 1.0.0__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.
- codex_plugin_scanner-1.0.0/.github/CODEOWNERS +1 -0
- codex_plugin_scanner-1.0.0/.github/workflows/ci.yml +22 -0
- codex_plugin_scanner-1.0.0/.github/workflows/publish.yml +81 -0
- codex_plugin_scanner-1.0.0/.github/workflows/scorecard.yml +26 -0
- codex_plugin_scanner-1.0.0/.gitignore +42 -0
- codex_plugin_scanner-1.0.0/CONTRIBUTING.md +38 -0
- codex_plugin_scanner-1.0.0/LICENSE +118 -0
- codex_plugin_scanner-1.0.0/PKG-INFO +174 -0
- codex_plugin_scanner-1.0.0/README.md +144 -0
- codex_plugin_scanner-1.0.0/SECURITY.md +34 -0
- codex_plugin_scanner-1.0.0/pyproject.toml +56 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/__init__.py +14 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/checks/__init__.py +0 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/checks/best_practices.py +171 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/checks/code_quality.py +91 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/checks/manifest.py +121 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/checks/marketplace.py +130 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/checks/security.py +185 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/cli.py +154 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/models.py +57 -0
- codex_plugin_scanner-1.0.0/src/codex_plugin_scanner/scanner.py +44 -0
- codex_plugin_scanner-1.0.0/tests/__init__.py +0 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/__init__.py +0 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/bad-plugin/.mcp.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/bad-plugin/secrets.js +3 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/code-quality-bad/evil.js +4 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/code-quality-bad/inject.js +2 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/good-plugin/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/good-plugin/.codexignore +3 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/good-plugin/LICENSE +17 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/good-plugin/README.md +3 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/good-plugin/SECURITY.md +3 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/good-plugin/skills/example/SKILL.md +5 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/malformed-json/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/missing-fields/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/mit-license/LICENSE +5 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/no-version/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +1 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/with-marketplace/marketplace-broken.json +8 -0
- codex_plugin_scanner-1.0.0/tests/fixtures/with-marketplace/marketplace.json +12 -0
- codex_plugin_scanner-1.0.0/tests/test_best_practices.py +104 -0
- codex_plugin_scanner-1.0.0/tests/test_cli.py +138 -0
- codex_plugin_scanner-1.0.0/tests/test_code_quality.py +79 -0
- codex_plugin_scanner-1.0.0/tests/test_coverage_remaining.py +146 -0
- codex_plugin_scanner-1.0.0/tests/test_edge_cases.py +157 -0
- codex_plugin_scanner-1.0.0/tests/test_final_coverage.py +52 -0
- codex_plugin_scanner-1.0.0/tests/test_integration.py +106 -0
- codex_plugin_scanner-1.0.0/tests/test_manifest.py +129 -0
- codex_plugin_scanner-1.0.0/tests/test_marketplace.py +110 -0
- codex_plugin_scanner-1.0.0/tests/test_scanner.py +113 -0
- codex_plugin_scanner-1.0.0/tests/test_security.py +121 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @hashgraph-online/core
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: [main]
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: ${{ matrix.python-version }}
|
|
18
|
+
cache: pip
|
|
19
|
+
- run: pip install -e ".[dev]"
|
|
20
|
+
- run: ruff check src/
|
|
21
|
+
- run: ruff format --check src/
|
|
22
|
+
- run: pytest --tb=short
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
publish_target:
|
|
7
|
+
description: "Target repository"
|
|
8
|
+
required: true
|
|
9
|
+
default: testpypi
|
|
10
|
+
type: choice
|
|
11
|
+
options:
|
|
12
|
+
- testpypi
|
|
13
|
+
- pypi
|
|
14
|
+
push:
|
|
15
|
+
tags:
|
|
16
|
+
- "v*"
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
concurrency:
|
|
23
|
+
group: codex-plugin-scanner-publish-${{ github.ref }}
|
|
24
|
+
cancel-in-progress: false
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
build:
|
|
28
|
+
name: Build + Verify
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
- uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.12"
|
|
35
|
+
cache: "pip"
|
|
36
|
+
cache-dependency-path: pyproject.toml
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: |
|
|
39
|
+
python -m pip install --upgrade pip
|
|
40
|
+
pip install build twine
|
|
41
|
+
- name: Build package
|
|
42
|
+
run: python -m build
|
|
43
|
+
- name: Verify distributions
|
|
44
|
+
run: twine check dist/*
|
|
45
|
+
- name: Upload artifacts
|
|
46
|
+
uses: actions/upload-artifact@v4
|
|
47
|
+
with:
|
|
48
|
+
name: distributions
|
|
49
|
+
path: dist/
|
|
50
|
+
|
|
51
|
+
publish-testpypi:
|
|
52
|
+
name: Publish to TestPyPI
|
|
53
|
+
if: github.event.inputs.publish_target == 'testpypi'
|
|
54
|
+
needs: build
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
environment: testpypi
|
|
57
|
+
permissions:
|
|
58
|
+
id-token: write
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/download-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: distributions
|
|
63
|
+
path: dist/
|
|
64
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
65
|
+
with:
|
|
66
|
+
repository-url: https://test.pypi.org/legacy/
|
|
67
|
+
|
|
68
|
+
publish-pypi:
|
|
69
|
+
name: Publish to PyPI
|
|
70
|
+
if: github.event.inputs.publish_target != 'testpypi'
|
|
71
|
+
needs: build
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
environment: pypi
|
|
74
|
+
permissions:
|
|
75
|
+
id-token: write
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/download-artifact@v4
|
|
78
|
+
with:
|
|
79
|
+
name: distributions
|
|
80
|
+
path: dist/
|
|
81
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: OpenSSF Scorecard
|
|
2
|
+
on:
|
|
3
|
+
schedule:
|
|
4
|
+
- cron: '0 0 * * 0'
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
security-events: write
|
|
11
|
+
jobs:
|
|
12
|
+
scorecard:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
- uses: ossf/scorecard-action@v2
|
|
19
|
+
with:
|
|
20
|
+
results_file: results.sarif
|
|
21
|
+
results_format: sarif
|
|
22
|
+
publish_results: true
|
|
23
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
24
|
+
with:
|
|
25
|
+
sarif_file: results.sarif
|
|
26
|
+
if: always()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
*.egg-info/
|
|
13
|
+
*.egg
|
|
14
|
+
|
|
15
|
+
# Virtual environments
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
|
|
20
|
+
# Testing
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
coverage/
|
|
25
|
+
|
|
26
|
+
# Tooling
|
|
27
|
+
.ruff_cache/
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
|
|
35
|
+
# OS
|
|
36
|
+
.DS_Store
|
|
37
|
+
Thumbs.db
|
|
38
|
+
|
|
39
|
+
# Environment
|
|
40
|
+
.env
|
|
41
|
+
.env.*
|
|
42
|
+
!.env.example
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Contributing to Codex Plugin Scanner
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/hashgraph-online/codex-plugin-scanner.git
|
|
9
|
+
cd codex-plugin-scanner
|
|
10
|
+
pip install -e ".[dev]"
|
|
11
|
+
pytest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Adding New Checks
|
|
15
|
+
|
|
16
|
+
1. Create a new check function in the appropriate file under `src/codex_plugin_scanner/checks/`.
|
|
17
|
+
2. Add it to the corresponding `run_*_checks()` function.
|
|
18
|
+
3. Write tests in `tests/`.
|
|
19
|
+
4. Update the README's checks table.
|
|
20
|
+
5. Submit a PR.
|
|
21
|
+
|
|
22
|
+
## Code Style
|
|
23
|
+
|
|
24
|
+
- Python 3.10+
|
|
25
|
+
- Ruff for linting and formatting
|
|
26
|
+
- All checks must return a `CheckResult` with accurate point values
|
|
27
|
+
|
|
28
|
+
## Pull Request Process
|
|
29
|
+
|
|
30
|
+
1. Fork the repo
|
|
31
|
+
2. Create a feature branch
|
|
32
|
+
3. Write tests for new functionality
|
|
33
|
+
4. Ensure `pytest` passes and `ruff check` is clean
|
|
34
|
+
5. Submit PR against `main`
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
By contributing, you agree that your contributions will be licensed under Apache-2.0.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity.
|
|
18
|
+
|
|
19
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
20
|
+
exercising permissions granted by this License.
|
|
21
|
+
|
|
22
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
23
|
+
including but not limited to software source code, documentation
|
|
24
|
+
source, and configuration files.
|
|
25
|
+
|
|
26
|
+
"Object" form shall mean any form resulting from mechanical
|
|
27
|
+
transformation or translation of a Source form.
|
|
28
|
+
|
|
29
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
30
|
+
Object form.
|
|
31
|
+
|
|
32
|
+
"Derivative Works" shall mean any work that is based on the Work
|
|
33
|
+
and for which the editorial revisions, annotations, elaborations,
|
|
34
|
+
or other modifications represent, as a whole, an original work of
|
|
35
|
+
authorship.
|
|
36
|
+
|
|
37
|
+
"Contribution" shall mean any work of authorship, including the
|
|
38
|
+
original version of the Work and any modifications or additions.
|
|
39
|
+
|
|
40
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
41
|
+
on behalf of whom a Contribution has been received.
|
|
42
|
+
|
|
43
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
44
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
45
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
46
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
47
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
48
|
+
Work and such Derivative Works in Source or Object form.
|
|
49
|
+
|
|
50
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
51
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
52
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
53
|
+
(except as stated in this section) patent license to make, have made,
|
|
54
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
55
|
+
where such license applies only to those patent claims licensable
|
|
56
|
+
by such Contributor that are necessarily infringed by their
|
|
57
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
58
|
+
with the Work to which such Contribution(s) was submitted.
|
|
59
|
+
|
|
60
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
61
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
62
|
+
modifications, and in Source or Object form, provided that You
|
|
63
|
+
meet the following conditions:
|
|
64
|
+
|
|
65
|
+
(a) You must give any other recipients of the Work or
|
|
66
|
+
Derivative Works a copy of this License; and
|
|
67
|
+
|
|
68
|
+
(b) You must cause any modified files to carry prominent notices
|
|
69
|
+
stating that You changed the files; and
|
|
70
|
+
|
|
71
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
72
|
+
that You distribute, all copyright, patent, trademark, and
|
|
73
|
+
attribution notices from the Source form of the Work; and
|
|
74
|
+
|
|
75
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
76
|
+
distribution, then any Derivative Works that You distribute must
|
|
77
|
+
include a readable copy of the attribution notices contained
|
|
78
|
+
within such NOTICE file.
|
|
79
|
+
|
|
80
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
81
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
82
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
83
|
+
this License, without any additional terms or conditions.
|
|
84
|
+
|
|
85
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
86
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
87
|
+
except as required for reasonable and customary use in describing the
|
|
88
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
89
|
+
|
|
90
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
91
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
92
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
93
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
94
|
+
implied, including, without limitation, any warranties or conditions
|
|
95
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
96
|
+
PARTICULAR PURPOSE.
|
|
97
|
+
|
|
98
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
99
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
100
|
+
unless required by applicable law, Contributor be liable for any
|
|
101
|
+
damages, including any direct, indirect, special, incidental, or
|
|
102
|
+
consequential damages.
|
|
103
|
+
|
|
104
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
105
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
106
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
107
|
+
or other liability obligations and/or rights consistent with this
|
|
108
|
+
License.
|
|
109
|
+
|
|
110
|
+
END OF TERMS AND CONDITIONS
|
|
111
|
+
|
|
112
|
+
Copyright 2026 Hashgraph Online
|
|
113
|
+
|
|
114
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
115
|
+
you may not use this file except in compliance with the License.
|
|
116
|
+
You may obtain a copy of the License at
|
|
117
|
+
|
|
118
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-plugin-scanner
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Security and best-practices scanner for Codex CLI plugins. Scores plugins 0-100.
|
|
5
|
+
Project-URL: Homepage, https://github.com/hashgraph-online/codex-plugin-scanner
|
|
6
|
+
Project-URL: Repository, https://github.com/hashgraph-online/codex-plugin-scanner
|
|
7
|
+
Project-URL: Issues, https://github.com/hashgraph-online/codex-plugin-scanner/issues
|
|
8
|
+
Author-email: Hashgraph Online <dev@hol.org>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,codex,mcp,plugin,scanner,security
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# 🔗 Codex Plugin Scanner
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/codex-plugin-scanner/)
|
|
34
|
+
[](https://pypi.org/project/codex-plugin-scanner/)
|
|
35
|
+
[](LICENSE)
|
|
36
|
+
[](https://github.com/hashgraph-online/codex-plugin-scanner/actions/workflows/ci.yml)
|
|
37
|
+
[](https://scorecard.dev/viewer/?uri=github.com/hashgraph-online/codex-plugin-scanner)
|
|
38
|
+
|
|
39
|
+
A security and best-practices scanner for [Codex CLI plugins](https://developers.openai.com/codex/plugins). Scans plugin directories and outputs a score from 0-100.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install codex-plugin-scanner
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Or run directly without installing:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pipx run codex-plugin-scanner ./my-plugin
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Scan a plugin directory
|
|
57
|
+
codex-plugin-scanner ./my-plugin
|
|
58
|
+
|
|
59
|
+
# Output as JSON
|
|
60
|
+
codex-plugin-scanner ./my-plugin --json
|
|
61
|
+
|
|
62
|
+
# Write report to file
|
|
63
|
+
codex-plugin-scanner ./my-plugin --output report.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Example Output
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
🔗 Codex Plugin Scanner v1.0.0
|
|
70
|
+
Scanning: ./my-plugin
|
|
71
|
+
|
|
72
|
+
── Manifest Validation (25/25) ──
|
|
73
|
+
✅ plugin.json exists +5
|
|
74
|
+
✅ Valid JSON +5
|
|
75
|
+
✅ Required fields present +8
|
|
76
|
+
✅ Version follows semver +4
|
|
77
|
+
✅ Name is kebab-case +3
|
|
78
|
+
|
|
79
|
+
── Security (30/30) ──
|
|
80
|
+
✅ SECURITY.md found +5
|
|
81
|
+
✅ LICENSE found (Apache-2.0) +5
|
|
82
|
+
✅ No hardcoded secrets detected +10
|
|
83
|
+
✅ No dangerous MCP commands +10
|
|
84
|
+
|
|
85
|
+
── Best Practices (25/25) ──
|
|
86
|
+
✅ README.md found +5
|
|
87
|
+
✅ Skills directory exists if declared +5
|
|
88
|
+
✅ SKILL.md frontmatter +5
|
|
89
|
+
✅ No .env files committed +5
|
|
90
|
+
✅ .codexignore found +5
|
|
91
|
+
|
|
92
|
+
── Marketplace (10/10) ──
|
|
93
|
+
✅ marketplace.json valid +5
|
|
94
|
+
✅ Policy fields present +5
|
|
95
|
+
|
|
96
|
+
── Code Quality (10/10) ──
|
|
97
|
+
✅ No eval or Function constructor +5
|
|
98
|
+
✅ No shell injection patterns +5
|
|
99
|
+
|
|
100
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
101
|
+
Final Score: 100/100 (A - Excellent)
|
|
102
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Scoring Breakdown
|
|
106
|
+
|
|
107
|
+
| Category | Max Points | Checks |
|
|
108
|
+
|----------|-----------|--------|
|
|
109
|
+
| Manifest Validation | 25 | plugin.json exists, valid JSON, required fields, semver version, kebab-case name |
|
|
110
|
+
| Security | 30 | SECURITY.md, LICENSE, no hardcoded secrets, no dangerous MCP commands |
|
|
111
|
+
| Best Practices | 25 | README.md, skills directory, SKILL.md frontmatter, no .env files, .codexignore |
|
|
112
|
+
| Marketplace | 10 | marketplace.json valid, policy fields present |
|
|
113
|
+
| Code Quality | 10 | no eval/Function, no shell injection |
|
|
114
|
+
|
|
115
|
+
### Grade Scale
|
|
116
|
+
|
|
117
|
+
| Score | Grade | Meaning |
|
|
118
|
+
|-------|-------|---------|
|
|
119
|
+
| 90-100 | A | Excellent |
|
|
120
|
+
| 80-89 | B | Good |
|
|
121
|
+
| 70-79 | C | Acceptable |
|
|
122
|
+
| 60-69 | D | Needs Improvement |
|
|
123
|
+
| 0-59 | F | Failing |
|
|
124
|
+
|
|
125
|
+
## Security Checks
|
|
126
|
+
|
|
127
|
+
The scanner detects:
|
|
128
|
+
|
|
129
|
+
- **Hardcoded secrets**: AWS keys, GitHub tokens, OpenAI keys, Slack tokens, GitLab tokens, generic password/secret/token patterns
|
|
130
|
+
- **Dangerous MCP commands**: `rm -rf`, `sudo`, `curl|sh`, `wget|sh`, `eval`, `exec`, `powershell -c`
|
|
131
|
+
- **Shell injection**: template literals with unsanitized interpolation in exec/spawn calls
|
|
132
|
+
- **Unsafe code**: `eval()` and `new Function()` usage
|
|
133
|
+
|
|
134
|
+
## Use as a GitHub Action
|
|
135
|
+
|
|
136
|
+
Add to your plugin's CI:
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
- name: Install scanner
|
|
140
|
+
run: pip install codex-plugin-scanner
|
|
141
|
+
- name: Scan plugin
|
|
142
|
+
run: codex-plugin-scanner ./my-plugin
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Use as a pre-commit hook
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
repos:
|
|
149
|
+
- repo: local
|
|
150
|
+
hooks:
|
|
151
|
+
- id: codex-plugin-scanner
|
|
152
|
+
name: Codex Plugin Scanner
|
|
153
|
+
entry: codex-plugin-scanner
|
|
154
|
+
language: system
|
|
155
|
+
types: [directory]
|
|
156
|
+
pass_filenames: false
|
|
157
|
+
args: ["./"]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
pip install -e ".[dev]"
|
|
164
|
+
pytest
|
|
165
|
+
ruff check src/
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Contributing
|
|
169
|
+
|
|
170
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
[Apache-2.0](LICENSE) - Hashgraph Online
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# 🔗 Codex Plugin Scanner
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/codex-plugin-scanner/)
|
|
4
|
+
[](https://pypi.org/project/codex-plugin-scanner/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/hashgraph-online/codex-plugin-scanner/actions/workflows/ci.yml)
|
|
7
|
+
[](https://scorecard.dev/viewer/?uri=github.com/hashgraph-online/codex-plugin-scanner)
|
|
8
|
+
|
|
9
|
+
A security and best-practices scanner for [Codex CLI plugins](https://developers.openai.com/codex/plugins). Scans plugin directories and outputs a score from 0-100.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install codex-plugin-scanner
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or run directly without installing:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pipx run codex-plugin-scanner ./my-plugin
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Scan a plugin directory
|
|
27
|
+
codex-plugin-scanner ./my-plugin
|
|
28
|
+
|
|
29
|
+
# Output as JSON
|
|
30
|
+
codex-plugin-scanner ./my-plugin --json
|
|
31
|
+
|
|
32
|
+
# Write report to file
|
|
33
|
+
codex-plugin-scanner ./my-plugin --output report.json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Example Output
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
🔗 Codex Plugin Scanner v1.0.0
|
|
40
|
+
Scanning: ./my-plugin
|
|
41
|
+
|
|
42
|
+
── Manifest Validation (25/25) ──
|
|
43
|
+
✅ plugin.json exists +5
|
|
44
|
+
✅ Valid JSON +5
|
|
45
|
+
✅ Required fields present +8
|
|
46
|
+
✅ Version follows semver +4
|
|
47
|
+
✅ Name is kebab-case +3
|
|
48
|
+
|
|
49
|
+
── Security (30/30) ──
|
|
50
|
+
✅ SECURITY.md found +5
|
|
51
|
+
✅ LICENSE found (Apache-2.0) +5
|
|
52
|
+
✅ No hardcoded secrets detected +10
|
|
53
|
+
✅ No dangerous MCP commands +10
|
|
54
|
+
|
|
55
|
+
── Best Practices (25/25) ──
|
|
56
|
+
✅ README.md found +5
|
|
57
|
+
✅ Skills directory exists if declared +5
|
|
58
|
+
✅ SKILL.md frontmatter +5
|
|
59
|
+
✅ No .env files committed +5
|
|
60
|
+
✅ .codexignore found +5
|
|
61
|
+
|
|
62
|
+
── Marketplace (10/10) ──
|
|
63
|
+
✅ marketplace.json valid +5
|
|
64
|
+
✅ Policy fields present +5
|
|
65
|
+
|
|
66
|
+
── Code Quality (10/10) ──
|
|
67
|
+
✅ No eval or Function constructor +5
|
|
68
|
+
✅ No shell injection patterns +5
|
|
69
|
+
|
|
70
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
71
|
+
Final Score: 100/100 (A - Excellent)
|
|
72
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Scoring Breakdown
|
|
76
|
+
|
|
77
|
+
| Category | Max Points | Checks |
|
|
78
|
+
|----------|-----------|--------|
|
|
79
|
+
| Manifest Validation | 25 | plugin.json exists, valid JSON, required fields, semver version, kebab-case name |
|
|
80
|
+
| Security | 30 | SECURITY.md, LICENSE, no hardcoded secrets, no dangerous MCP commands |
|
|
81
|
+
| Best Practices | 25 | README.md, skills directory, SKILL.md frontmatter, no .env files, .codexignore |
|
|
82
|
+
| Marketplace | 10 | marketplace.json valid, policy fields present |
|
|
83
|
+
| Code Quality | 10 | no eval/Function, no shell injection |
|
|
84
|
+
|
|
85
|
+
### Grade Scale
|
|
86
|
+
|
|
87
|
+
| Score | Grade | Meaning |
|
|
88
|
+
|-------|-------|---------|
|
|
89
|
+
| 90-100 | A | Excellent |
|
|
90
|
+
| 80-89 | B | Good |
|
|
91
|
+
| 70-79 | C | Acceptable |
|
|
92
|
+
| 60-69 | D | Needs Improvement |
|
|
93
|
+
| 0-59 | F | Failing |
|
|
94
|
+
|
|
95
|
+
## Security Checks
|
|
96
|
+
|
|
97
|
+
The scanner detects:
|
|
98
|
+
|
|
99
|
+
- **Hardcoded secrets**: AWS keys, GitHub tokens, OpenAI keys, Slack tokens, GitLab tokens, generic password/secret/token patterns
|
|
100
|
+
- **Dangerous MCP commands**: `rm -rf`, `sudo`, `curl|sh`, `wget|sh`, `eval`, `exec`, `powershell -c`
|
|
101
|
+
- **Shell injection**: template literals with unsanitized interpolation in exec/spawn calls
|
|
102
|
+
- **Unsafe code**: `eval()` and `new Function()` usage
|
|
103
|
+
|
|
104
|
+
## Use as a GitHub Action
|
|
105
|
+
|
|
106
|
+
Add to your plugin's CI:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
- name: Install scanner
|
|
110
|
+
run: pip install codex-plugin-scanner
|
|
111
|
+
- name: Scan plugin
|
|
112
|
+
run: codex-plugin-scanner ./my-plugin
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Use as a pre-commit hook
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
repos:
|
|
119
|
+
- repo: local
|
|
120
|
+
hooks:
|
|
121
|
+
- id: codex-plugin-scanner
|
|
122
|
+
name: Codex Plugin Scanner
|
|
123
|
+
entry: codex-plugin-scanner
|
|
124
|
+
language: system
|
|
125
|
+
types: [directory]
|
|
126
|
+
pass_filenames: false
|
|
127
|
+
args: ["./"]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Development
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install -e ".[dev]"
|
|
134
|
+
pytest
|
|
135
|
+
ruff check src/
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
[Apache-2.0](LICENSE) - Hashgraph Online
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---------|-----------|
|
|
7
|
+
| 1.x | Yes |
|
|
8
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
If you discover a security vulnerability in this project, please report it responsibly:
|
|
12
|
+
|
|
13
|
+
1. Do not open a public issue.
|
|
14
|
+
2. Email us at security@hol.org with details.
|
|
15
|
+
3. Include steps to reproduce, expected vs actual behavior, and potential impact.
|
|
16
|
+
4. We will acknowledge within 48 hours and aim to resolve within 7 days.
|
|
17
|
+
|
|
18
|
+
## Security Best Practices
|
|
19
|
+
|
|
20
|
+
This tool helps you follow security best practices for Codex plugins. For the latest guidance, see the [Codex Security documentation](https://developers.openai.com/codex/security).
|
|
21
|
+
|
|
22
|
+
### For Plugin Authors
|
|
23
|
+
|
|
24
|
+
- Never commit API keys, tokens, or secrets to your repository.
|
|
25
|
+
- Use environment variables for sensitive configuration.
|
|
26
|
+
- Avoid dangerous shell commands in `.mcp.json` configurations.
|
|
27
|
+
- Include a `SECURITY.md` in your plugin repository.
|
|
28
|
+
- Use permissive licenses (Apache-2.0 or MIT) for clarity.
|
|
29
|
+
|
|
30
|
+
### For Scanner Users
|
|
31
|
+
|
|
32
|
+
- This scanner checks for common patterns but does not guarantee security.
|
|
33
|
+
- Always review plugin code manually before installation.
|
|
34
|
+
- Keep this tool updated for the latest check definitions.
|