Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CODEOWNERS
#
# Each line is a pattern followed by one or more GitHub usernames / teams.
# The last matching pattern takes precedence.
# Docs: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners

# ── Default owner (catches everything not matched below) ──────────
* @alfacode-team

# ── Core source ───────────────────────────────────────────────────
/src/ @alfacode-team
/src/Components/ @alfacode-team
/src/Depends/ @alfacode-team

# ── Tests ─────────────────────────────────────────────────────────
/tests/ @alfacode-team

# ── Examples / docs ───────────────────────────────────────────────
/examples/ @alfacode-team
/docs/ @alfacode-team
README.md @alfacode-team
CHANGELOG.md @alfacode-team

# ── CI / release infrastructure ───────────────────────────────────
/.github/ @alfacode-team
/Makefile @alfacode-team
phpunit.xml.dist @alfacode-team
phpstan.neon @alfacode-team
.php-cs-fixer.php @alfacode-team
rector.php @alfacode-team

# ── Security-sensitive files ──────────────────────────────────────
SECURITY.md @alfacode-team
composer.json @alfacode-team
composer.lock @alfacode-team
43 changes: 43 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
version: 2

updates:
# ── Composer (PHP) ────────────────────────────────────────────────
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "UTC"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "php"
commit-message:
prefix: "chore(deps)"
# Keep dev-only bumps out of the release changelog noise
groups:
dev-dependencies:
dependency-type: "development"
update-types:
- "minor"
- "patch"
ignore:
# symfony/console is a dev dep; only auto-update patch/minor
- dependency-name: "symfony/console"
update-types: ["version-update:semver-major"]

# ── GitHub Actions ────────────────────────────────────────────────
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "UTC"
open-pull-requests-limit: 3
labels:
- "dependencies"
- "ci"
commit-message:
prefix: "chore(ci)"
81 changes: 81 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
.PHONY: help install test test-unit test-integration coverage stan cs-check cs-fix \
refactor mutation demo clean check check-full

