flowsec 0.5.2__tar.gz → 0.5.4__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.5.2 → flowsec-0.5.4}/AGENTS.md +71 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/PKG-INFO +82 -168
- flowsec-0.5.4/PYPI_README.md +161 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/README.md +18 -2
- {flowsec-0.5.2 → flowsec-0.5.4}/SECURITY.md +1 -1
- {flowsec-0.5.2 → flowsec-0.5.4}/docs/FULL_README.md +154 -82
- flowsec-0.5.4/homebrew-tap/Formula/flowsec.rb +207 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/pyproject.toml +2 -2
- {flowsec-0.5.2 → flowsec-0.5.4}/.devcontainer/devcontainer.json +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/.github/workflows/publish.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/.github/workflows/security.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/.gitignore +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/LICENSE +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/Makefile +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/docs/screenshots/flowsec-logo.png +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/__init__.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/ai_narrative.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/cli.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/config.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/parser.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/report.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/__init__.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/artifact_signing.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/base.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/broad_artifact_upload.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/container_runs_as_root.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/continue_on_error_security.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/dependency_pinning.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/deploy_all_branches.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/env_vars_in_logs.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/excessive_permissions.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/github_context_injection.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/hardcoded_secrets.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/insecure_curl.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/missing_env_protection.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/missing_oidc.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/missing_timeout.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/mutable_container_image.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/persist_credentials.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/privileged_docker.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/pull_request_target.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/secret_as_cli_arg.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/secrets_in_build_args.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/secrets_in_run.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/self_hosted_runner.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/unpinned_actions.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/unverified_install_script.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/workflow_dispatch_injection.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/rules/workflow_run_trigger.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/scanner.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/scoring.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/src/pipelineguard/templates/report.html +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/__init__.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/azure_all_vulns.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/github_all_vulns.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/gitlab_all_vulns.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/sample_azure_vulnerable.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/sample_gitlab_vulnerable.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/sample_workflow_clean.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/fixtures/sample_workflow_vulnerable.yml +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/test_azure_rules.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/test_github_rules.py +0 -0
- {flowsec-0.5.2 → flowsec-0.5.4}/tests/test_gitlab_rules.py +0 -0
|
@@ -328,6 +328,76 @@ FS003 (Excessive Permissions) fires when a GitHub workflow has `permissions: wri
|
|
|
328
328
|
|
|
329
329
|
---
|
|
330
330
|
|
|
331
|
+
## Homebrew Tap
|
|
332
|
+
|
|
333
|
+
FlowSec is distributed via a dedicated Homebrew tap in addition to PyPI.
|
|
334
|
+
|
|
335
|
+
### Repositories
|
|
336
|
+
|
|
337
|
+
| Repo | URL | Purpose |
|
|
338
|
+
|---|---|---|
|
|
339
|
+
| Main codebase | `github.com/VanshBhardwaj1945/FlowSec` | Source code, PyPI publishing |
|
|
340
|
+
| Homebrew tap | `github.com/VanshBhardwaj1945/homebrew-flowsec` | Homebrew formula only |
|
|
341
|
+
|
|
342
|
+
The tap repo holds a single file: `Formula/flowsec.rb`. Homebrew requires the repo to be named `homebrew-<tapname>` — this is mandatory, not a convention.
|
|
343
|
+
|
|
344
|
+
### Install commands (for users)
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
# One-liner (taps and installs in one step)
|
|
348
|
+
brew install VanshBhardwaj1945/flowsec/flowsec
|
|
349
|
+
|
|
350
|
+
# Or tap first, then install
|
|
351
|
+
brew tap VanshBhardwaj1945/flowsec
|
|
352
|
+
brew install flowsec
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Local tap path (for development)
|
|
356
|
+
|
|
357
|
+
When the tap is registered locally, brew stores it at:
|
|
358
|
+
```
|
|
359
|
+
/usr/local/Homebrew/Library/Taps/vanshbhardwaj1945/homebrew-flowsec/Formula/flowsec.rb
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
A canonical copy is also kept in this repo at `homebrew-tap/Formula/flowsec.rb`. When updating the formula, edit the canonical copy here first, then push it to the tap repo.
|
|
363
|
+
|
|
364
|
+
### Formula structure
|
|
365
|
+
|
|
366
|
+
The formula (`flowsec.rb`) uses `Language::Python::Virtualenv` — Homebrew's standard approach for Python CLI tools. It installs flowsec and all 36 transitive runtime dependencies into an isolated virtualenv in the Cellar. The binary at `$(brew --prefix)/bin/flowsec` is a shim into that virtualenv.
|
|
367
|
+
|
|
368
|
+
Build-time dependencies: `rust` (required for `pydantic-core` and `jiter`, which are Rust extensions).
|
|
369
|
+
Runtime dependencies: `libsodium` (for PyNaCl), `libyaml` (for PyYAML), `python@3.11`.
|
|
370
|
+
|
|
371
|
+
### Updating the formula for a new FlowSec release
|
|
372
|
+
|
|
373
|
+
When a new version is published to PyPI, the formula must be updated:
|
|
374
|
+
|
|
375
|
+
1. Get the new tarball URL and SHA256 from `https://pypi.org/pypi/flowsec/X.Y.Z/json` (look in `urls` for `packagetype == "sdist"`)
|
|
376
|
+
2. Update `url` and `sha256` at the top of `homebrew-tap/Formula/flowsec.rb`
|
|
377
|
+
3. Check if any dependencies changed versions — re-run a pip dry-run to confirm:
|
|
378
|
+
```bash
|
|
379
|
+
/usr/local/opt/python@3.11/libexec/bin/python -m pip install --dry-run --ignore-installed --report=/tmp/report.json flowsec==X.Y.Z
|
|
380
|
+
python3 -c "import json; [print(p['metadata']['name'], p['metadata']['version']) for p in json.load(open('/tmp/report.json'))['install']]"
|
|
381
|
+
```
|
|
382
|
+
4. If dependency versions changed, update the corresponding `resource` blocks (url + sha256). For pure-Python packages use the `-py3-none-any.whl` wheel URL. For compiled packages (cffi, cryptography, jiter, markupsafe, pydantic-core, pynacl, pyyaml, charset-normalizer) use the `.tar.gz` sdist URL.
|
|
383
|
+
5. Commit the updated formula to both `homebrew-tap/Formula/flowsec.rb` in this repo **and** push it to `github.com/VanshBhardwaj1945/homebrew-flowsec`
|
|
384
|
+
6. Test locally: `brew upgrade VanshBhardwaj1945/flowsec/flowsec`
|
|
385
|
+
|
|
386
|
+
### Auditing and testing the formula
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
# Check for style/correctness issues
|
|
390
|
+
brew audit --new VanshBhardwaj1945/flowsec/flowsec
|
|
391
|
+
|
|
392
|
+
# Run the formula's test block
|
|
393
|
+
brew test VanshBhardwaj1945/flowsec/flowsec
|
|
394
|
+
|
|
395
|
+
# Full install from source
|
|
396
|
+
brew install --build-from-source VanshBhardwaj1945/flowsec/flowsec
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
331
401
|
## Publishing to PyPI
|
|
332
402
|
|
|
333
403
|
The project uses PyPI trusted publishing (OIDC) — no API token needed. The workflow in `.github/workflows/publish.yml` handles everything automatically when a `v*` tag is pushed. PyPI generates Sigstore attestations automatically for OIDC-published packages.
|
|
@@ -359,3 +429,4 @@ The README.md is used as the PyPI long description. Hatchling detects `text/mark
|
|
|
359
429
|
| `tests/fixtures/` | The ground truth for what each platform's YAML looks like and what should be detected. |
|
|
360
430
|
| `.github/workflows/publish.yml` | PyPI release pipeline. Triggered by `v*` tags. |
|
|
361
431
|
| `.github/workflows/security.yml` | Security checks on every push/PR to main. |
|
|
432
|
+
| `homebrew-tap/Formula/flowsec.rb` | Canonical copy of the Homebrew formula. Push changes here and to `github.com/VanshBhardwaj1945/homebrew-flowsec`. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowsec
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: CI/CD pipeline security analyzer — scans GitHub Actions, GitLab CI, and Azure DevOps configs for attack vectors
|
|
5
5
|
Author-email: Vansh Bhardwaj <Scorpio.vansh@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -33,24 +33,74 @@ Requires-Dist: responses>=0.25.3; extra == 'dev'
|
|
|
33
33
|
Requires-Dist: ruff>=0.4.4; extra == 'dev'
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
<img src="docs/screenshots/flowsec-logo.png" alt="FlowSec" width="520" />
|
|
38
|
-
</p>
|
|
36
|
+
# FlowSec
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
<a href="https://codespaces.new/VanshBhardwaj1945/FlowSec"><img src="https://github.com/codespaces/badge.svg" alt="Open in GitHub Codespaces" /></a>
|
|
42
|
-
<a href="https://badge.fury.io/py/flowsec"><img src="https://badge.fury.io/py/flowsec.svg" alt="PyPI version" /></a>
|
|
43
|
-
</p>
|
|
38
|
+
A Python command-line 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 an OWASP CICD Top 10 category.
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
>
|
|
47
|
-
> The pipeline is the attack surface. FlowSec treats it that way.
|
|
40
|
+
The pipeline is the attack surface. FlowSec treats it that way.
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
**Homebrew (macOS):**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
brew install VanshBhardwaj1945/flowsec/flowsec
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**PyPI:**
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install flowsec
|
|
56
|
+
```
|
|
50
57
|
|
|
51
58
|
---
|
|
52
59
|
|
|
53
|
-
##
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Scan a GitHub Actions repo
|
|
64
|
+
export GITHUB_TOKEN=your_token
|
|
65
|
+
flowsec scan --github --repo owner/repo
|
|
66
|
+
|
|
67
|
+
# Scan a local GitHub Actions workflow file
|
|
68
|
+
flowsec scan --github --file .github/workflows/ci.yml
|
|
69
|
+
|
|
70
|
+
# Scan a GitLab CI file
|
|
71
|
+
flowsec scan --gitlab --file .gitlab-ci.yml
|
|
72
|
+
|
|
73
|
+
# Scan an Azure DevOps pipeline file
|
|
74
|
+
flowsec scan --azure --file azure-pipelines.yml
|
|
75
|
+
|
|
76
|
+
# Generate an HTML report
|
|
77
|
+
flowsec scan --github --repo owner/repo --output report.html
|
|
78
|
+
|
|
79
|
+
# Generate AI attack narratives (requires ANTHROPIC_API_KEY)
|
|
80
|
+
flowsec scan --github --repo owner/repo --ai
|
|
81
|
+
|
|
82
|
+
# Fail pipeline if findings at or above threshold
|
|
83
|
+
flowsec scan --github --repo owner/repo --fail-on critical
|
|
84
|
+
|
|
85
|
+
# Ignore specific rules
|
|
86
|
+
flowsec scan --github --repo owner/repo --ignore FS006 --ignore FS011
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Platforms and Tokens
|
|
92
|
+
|
|
93
|
+
| Platform | File scan | Remote scan | Token required |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| GitHub Actions | `--github --file` | `--github --repo owner/repo` | `GITHUB_TOKEN` (remote only) |
|
|
96
|
+
| GitLab CI | `--gitlab --file` | `--gitlab --repo namespace/project` | `GITLAB_TOKEN` (remote only) |
|
|
97
|
+
| Azure DevOps | `--azure --file` | `--azure --repo org/project` | `AZURE_DEVOPS_TOKEN` (always — Azure requires auth even for public projects) |
|
|
98
|
+
|
|
99
|
+
Set tokens in a `.env` file in your working directory or as environment variables. FlowSec loads `.env` automatically.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 26 Security Rules
|
|
54
104
|
|
|
55
105
|
| ID | Rule | Severity | MITRE | OWASP |
|
|
56
106
|
|---|---|---|---|---|
|
|
@@ -83,127 +133,20 @@ Description-Content-Type: text/markdown
|
|
|
83
133
|
|
|
84
134
|
---
|
|
85
135
|
|
|
86
|
-
##
|
|
87
|
-
|
|
88
|
-
| Platform | File scan | Remote repo scan |
|
|
89
|
-
|---|---|---|
|
|
90
|
-
| GitHub Actions | `flowsec scan --github --file workflow.yml` | `flowsec scan --github --repo owner/repo` |
|
|
91
|
-
| GitLab CI | `flowsec scan --gitlab --file .gitlab-ci.yml` | `flowsec scan --gitlab --repo namespace/project` |
|
|
92
|
-
| Azure DevOps | `flowsec scan --azure --file azure-pipelines.yml` | `flowsec scan --azure --repo org/project` |
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Real findings on a real repo
|
|
97
|
-
|
|
98
|
-
Scanned `VanshBhardwaj1945/cloud-resume-challenge-azure` — 13 findings across 2 workflow files:
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
[CRITICAL] FS002 - Unpinned Action — Supply Chain Attack Vector
|
|
102
|
-
File: .github/workflows/backend.main.yaml
|
|
103
|
-
Action 'actions/checkout@v4' is not pinned to a commit hash
|
|
104
|
-
|
|
105
|
-
[HIGH] FS003 - Excessive Permissions — Overprivileged Workflow Token
|
|
106
|
-
File: .github/workflows/backend.main.yaml
|
|
107
|
-
Pipeline permissions set to 'None' — GitHub defaults apply
|
|
108
|
-
|
|
109
|
-
[HIGH] FS004 - Missing OIDC — Long-Lived Cloud Credential in Use
|
|
110
|
-
File: .github/workflows/backend.main.yaml
|
|
111
|
-
Cloud provider action present but no id-token: write permission
|
|
112
|
-
|
|
113
|
-
[LOW] FS006 - Missing Timeout — Job Runs Up to 6 Hours Unchecked
|
|
114
|
-
File: .github/workflows/backend.main.yaml
|
|
115
|
-
Job 'build-and-deploy' has no timeout — GitHub default is 6 hours
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Stack
|
|
121
|
-
|
|
122
|
-
| Layer | Tools |
|
|
123
|
-
|---|---|
|
|
124
|
-
| Language | Python 3.11 |
|
|
125
|
-
| GitHub Connection | PyGithub |
|
|
126
|
-
| YAML Parsing | PyYAML with custom line-tracking loader |
|
|
127
|
-
| Terminal Output | rich |
|
|
128
|
-
| HTML Reports | Jinja2 — interactive filtering, expandable findings, PDF export |
|
|
129
|
-
| AI Narratives | Anthropic Claude API with local caching |
|
|
130
|
-
| Linting | ruff, mypy, bandit |
|
|
131
|
-
| Packaging | hatch, pyproject.toml |
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## Quick Start
|
|
136
|
-
|
|
137
|
-
Click the Codespaces button above to run FlowSec in your browser with zero setup. Or install from PyPI:
|
|
136
|
+
## Risk Score
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
pip install flowsec
|
|
141
|
-
export GITHUB_TOKEN=your_token_here
|
|
142
|
-
flowsec scan --github --repo owner/repo
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Or run from source:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
git clone https://github.com/VanshBhardwaj1945/FlowSec.git
|
|
149
|
-
cd FlowSec
|
|
150
|
-
python3 -m venv .venv
|
|
151
|
-
source .venv/bin/activate
|
|
152
|
-
pip install -e ".[dev]"
|
|
153
|
-
cp .env.example .env
|
|
154
|
-
# Add your GITHUB_TOKEN to .env
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## CLI
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
# Scan a GitHub Actions repo (remote)
|
|
163
|
-
flowsec scan --github --repo owner/repo
|
|
164
|
-
|
|
165
|
-
# Scan a local GitHub Actions file
|
|
166
|
-
flowsec scan --github --file .github/workflows/ci.yml
|
|
167
|
-
|
|
168
|
-
# Scan a GitLab CI file (local)
|
|
169
|
-
flowsec scan --gitlab --file .gitlab-ci.yml
|
|
170
|
-
|
|
171
|
-
# Scan a GitLab CI repo (remote — requires GITLAB_TOKEN)
|
|
172
|
-
flowsec scan --gitlab --repo namespace/project
|
|
173
|
-
|
|
174
|
-
# Scan an Azure DevOps file (local)
|
|
175
|
-
flowsec scan --azure --file azure-pipelines.yml
|
|
176
|
-
|
|
177
|
-
# Scan an Azure DevOps repo (remote — requires AZURE_DEVOPS_TOKEN)
|
|
178
|
-
flowsec scan --azure --repo org/project
|
|
179
|
-
|
|
180
|
-
# Generate an HTML report
|
|
181
|
-
flowsec scan --github --repo owner/repo --output report.html
|
|
182
|
-
|
|
183
|
-
# Generate AI attack narratives (requires ANTHROPIC_API_KEY)
|
|
184
|
-
flowsec scan --github --repo owner/repo --ai
|
|
185
|
-
|
|
186
|
-
# Ignore specific rules
|
|
187
|
-
flowsec scan --github --repo owner/repo --ignore FS006 --ignore FS011
|
|
188
|
-
|
|
189
|
-
# Fail pipeline if findings at or above threshold
|
|
190
|
-
flowsec scan --github --repo owner/repo --fail-on critical
|
|
191
|
-
|
|
192
|
-
# Everything at once
|
|
193
|
-
flowsec scan --github --repo owner/repo --ai --output report.html --fail-on high
|
|
194
|
-
```
|
|
138
|
+
Every scan produces a 0-100 risk score using severity-weighted diminishing returns and exponential normalization. A single critical finding scores ~28. A heavily vulnerable pipeline scores ~90-97. The score cannot exceed 100.
|
|
195
139
|
|
|
196
140
|
---
|
|
197
141
|
|
|
198
142
|
## Rule Suppression
|
|
199
143
|
|
|
200
|
-
Suppress specific rules inline with `--ignore`:
|
|
201
|
-
|
|
202
144
|
```bash
|
|
145
|
+
# CLI flag
|
|
203
146
|
flowsec scan --github --repo owner/repo --ignore FS006 --ignore FS011
|
|
204
|
-
```
|
|
205
147
|
|
|
206
|
-
|
|
148
|
+
# .flowsec.yml in your repo root
|
|
149
|
+
```
|
|
207
150
|
|
|
208
151
|
```yaml
|
|
209
152
|
ignore:
|
|
@@ -217,8 +160,6 @@ ignore:
|
|
|
217
160
|
|
|
218
161
|
## Use as a Pipeline Gate
|
|
219
162
|
|
|
220
|
-
Add FlowSec to your own GitHub Actions workflow to automatically block PRs that introduce security misconfigurations:
|
|
221
|
-
|
|
222
163
|
```yaml
|
|
223
164
|
name: FlowSec Security Scan
|
|
224
165
|
on: [push, pull_request]
|
|
@@ -227,56 +168,29 @@ jobs:
|
|
|
227
168
|
runs-on: ubuntu-latest
|
|
228
169
|
steps:
|
|
229
170
|
- uses: actions/checkout@v4
|
|
230
|
-
-
|
|
231
|
-
|
|
232
|
-
- name: Run FlowSec
|
|
233
|
-
run: flowsec scan --github --file .github/workflows/ci.yml --fail-on critical
|
|
171
|
+
- run: pip install flowsec
|
|
172
|
+
- run: flowsec scan --github --file .github/workflows/ci.yml --fail-on critical
|
|
234
173
|
```
|
|
235
174
|
|
|
236
|
-
`--fail-on` supports `critical`, `high`, `medium`, and `low` thresholds.
|
|
237
|
-
|
|
238
175
|
---
|
|
239
176
|
|
|
240
|
-
##
|
|
241
|
-
|
|
242
|
-
| Component | Status |
|
|
243
|
-
|---|---|
|
|
244
|
-
| Rule engine — BaseRule, Finding, Severity | Complete |
|
|
245
|
-
| YAML parser with line number tracking | Complete |
|
|
246
|
-
| 26 security rules FS001-FS026 | Complete |
|
|
247
|
-
| MITRE ATT&CK + OWASP CICD Top 10 mapping | Complete |
|
|
248
|
-
| Platform-aware rule engine (GitHub/GitLab/Azure) | Complete |
|
|
249
|
-
| GitHub Actions scanner — remote repo and local file | Complete |
|
|
250
|
-
| GitLab CI scanner — remote repo and local file | Complete |
|
|
251
|
-
| Azure DevOps scanner — remote repo and local file | Complete |
|
|
252
|
-
| CLI — `--github/--gitlab/--azure` + `--file/--repo` | Complete |
|
|
253
|
-
| Rich terminal output with risk score (0-100) | Complete |
|
|
254
|
-
| HTML report with filtering, PDF export | Complete |
|
|
255
|
-
| AI attack narratives with local caching | Complete |
|
|
256
|
-
| Line number tracking | Complete |
|
|
257
|
-
| Pipeline gate `--fail-on` | Complete |
|
|
258
|
-
| Rule suppression `--ignore` and `.flowsec.yml` | Complete |
|
|
259
|
-
| GitHub Codespace config | Complete |
|
|
260
|
-
| PyPI publish with OIDC trusted publishing | Complete |
|
|
261
|
-
| CI security workflow (gitleaks, bandit, pip-audit, self-scan) | Complete |
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## Roadmap
|
|
266
|
-
|
|
267
|
-
**Phase 2 — Expansion**
|
|
268
|
-
Jenkins support, AWS CodePipeline, 20+ rule library, Homebrew formula.
|
|
177
|
+
## Security
|
|
269
178
|
|
|
270
|
-
|
|
179
|
+
FlowSec is built to the same standard it enforces:
|
|
271
180
|
|
|
272
|
-
|
|
181
|
+
- All GitHub Actions pinned to commit SHAs with least-privilege permissions
|
|
182
|
+
- PyPI publishing via OIDC trusted publishing — no long-lived tokens
|
|
183
|
+
- Own CI runs gitleaks, bandit, pip-audit, and FlowSec self-scan on every push
|
|
184
|
+
- Branch protection on main — force push blocked, 4 required status checks
|
|
185
|
+
- YAML parsed with a SafeLoader subclass — no code execution risk
|
|
186
|
+
- HTML reports use Jinja2 autoescape — XSS from finding content prevented
|
|
273
187
|
|
|
274
|
-
|
|
188
|
+
Report vulnerabilities via GitHub Security Advisories or email Scorpio.vansh@gmail.com.
|
|
275
189
|
|
|
276
190
|
---
|
|
277
191
|
|
|
278
|
-
##
|
|
192
|
+
## License
|
|
279
193
|
|
|
280
|
-
|
|
194
|
+
MIT — see LICENSE on GitHub.
|
|
281
195
|
|
|
282
|
-
**
|
|
196
|
+
**Source:** https://github.com/VanshBhardwaj1945/FlowSec
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# FlowSec
|
|
2
|
+
|
|
3
|
+
A Python command-line 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 an OWASP CICD Top 10 category.
|
|
4
|
+
|
|
5
|
+
The pipeline is the attack surface. FlowSec treats it that way.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
**Homebrew (macOS):**
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
brew install VanshBhardwaj1945/flowsec/flowsec
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**PyPI:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install flowsec
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Scan a GitHub Actions repo
|
|
29
|
+
export GITHUB_TOKEN=your_token
|
|
30
|
+
flowsec scan --github --repo owner/repo
|
|
31
|
+
|
|
32
|
+
# Scan a local GitHub Actions workflow file
|
|
33
|
+
flowsec scan --github --file .github/workflows/ci.yml
|
|
34
|
+
|
|
35
|
+
# Scan a GitLab CI file
|
|
36
|
+
flowsec scan --gitlab --file .gitlab-ci.yml
|
|
37
|
+
|
|
38
|
+
# Scan an Azure DevOps pipeline file
|
|
39
|
+
flowsec scan --azure --file azure-pipelines.yml
|
|
40
|
+
|
|
41
|
+
# Generate an HTML report
|
|
42
|
+
flowsec scan --github --repo owner/repo --output report.html
|
|
43
|
+
|
|
44
|
+
# Generate AI attack narratives (requires ANTHROPIC_API_KEY)
|
|
45
|
+
flowsec scan --github --repo owner/repo --ai
|
|
46
|
+
|
|
47
|
+
# Fail pipeline if findings at or above threshold
|
|
48
|
+
flowsec scan --github --repo owner/repo --fail-on critical
|
|
49
|
+
|
|
50
|
+
# Ignore specific rules
|
|
51
|
+
flowsec scan --github --repo owner/repo --ignore FS006 --ignore FS011
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Platforms and Tokens
|
|
57
|
+
|
|
58
|
+
| Platform | File scan | Remote scan | Token required |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| GitHub Actions | `--github --file` | `--github --repo owner/repo` | `GITHUB_TOKEN` (remote only) |
|
|
61
|
+
| GitLab CI | `--gitlab --file` | `--gitlab --repo namespace/project` | `GITLAB_TOKEN` (remote only) |
|
|
62
|
+
| Azure DevOps | `--azure --file` | `--azure --repo org/project` | `AZURE_DEVOPS_TOKEN` (always — Azure requires auth even for public projects) |
|
|
63
|
+
|
|
64
|
+
Set tokens in a `.env` file in your working directory or as environment variables. FlowSec loads `.env` automatically.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 26 Security Rules
|
|
69
|
+
|
|
70
|
+
| ID | Rule | Severity | MITRE | OWASP |
|
|
71
|
+
|---|---|---|---|---|
|
|
72
|
+
| FS001 | Hardcoded Secret — Plaintext Credential in Workflow | CRITICAL | T1552.001 | CICD-SEC-6 |
|
|
73
|
+
| FS002 | Unpinned Action — Supply Chain Attack Vector | CRITICAL | T1195.001 | CICD-SEC-3 |
|
|
74
|
+
| FS003 | Excessive Permissions — Overprivileged Workflow Token | HIGH | T1078 | CICD-SEC-5 |
|
|
75
|
+
| FS004 | Missing OIDC — Long-Lived Cloud Credential in Use | HIGH | T1552.004 | CICD-SEC-6 |
|
|
76
|
+
| FS005 | Pull Request Target — Secrets Exposed to Fork Code | CRITICAL | T1611 | CICD-SEC-4 |
|
|
77
|
+
| FS006 | Missing Timeout — Job Runs Up to 6 Hours Unchecked | LOW | T1499 | CICD-SEC-10 |
|
|
78
|
+
| FS007 | Self-Hosted Runner — Persistent Environment Risk | HIGH | T1053 | CICD-SEC-7 |
|
|
79
|
+
| FS008 | Missing Artifact Signing — No Tamper Protection | MEDIUM | T1553 | CICD-SEC-8 |
|
|
80
|
+
| FS009 | Unpinned Dependency — Package Installed Without Version Lock | HIGH | T1195.002 | CICD-SEC-3 |
|
|
81
|
+
| FS010 | Secret in Run Command — Plaintext Credential in Shell Step | CRITICAL | T1552.001 | CICD-SEC-6 |
|
|
82
|
+
| FS011 | GitHub Context Injection — Untrusted Event Data in Run Step | CRITICAL | T1059.004 | CICD-SEC-4 |
|
|
83
|
+
| FS012 | Missing Environment Protection — Deploy Job Has No Approval Gate | HIGH | T1078 | CICD-SEC-5 |
|
|
84
|
+
| FS013 | Workflow Dispatch Injection — Unvalidated Input in Shell Command | CRITICAL | T1059 | CICD-SEC-9 |
|
|
85
|
+
| FS014 | Mutable Container Image — Unpinned Image Tag in Pipeline | MEDIUM | T1195.001 | CICD-SEC-3 |
|
|
86
|
+
| FS015 | Persist Credentials — GitHub Token Remains in Git Config After Checkout | MEDIUM | T1552.001 | CICD-SEC-6 |
|
|
87
|
+
| FS016 | workflow_run Trigger — Privileged Execution from Untrusted Workflow | HIGH | T1059 | CICD-SEC-1 |
|
|
88
|
+
| FS017 | Security Scan Silenced — Failures Suppressed with continue-on-error | MEDIUM | T1562.001 | CICD-SEC-7 |
|
|
89
|
+
| FS018 | Secret as CLI Argument — Credential Exposed in Process List | HIGH | T1552 | CICD-SEC-6 |
|
|
90
|
+
| FS019 | Unverified Install Script — Remote Code Fetched and Executed Directly | HIGH | T1195.002 | CICD-SEC-3 |
|
|
91
|
+
| FS020 | Container Running as Root — Elevated Privilege in Pipeline | HIGH | T1611 | CICD-SEC-7 |
|
|
92
|
+
| FS021 | Secret in Docker Build Argument — Credential Stored in Image History | HIGH | T1552.001 | CICD-SEC-6 |
|
|
93
|
+
| FS022 | Broad Artifact Upload — Entire Workspace Exposed as Artifact | MEDIUM | T1560 | CICD-SEC-9 |
|
|
94
|
+
| FS023 | Insecure curl — SSL Verification Disabled in Pipeline | HIGH | T1071 | CICD-SEC-3 |
|
|
95
|
+
| FS024 | Privileged Docker Container — Full Host Access Granted in Pipeline | CRITICAL | T1611 | CICD-SEC-7 |
|
|
96
|
+
| FS025 | Environment Variables Printed to Logs — Secrets Exposed in Pipeline Output | MEDIUM | T1552.001 | CICD-SEC-6 |
|
|
97
|
+
| FS026 | Unguarded Deploy — Deployment Job Runs on Untrusted Branches | HIGH | T1078 | CICD-SEC-1 |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Risk Score
|
|
102
|
+
|
|
103
|
+
Every scan produces a 0-100 risk score using severity-weighted diminishing returns and exponential normalization. A single critical finding scores ~28. A heavily vulnerable pipeline scores ~90-97. The score cannot exceed 100.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Rule Suppression
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# CLI flag
|
|
111
|
+
flowsec scan --github --repo owner/repo --ignore FS006 --ignore FS011
|
|
112
|
+
|
|
113
|
+
# .flowsec.yml in your repo root
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
ignore:
|
|
118
|
+
- rule_id: FS006
|
|
119
|
+
reason: "We use external timeout management"
|
|
120
|
+
- rule_id: FS011
|
|
121
|
+
reason: "Branch protection managed at org level"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Use as a Pipeline Gate
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
name: FlowSec Security Scan
|
|
130
|
+
on: [push, pull_request]
|
|
131
|
+
jobs:
|
|
132
|
+
security:
|
|
133
|
+
runs-on: ubuntu-latest
|
|
134
|
+
steps:
|
|
135
|
+
- uses: actions/checkout@v4
|
|
136
|
+
- run: pip install flowsec
|
|
137
|
+
- run: flowsec scan --github --file .github/workflows/ci.yml --fail-on critical
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Security
|
|
143
|
+
|
|
144
|
+
FlowSec is built to the same standard it enforces:
|
|
145
|
+
|
|
146
|
+
- All GitHub Actions pinned to commit SHAs with least-privilege permissions
|
|
147
|
+
- PyPI publishing via OIDC trusted publishing — no long-lived tokens
|
|
148
|
+
- Own CI runs gitleaks, bandit, pip-audit, and FlowSec self-scan on every push
|
|
149
|
+
- Branch protection on main — force push blocked, 4 required status checks
|
|
150
|
+
- YAML parsed with a SafeLoader subclass — no code execution risk
|
|
151
|
+
- HTML reports use Jinja2 autoescape — XSS from finding content prevented
|
|
152
|
+
|
|
153
|
+
Report vulnerabilities via GitHub Security Advisories or email Scorpio.vansh@gmail.com.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT — see LICENSE on GitHub.
|
|
160
|
+
|
|
161
|
+
**Source:** https://github.com/VanshBhardwaj1945/FlowSec
|
|
@@ -99,7 +99,22 @@ Scanned `VanshBhardwaj1945/cloud-resume-challenge-azure` — 13 findings across
|
|
|
99
99
|
|
|
100
100
|
## Quick Start
|
|
101
101
|
|
|
102
|
-
Click the Codespaces button above to run FlowSec in your browser with zero setup.
|
|
102
|
+
Click the Codespaces button above to run FlowSec in your browser with zero setup.
|
|
103
|
+
|
|
104
|
+
**Homebrew (macOS):**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
brew install VanshBhardwaj1945/flowsec/flowsec
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Or tap once then install:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
brew tap VanshBhardwaj1945/flowsec
|
|
114
|
+
brew install flowsec
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**PyPI:**
|
|
103
118
|
|
|
104
119
|
```bash
|
|
105
120
|
pip install flowsec
|
|
@@ -223,6 +238,7 @@ jobs:
|
|
|
223
238
|
| Rule suppression `--ignore` and `.flowsec.yml` | Complete |
|
|
224
239
|
| GitHub Codespace config | Complete |
|
|
225
240
|
| PyPI publish with OIDC trusted publishing | Complete |
|
|
241
|
+
| Homebrew tap (`brew install VanshBhardwaj1945/flowsec/flowsec`) | Complete |
|
|
226
242
|
| CI security workflow (gitleaks, bandit, pip-audit, self-scan) | Complete |
|
|
227
243
|
|
|
228
244
|
---
|
|
@@ -230,7 +246,7 @@ jobs:
|
|
|
230
246
|
## Roadmap
|
|
231
247
|
|
|
232
248
|
**Phase 2 — Expansion**
|
|
233
|
-
Jenkins support, AWS CodePipeline, 20+ rule library
|
|
249
|
+
Jenkins support, AWS CodePipeline, 20+ rule library.
|
|
234
250
|
|
|
235
251
|
---
|
|
236
252
|
|
|
@@ -18,7 +18,7 @@ Include:
|
|
|
18
18
|
- Steps to reproduce or a proof-of-concept
|
|
19
19
|
- Any suggested fix (optional)
|
|
20
20
|
|
|
21
|
-
You will receive a response within **
|
|
21
|
+
You will receive a response within **144 hours** and a fix or mitigation within **14 days** for confirmed issues.
|
|
22
22
|
|
|
23
23
|
## Scope
|
|
24
24
|
|