flowsec 0.1.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.
- flowsec-0.1.0/.devcontainer/devcontainer.json +21 -0
- flowsec-0.1.0/.env.example +6 -0
- flowsec-0.1.0/.github/workflows/publish.yml +32 -0
- flowsec-0.1.0/.gitignore +28 -0
- flowsec-0.1.0/.pre-commit-config.yaml +22 -0
- flowsec-0.1.0/.python-version +0 -0
- flowsec-0.1.0/Dockerfile +15 -0
- flowsec-0.1.0/Makefile +24 -0
- flowsec-0.1.0/PKG-INFO +206 -0
- flowsec-0.1.0/README.md +171 -0
- flowsec-0.1.0/docker-compose.yml +6 -0
- flowsec-0.1.0/docs/FULL_README.md +367 -0
- flowsec-0.1.0/pyproject.toml +72 -0
- flowsec-0.1.0/src/pipelineguard/__init__.py +0 -0
- flowsec-0.1.0/src/pipelineguard/ai_narrative.py +73 -0
- flowsec-0.1.0/src/pipelineguard/cli.py +141 -0
- flowsec-0.1.0/src/pipelineguard/parser.py +33 -0
- flowsec-0.1.0/src/pipelineguard/report.py +35 -0
- flowsec-0.1.0/src/pipelineguard/rules/__init__.py +0 -0
- flowsec-0.1.0/src/pipelineguard/rules/artifact_signing.py +63 -0
- flowsec-0.1.0/src/pipelineguard/rules/base.py +37 -0
- flowsec-0.1.0/src/pipelineguard/rules/dependency_pinning.py +72 -0
- flowsec-0.1.0/src/pipelineguard/rules/excessive_permissions.py +40 -0
- flowsec-0.1.0/src/pipelineguard/rules/hardcoded_secrets.py +119 -0
- flowsec-0.1.0/src/pipelineguard/rules/missing_branch_protection.py +15 -0
- flowsec-0.1.0/src/pipelineguard/rules/missing_env_protection.py +33 -0
- flowsec-0.1.0/src/pipelineguard/rules/missing_oidc.py +56 -0
- flowsec-0.1.0/src/pipelineguard/rules/missing_timeout.py +65 -0
- flowsec-0.1.0/src/pipelineguard/rules/pull_request_target.py +58 -0
- flowsec-0.1.0/src/pipelineguard/rules/secrets_in_run.py +64 -0
- flowsec-0.1.0/src/pipelineguard/rules/self_hosted_runner.py +79 -0
- flowsec-0.1.0/src/pipelineguard/rules/unpinned_actions.py +45 -0
- flowsec-0.1.0/src/pipelineguard/rules/workflow_dispatch_injection.py +44 -0
- flowsec-0.1.0/src/pipelineguard/scanner.py +84 -0
- flowsec-0.1.0/src/pipelineguard/scoring.py +0 -0
- flowsec-0.1.0/tests/__init__.py +0 -0
- flowsec-0.1.0/tests/conftest.py +0 -0
- flowsec-0.1.0/tests/fixtures/sample_azure_vulnerable.yml +36 -0
- flowsec-0.1.0/tests/fixtures/sample_gitlab_vulnerable.yml +31 -0
- flowsec-0.1.0/tests/fixtures/sample_workflow_clean.yml +0 -0
- flowsec-0.1.0/tests/fixtures/sample_workflow_vulnerable.yml +34 -0
- flowsec-0.1.0/tests/test_parser.py +0 -0
- flowsec-0.1.0/tests/test_rules_artifact_signing.py +0 -0
- flowsec-0.1.0/tests/test_rules_excessive_permissions.py +0 -0
- flowsec-0.1.0/tests/test_rules_hardcoded_secrets.py +0 -0
- flowsec-0.1.0/tests/test_rules_missing_oidc.py +0 -0
- flowsec-0.1.0/tests/test_rules_missing_timeout.py +0 -0
- flowsec-0.1.0/tests/test_rules_pull_request_target.py +0 -0
- flowsec-0.1.0/tests/test_rules_self_hosted_runner.py +0 -0
- flowsec-0.1.0/tests/test_rules_unpinned_actions.py +0 -0
- flowsec-0.1.0/tests/test_scanner.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "FlowSec",
|
|
3
|
+
"image": "mcr.microsoft.com/devcontainers/python:3.11",
|
|
4
|
+
"postCreateCommand": "pip install -e '.[dev]'",
|
|
5
|
+
"containerEnv": {
|
|
6
|
+
"PYTHONPATH": "/workspaces/FlowSec/src"
|
|
7
|
+
},
|
|
8
|
+
"customizations": {
|
|
9
|
+
"vscode": {
|
|
10
|
+
"extensions": [
|
|
11
|
+
"ms-python.python",
|
|
12
|
+
"ms-python.vscode-pylance",
|
|
13
|
+
"ms-python.black-formatter"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"forwardPorts": [],
|
|
18
|
+
"remoteEnv": {
|
|
19
|
+
"PYTHONPATH": "/workspaces/FlowSec/src"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v3
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
|
|
22
|
+
- name: Install hatch
|
|
23
|
+
run: pip install hatch
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: hatch build
|
|
30
|
+
|
|
31
|
+
- name: Publish to PyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
flowsec-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.ruff_cache/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
htmlcov/
|
|
13
|
+
.coverage
|
|
14
|
+
|
|
15
|
+
# Secrets
|
|
16
|
+
.env
|
|
17
|
+
|
|
18
|
+
# Virtual environment
|
|
19
|
+
path/
|
|
20
|
+
venv/
|
|
21
|
+
.venv/
|
|
22
|
+
|
|
23
|
+
# Reports
|
|
24
|
+
*.html
|
|
25
|
+
!src/pipelineguard/templates/*.html.j2
|
|
26
|
+
|
|
27
|
+
# OS
|
|
28
|
+
.DS_Store
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v4.6.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: check-yaml
|
|
6
|
+
- id: check-toml
|
|
7
|
+
- id: detect-private-key
|
|
8
|
+
- id: end-of-file-fixer
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
|
|
11
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
12
|
+
rev: v0.4.4
|
|
13
|
+
hooks:
|
|
14
|
+
- id: ruff
|
|
15
|
+
args: [--fix]
|
|
16
|
+
- id: ruff-format
|
|
17
|
+
|
|
18
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
19
|
+
rev: v1.10.0
|
|
20
|
+
hooks:
|
|
21
|
+
- id: mypy
|
|
22
|
+
additional_dependencies: [types-PyYAML, types-requests]
|
|
File without changes
|
flowsec-0.1.0/Dockerfile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# ── Builder stage ─────────────────────────────────────
|
|
2
|
+
FROM python:3.11-slim AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY pyproject.toml .
|
|
5
|
+
RUN pip install --no-cache-dir hatchling && \
|
|
6
|
+
pip install --no-cache-dir -e ".[dev]" 2>/dev/null || true
|
|
7
|
+
|
|
8
|
+
# ── Final stage ───────────────────────────────────────
|
|
9
|
+
FROM python:3.11-slim
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
|
|
12
|
+
COPY src/ ./src/
|
|
13
|
+
COPY pyproject.toml .
|
|
14
|
+
RUN pip install --no-cache-dir -e .
|
|
15
|
+
ENTRYPOINT ["pipelineguard"]
|
flowsec-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.PHONY: install lint type-check test security build clean
|
|
2
|
+
|
|
3
|
+
install:
|
|
4
|
+
pip install -e ".[dev]"
|
|
5
|
+
pre-commit install
|
|
6
|
+
|
|
7
|
+
lint:
|
|
8
|
+
ruff check src/ tests/
|
|
9
|
+
ruff format --check src/ tests/
|
|
10
|
+
|
|
11
|
+
type-check:
|
|
12
|
+
mypy src/
|
|
13
|
+
|
|
14
|
+
test:
|
|
15
|
+
pytest
|
|
16
|
+
|
|
17
|
+
security:
|
|
18
|
+
bandit -r src/
|
|
19
|
+
|
|
20
|
+
build:
|
|
21
|
+
hatch build
|
|
22
|
+
|
|
23
|
+
clean:
|
|
24
|
+
rm -rf dist/ build/ .coverage htmlcov/ .pytest_cache/ .mypy_cache/
|
flowsec-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flowsec
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CI/CD pipeline security analyzer — scans GitHub Actions, GitLab CI, and Azure DevOps configs for attack vectors
|
|
5
|
+
Author-email: Vansh Bhardwaj <Scorpio.vansh@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: cicd,devsecops,github-actions,pipeline-security,sast,security
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Topic :: Security
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Requires-Dist: anthropic>=0.28.0
|
|
15
|
+
Requires-Dist: httpx>=0.27.0
|
|
16
|
+
Requires-Dist: jinja2>=3.1.4
|
|
17
|
+
Requires-Dist: jsonpath-ng>=1.6.1
|
|
18
|
+
Requires-Dist: pygithub>=2.1.1
|
|
19
|
+
Requires-Dist: pygments>=2.18.0
|
|
20
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
21
|
+
Requires-Dist: python-gitlab>=4.4.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
23
|
+
Requires-Dist: rich>=13.7.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: bandit>=1.7.8; extra == 'dev'
|
|
26
|
+
Requires-Dist: hatch>=1.12.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pre-commit>=3.7.1; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-mock>=3.14.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.2.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: responses>=0.25.3; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.4.4; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# FlowSec
|
|
37
|
+
|
|
38
|
+
> A Python security tool that scans CI/CD pipeline configurations for attack vectors across GitHub Actions, GitLab CI, and Azure DevOps. Every finding maps to a MITRE ATT&CK technique and OWASP CICD Top 10 category.
|
|
39
|
+
>
|
|
40
|
+
> The pipeline is the attack surface. FlowSec treats it that way.
|
|
41
|
+
|
|
42
|
+
**[Full documentation](docs/FULL_README.md)**
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
[](https://codespaces.new/VanshBhardwaj1945/FlowSec)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## What it catches
|
|
51
|
+
|
|
52
|
+
| ID | Rule | Severity | MITRE | OWASP |
|
|
53
|
+
|---|---|---|---|---|
|
|
54
|
+
| FS001 | Hardcoded Secret — Plaintext Credential in Workflow | CRITICAL | T1552.001 | CICD-SEC-6 |
|
|
55
|
+
| FS002 | Unpinned Action — Supply Chain Attack Vector | CRITICAL | T1195.001 | CICD-SEC-3 |
|
|
56
|
+
| FS003 | Excessive Permissions — Overprivileged Workflow Token | HIGH | T1078 | CICD-SEC-5 |
|
|
57
|
+
| FS004 | Missing OIDC — Long-Lived Cloud Credential in Use | HIGH | T1552.004 | CICD-SEC-6 |
|
|
58
|
+
| FS005 | Pull Request Target — Secrets Exposed to Fork Code | CRITICAL | T1611 | CICD-SEC-4 |
|
|
59
|
+
| FS006 | Missing Timeout — Job Runs Up to 6 Hours Unchecked | LOW | T1499 | CICD-SEC-10 |
|
|
60
|
+
| FS007 | Self-Hosted Runner — Persistent Environment Risk | HIGH | T1053 | CICD-SEC-7 |
|
|
61
|
+
| FS008 | Missing Artifact Signing — No Tamper Protection | MEDIUM | T1553 | CICD-SEC-8 |
|
|
62
|
+
| FS009 | Unpinned Dependency — Package Installed Without Version Lock | HIGH | T1195.002 | CICD-SEC-3 |
|
|
63
|
+
| FS010 | Secret in Run Command — Plaintext Credential in Shell Step | CRITICAL | T1552.001 | CICD-SEC-6 |
|
|
64
|
+
| FS011 | Missing Branch Protection — Direct Push to Default Branch Possible | HIGH | T1098 | CICD-SEC-1 |
|
|
65
|
+
| FS012 | Missing Environment Protection — Deploy Job Has No Approval Gate | HIGH | T1078 | CICD-SEC-5 |
|
|
66
|
+
| FS013 | Workflow Dispatch Injection — Unvalidated Input in Shell Command | CRITICAL | T1059 | CICD-SEC-9 |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Platforms supported
|
|
71
|
+
|
|
72
|
+
| Platform | How to scan |
|
|
73
|
+
|---|---|
|
|
74
|
+
| GitHub Actions | `flowsec scan --repo owner/repo` or `--file workflow.yml` |
|
|
75
|
+
| GitLab CI | `flowsec scan --gitlab .gitlab-ci.yml` |
|
|
76
|
+
| Azure DevOps | `flowsec scan --azure azure-pipelines.yml` |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Real findings on a real repo
|
|
81
|
+
|
|
82
|
+
Scanned `VanshBhardwaj1945/cloud-resume-challenge-azure` — 13 findings across 2 workflow files:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
[CRITICAL] FS002 - Unpinned Action — Supply Chain Attack Vector
|
|
86
|
+
File: .github/workflows/backend.main.yaml
|
|
87
|
+
Action 'actions/checkout@v4' is not pinned to a commit hash
|
|
88
|
+
|
|
89
|
+
[HIGH] FS003 - Excessive Permissions — Overprivileged Workflow Token
|
|
90
|
+
File: .github/workflows/backend.main.yaml
|
|
91
|
+
Pipeline permissions set to 'None' — GitHub defaults apply
|
|
92
|
+
|
|
93
|
+
[HIGH] FS004 - Missing OIDC — Long-Lived Cloud Credential in Use
|
|
94
|
+
File: .github/workflows/backend.main.yaml
|
|
95
|
+
Cloud provider action present but no id-token: write permission
|
|
96
|
+
|
|
97
|
+
[LOW] FS006 - Missing Timeout — Job Runs Up to 6 Hours Unchecked
|
|
98
|
+
File: .github/workflows/backend.main.yaml
|
|
99
|
+
Job 'build-and-deploy' has no timeout — GitHub default is 6 hours
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Stack
|
|
105
|
+
|
|
106
|
+
| Layer | Tools |
|
|
107
|
+
|---|---|
|
|
108
|
+
| Language | Python 3.11 |
|
|
109
|
+
| GitHub Connection | PyGithub |
|
|
110
|
+
| YAML Parsing | PyYAML with custom line-tracking loader |
|
|
111
|
+
| Terminal Output | rich |
|
|
112
|
+
| HTML Reports | Jinja2 — interactive filtering, expandable findings, PDF export |
|
|
113
|
+
| AI Narratives | Anthropic Claude API with local caching |
|
|
114
|
+
| Linting | ruff, mypy, bandit |
|
|
115
|
+
| Packaging | hatch, pyproject.toml |
|
|
116
|
+
| Containerization | Docker |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Quick Start
|
|
121
|
+
|
|
122
|
+
Click the Codespaces button above to run FlowSec in your browser with zero setup. Or run locally:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
git clone https://github.com/VanshBhardwaj1945/FlowSec.git
|
|
126
|
+
cd FlowSec
|
|
127
|
+
python3 -m venv .venv
|
|
128
|
+
source .venv/bin/activate
|
|
129
|
+
pip install -e ".[dev]"
|
|
130
|
+
cp .env.example .env
|
|
131
|
+
# Add your GITHUB_TOKEN to .env
|
|
132
|
+
|
|
133
|
+
flowsec scan --repo owner/repo
|
|
134
|
+
flowsec scan --file .github/workflows/ci.yml
|
|
135
|
+
flowsec scan --gitlab .gitlab-ci.yml
|
|
136
|
+
flowsec scan --azure azure-pipelines.yml
|
|
137
|
+
flowsec scan --repo owner/repo --ai --output report.html
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Use as a Pipeline Gate
|
|
143
|
+
|
|
144
|
+
Add FlowSec to your own GitHub Actions workflow to automatically block PRs that introduce security misconfigurations:
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
name: FlowSec Security Scan
|
|
148
|
+
on: [push, pull_request]
|
|
149
|
+
jobs:
|
|
150
|
+
security:
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
steps:
|
|
153
|
+
- uses: actions/checkout@v3
|
|
154
|
+
- name: Install FlowSec
|
|
155
|
+
run: pip install flowsec
|
|
156
|
+
- name: Run FlowSec
|
|
157
|
+
run: flowsec scan --file .github/workflows/ --fail-on critical
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`--fail-on critical` exits with code 1 if any CRITICAL findings are found, failing the pipeline and blocking the PR. Supports `critical`, `high`, `medium`, and `low` thresholds.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Status
|
|
165
|
+
|
|
166
|
+
| Component | Status |
|
|
167
|
+
|---|---|
|
|
168
|
+
| Rule engine — BaseRule, Finding, Severity | Complete |
|
|
169
|
+
| YAML parser with line number tracking | Complete |
|
|
170
|
+
| 13 security rules FS001-FS013 | Complete |
|
|
171
|
+
| MITRE ATT&CK + OWASP CICD Top 10 mapping | Complete |
|
|
172
|
+
| Platform-aware rule engine | Complete |
|
|
173
|
+
| GitHub Actions scanner — API and local file | Complete |
|
|
174
|
+
| GitLab CI scanner | Complete |
|
|
175
|
+
| Azure DevOps scanner | Complete |
|
|
176
|
+
| CLI — --repo, --file, --gitlab, --azure, --ai, --output, --fail-on | Complete |
|
|
177
|
+
| Rich terminal output with risk score | Complete |
|
|
178
|
+
| HTML report with filtering, PDF export | Complete |
|
|
179
|
+
| AI attack narratives with local caching | Complete |
|
|
180
|
+
| Line number tracking | Complete |
|
|
181
|
+
| Pipeline gate flag --fail-on | Complete |
|
|
182
|
+
| GitHub Codespace config | Complete |
|
|
183
|
+
| PyPI publish | Pending |
|
|
184
|
+
| Web app — FastAPI + frontend | Pending |
|
|
185
|
+
| Web app — Azure Container Apps deployment | Pending |
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Roadmap
|
|
190
|
+
|
|
191
|
+
**Phase 1 — Core CLI**
|
|
192
|
+
PyPI publish so anyone can `pip install flowsec`.
|
|
193
|
+
|
|
194
|
+
**Phase 2 — Web App**
|
|
195
|
+
FastAPI backend, frontend for repo input and file upload, deployed to Azure Container Apps via GitHub Actions. Anyone can scan a pipeline from a browser without installing anything.
|
|
196
|
+
|
|
197
|
+
**Phase 3 — Expansion**
|
|
198
|
+
Jenkins support, AWS CodePipeline, 20+ rule library, rate limiting.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## About this project
|
|
203
|
+
|
|
204
|
+
Built as a security engineering portfolio project. The goal was to build an actual security tool — not run existing ones — and document every decision along the way.
|
|
205
|
+
|
|
206
|
+
**[Read the full documentation](docs/FULL_README.md)**
|
flowsec-0.1.0/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# FlowSec
|
|
2
|
+
|
|
3
|
+
> A Python security tool that scans CI/CD pipeline configurations for attack vectors across GitHub Actions, GitLab CI, and Azure DevOps. Every finding maps to a MITRE ATT&CK technique and OWASP CICD Top 10 category.
|
|
4
|
+
>
|
|
5
|
+
> The pipeline is the attack surface. FlowSec treats it that way.
|
|
6
|
+
|
|
7
|
+
**[Full documentation](docs/FULL_README.md)**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
[](https://codespaces.new/VanshBhardwaj1945/FlowSec)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What it catches
|
|
16
|
+
|
|
17
|
+
| ID | Rule | Severity | MITRE | OWASP |
|
|
18
|
+
|---|---|---|---|---|
|
|
19
|
+
| FS001 | Hardcoded Secret — Plaintext Credential in Workflow | CRITICAL | T1552.001 | CICD-SEC-6 |
|
|
20
|
+
| FS002 | Unpinned Action — Supply Chain Attack Vector | CRITICAL | T1195.001 | CICD-SEC-3 |
|
|
21
|
+
| FS003 | Excessive Permissions — Overprivileged Workflow Token | HIGH | T1078 | CICD-SEC-5 |
|
|
22
|
+
| FS004 | Missing OIDC — Long-Lived Cloud Credential in Use | HIGH | T1552.004 | CICD-SEC-6 |
|
|
23
|
+
| FS005 | Pull Request Target — Secrets Exposed to Fork Code | CRITICAL | T1611 | CICD-SEC-4 |
|
|
24
|
+
| FS006 | Missing Timeout — Job Runs Up to 6 Hours Unchecked | LOW | T1499 | CICD-SEC-10 |
|
|
25
|
+
| FS007 | Self-Hosted Runner — Persistent Environment Risk | HIGH | T1053 | CICD-SEC-7 |
|
|
26
|
+
| FS008 | Missing Artifact Signing — No Tamper Protection | MEDIUM | T1553 | CICD-SEC-8 |
|
|
27
|
+
| FS009 | Unpinned Dependency — Package Installed Without Version Lock | HIGH | T1195.002 | CICD-SEC-3 |
|
|
28
|
+
| FS010 | Secret in Run Command — Plaintext Credential in Shell Step | CRITICAL | T1552.001 | CICD-SEC-6 |
|
|
29
|
+
| FS011 | Missing Branch Protection — Direct Push to Default Branch Possible | HIGH | T1098 | CICD-SEC-1 |
|
|
30
|
+
| FS012 | Missing Environment Protection — Deploy Job Has No Approval Gate | HIGH | T1078 | CICD-SEC-5 |
|
|
31
|
+
| FS013 | Workflow Dispatch Injection — Unvalidated Input in Shell Command | CRITICAL | T1059 | CICD-SEC-9 |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Platforms supported
|
|
36
|
+
|
|
37
|
+
| Platform | How to scan |
|
|
38
|
+
|---|---|
|
|
39
|
+
| GitHub Actions | `flowsec scan --repo owner/repo` or `--file workflow.yml` |
|
|
40
|
+
| GitLab CI | `flowsec scan --gitlab .gitlab-ci.yml` |
|
|
41
|
+
| Azure DevOps | `flowsec scan --azure azure-pipelines.yml` |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Real findings on a real repo
|
|
46
|
+
|
|
47
|
+
Scanned `VanshBhardwaj1945/cloud-resume-challenge-azure` — 13 findings across 2 workflow files:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
[CRITICAL] FS002 - Unpinned Action — Supply Chain Attack Vector
|
|
51
|
+
File: .github/workflows/backend.main.yaml
|
|
52
|
+
Action 'actions/checkout@v4' is not pinned to a commit hash
|
|
53
|
+
|
|
54
|
+
[HIGH] FS003 - Excessive Permissions — Overprivileged Workflow Token
|
|
55
|
+
File: .github/workflows/backend.main.yaml
|
|
56
|
+
Pipeline permissions set to 'None' — GitHub defaults apply
|
|
57
|
+
|
|
58
|
+
[HIGH] FS004 - Missing OIDC — Long-Lived Cloud Credential in Use
|
|
59
|
+
File: .github/workflows/backend.main.yaml
|
|
60
|
+
Cloud provider action present but no id-token: write permission
|
|
61
|
+
|
|
62
|
+
[LOW] FS006 - Missing Timeout — Job Runs Up to 6 Hours Unchecked
|
|
63
|
+
File: .github/workflows/backend.main.yaml
|
|
64
|
+
Job 'build-and-deploy' has no timeout — GitHub default is 6 hours
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Stack
|
|
70
|
+
|
|
71
|
+
| Layer | Tools |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Language | Python 3.11 |
|
|
74
|
+
| GitHub Connection | PyGithub |
|
|
75
|
+
| YAML Parsing | PyYAML with custom line-tracking loader |
|
|
76
|
+
| Terminal Output | rich |
|
|
77
|
+
| HTML Reports | Jinja2 — interactive filtering, expandable findings, PDF export |
|
|
78
|
+
| AI Narratives | Anthropic Claude API with local caching |
|
|
79
|
+
| Linting | ruff, mypy, bandit |
|
|
80
|
+
| Packaging | hatch, pyproject.toml |
|
|
81
|
+
| Containerization | Docker |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Quick Start
|
|
86
|
+
|
|
87
|
+
Click the Codespaces button above to run FlowSec in your browser with zero setup. Or run locally:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
git clone https://github.com/VanshBhardwaj1945/FlowSec.git
|
|
91
|
+
cd FlowSec
|
|
92
|
+
python3 -m venv .venv
|
|
93
|
+
source .venv/bin/activate
|
|
94
|
+
pip install -e ".[dev]"
|
|
95
|
+
cp .env.example .env
|
|
96
|
+
# Add your GITHUB_TOKEN to .env
|
|
97
|
+
|
|
98
|
+
flowsec scan --repo owner/repo
|
|
99
|
+
flowsec scan --file .github/workflows/ci.yml
|
|
100
|
+
flowsec scan --gitlab .gitlab-ci.yml
|
|
101
|
+
flowsec scan --azure azure-pipelines.yml
|
|
102
|
+
flowsec scan --repo owner/repo --ai --output report.html
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Use as a Pipeline Gate
|
|
108
|
+
|
|
109
|
+
Add FlowSec to your own GitHub Actions workflow to automatically block PRs that introduce security misconfigurations:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
name: FlowSec Security Scan
|
|
113
|
+
on: [push, pull_request]
|
|
114
|
+
jobs:
|
|
115
|
+
security:
|
|
116
|
+
runs-on: ubuntu-latest
|
|
117
|
+
steps:
|
|
118
|
+
- uses: actions/checkout@v3
|
|
119
|
+
- name: Install FlowSec
|
|
120
|
+
run: pip install flowsec
|
|
121
|
+
- name: Run FlowSec
|
|
122
|
+
run: flowsec scan --file .github/workflows/ --fail-on critical
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`--fail-on critical` exits with code 1 if any CRITICAL findings are found, failing the pipeline and blocking the PR. Supports `critical`, `high`, `medium`, and `low` thresholds.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Status
|
|
130
|
+
|
|
131
|
+
| Component | Status |
|
|
132
|
+
|---|---|
|
|
133
|
+
| Rule engine — BaseRule, Finding, Severity | Complete |
|
|
134
|
+
| YAML parser with line number tracking | Complete |
|
|
135
|
+
| 13 security rules FS001-FS013 | Complete |
|
|
136
|
+
| MITRE ATT&CK + OWASP CICD Top 10 mapping | Complete |
|
|
137
|
+
| Platform-aware rule engine | Complete |
|
|
138
|
+
| GitHub Actions scanner — API and local file | Complete |
|
|
139
|
+
| GitLab CI scanner | Complete |
|
|
140
|
+
| Azure DevOps scanner | Complete |
|
|
141
|
+
| CLI — --repo, --file, --gitlab, --azure, --ai, --output, --fail-on | Complete |
|
|
142
|
+
| Rich terminal output with risk score | Complete |
|
|
143
|
+
| HTML report with filtering, PDF export | Complete |
|
|
144
|
+
| AI attack narratives with local caching | Complete |
|
|
145
|
+
| Line number tracking | Complete |
|
|
146
|
+
| Pipeline gate flag --fail-on | Complete |
|
|
147
|
+
| GitHub Codespace config | Complete |
|
|
148
|
+
| PyPI publish | Pending |
|
|
149
|
+
| Web app — FastAPI + frontend | Pending |
|
|
150
|
+
| Web app — Azure Container Apps deployment | Pending |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Roadmap
|
|
155
|
+
|
|
156
|
+
**Phase 1 — Core CLI**
|
|
157
|
+
PyPI publish so anyone can `pip install flowsec`.
|
|
158
|
+
|
|
159
|
+
**Phase 2 — Web App**
|
|
160
|
+
FastAPI backend, frontend for repo input and file upload, deployed to Azure Container Apps via GitHub Actions. Anyone can scan a pipeline from a browser without installing anything.
|
|
161
|
+
|
|
162
|
+
**Phase 3 — Expansion**
|
|
163
|
+
Jenkins support, AWS CodePipeline, 20+ rule library, rate limiting.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## About this project
|
|
168
|
+
|
|
169
|
+
Built as a security engineering portfolio project. The goal was to build an actual security tool — not run existing ones — and document every decision along the way.
|
|
170
|
+
|
|
171
|
+
**[Read the full documentation](docs/FULL_README.md)**
|