# ── Colours ───────────────────────────────────────────────────────────────────
BOLD := \033[1m
CYAN := \033[36m
GREEN := \033[32m
RESET := \033[0m

# ── Default target: print help ────────────────────────────────────────────────
help:
@printf "\n$(BOLD)php-io-cli — Development Makefile$(RESET)\n\n"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make install" "Install Composer dependencies"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make test" "Run full test suite (Unit + Integration)"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make test-unit" "Run Unit tests only"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make test-integration" "Run Integration tests only"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make coverage" "Generate HTML coverage report"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make stan" "PHPStan static analysis (level 8)"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make cs-check" "Check code style (dry-run)"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make cs-fix" "Apply code-style fixes"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make refactor" "Run Rector automated upgrades"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make mutation" "Run Infection mutation testing"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make demo" "Launch the interactive component demo"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make check" "cs-check + stan + test (CI gate)"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make check-full" "check + coverage + mutation"
@printf "$(CYAN)%-20s$(RESET) %s\n" "make clean" "Remove build artifacts and caches"
@echo ""

# ── Dependencies ──────────────────────────────────────────────────────────────
install:
composer install --no-interaction --prefer-dist

# ── Testing ───────────────────────────────────────────────────────────────────
test:
vendor/bin/phpunit --no-coverage

test-unit:
vendor/bin/phpunit --testsuite Unit --no-coverage

test-integration:
vendor/bin/phpunit --testsuite Integration --no-coverage

coverage:
vendor/bin/phpunit --coverage-html build/coverage/html --coverage-clover build/coverage/clover.xml
@printf "\n$(GREEN)✔ Coverage report written to build/coverage/html/$(RESET)\n"

# ── Static analysis ───────────────────────────────────────────────────────────
stan:
vendor/bin/phpstan analyse --memory-limit=256M

# ── Code style ────────────────────────────────────────────────────────────────
cs-check:
vendor/bin/php-cs-fixer fix --dry-run --diff --allow-unsupported-php-version=yes --config=php-cs-fixer.php

cs-fix:
vendor/bin/php-cs-fixer fix --allow-unsupported-php-version=yes --config=php-cs-fixer.php
@printf "\n$(GREEN)✔ Code style fixes applied.$(RESET)\n"

# ── Refactoring ───────────────────────────────────────────────────────────────
refactor:
vendor/bin/rector process

# ── Mutation testing ──────────────────────────────────────────────────────────
mutation:
vendor/bin/infection --threads=max --min-msi=60 --min-covered-msi=80

# ── Demo ─────────────────────────────────────────────────────────────────────
demo:
php examples/demo.php

# ── Composite gates ──────────────────────────────────────────────────────────
check: cs-check stan test

check-full: cs-check stan coverage mutation
@printf "\n$(BOLD)$(GREEN)✔ Full quality gate passed.$(RESET)\n"

# ── Clean ─────────────────────────────────────────────────────────────────────
clean:
rm -rf build/ .phpunit.cache .php-cs-fixer.cache .phpstan.cache \
infection.log .rector/ coverage/ coverage-html/ coverage.xml clover.xml
@printf "$(GREEN)✔ Build artifacts removed.$(RESET)\n"
92 changes: 92 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Security Policy

## Supported Versions

Only the latest stable release receives security patches.

| Version | Supported |
|---------|-----------|
| 1.x (latest) | ✅ Yes |
| < 1.0 | ❌ No |

---

## Reporting a Vulnerability

**Please do not open a public GitHub issue for security vulnerabilities.**

We ask that you follow responsible disclosure practices and report security issues privately so we can prepare a fix before public disclosure.

### How to report

Send an email to **shamavurasheed@gmail.com** with:

- **Subject line:** `[SECURITY] php-io-cli — <brief description>`
- A clear description of the vulnerability
- Steps to reproduce (proof-of-concept code is welcome)
- The potential impact in your assessment
- The version(s) affected

We use PGP-encrypted email if you prefer — ask for our public key in a separate (non-sensitive) message first.

### What to expect

| Timeline | Action |
|----------|--------|
| **Within 48 hours** | We acknowledge receipt of your report |
| **Within 7 days** | We assess severity and confirm whether we can reproduce |
| **Within 30 days** | We aim to release a patch (complex issues may take longer) |
| **After the patch is released** | We publicly credit the reporter (unless you prefer anonymity) |

If we cannot reproduce the issue or determine it to be out of scope, we will explain why.

---

## Scope

### In scope

- Code execution vulnerabilities in the library itself
- Unintended information disclosure via `Shell::run()`, `ConsoleIO`, or `BufferIO`
- Escape-sequence injection that could hijack a host terminal session
- Dependency vulnerabilities that affect `php-io-cli` users when installed as a library

### Out of scope

- Vulnerabilities in downstream applications that happen to use this library
- Issues that require physical access to the machine running the CLI
- Social engineering attacks
- Bugs without a security impact (please open a regular issue instead)

---

## Security considerations for users

### Shell::run()

`Shell::run()` executes arbitrary shell commands via `proc_open`. **Never pass unsanitised user input as the `$command` argument.** Always construct commands from trusted, fixed strings, and validate any user-supplied values before interpolating them.

```php
// ❌ Unsafe — user controls $branch
Shell::run("git checkout {$branch}");

// ✅ Safe — validate before use
if (!preg_match('/^[a-zA-Z0-9._\-\/]+$/', $branch)) {
throw new \InvalidArgumentException('Invalid branch name');
}
Shell::run('git checkout ' . escapeshellarg($branch));
```

### Terminal raw mode

`Terminal::enableRaw()` disables canonical input processing and echo. The library registers a shutdown function and signal handlers to restore the terminal on exit. If your application forks or spawns child processes while a component is running, ensure child processes do not inherit the raw-mode state of the parent.

### BufferIO in production

`BufferIO` is designed for testing. Do not use it in production environments, as it writes everything to an in-memory `php://memory` stream and may buffer sensitive data (passwords, tokens) in process memory longer than necessary.

---

## Acknowledgements

We are grateful to the security researchers and community members who help keep this project safe. Confirmed reporters will be listed here (with permission) after the relevant patch is released.
Loading
Loading