security-testing
Skill4 starsChanged 4 months agoMITView on GitHub
Test the security of a PHP application — assert authentication and authorization, cover injection and CSRF, verify 401/403/429 responses, write negative and abuse tests, add fuzzing and property checks, and place SAST/DAST in the pipeline with Pest or PHPUnit security assertions. Use when the user wants to write tests that assert authentication and authorization — who can reach an endpoint and who gets 401 or 403; the user wants to test that the app resists injection and malicious input — SQL injection, XSS payloads, path traversal, and other untrusted-input attacks; the user wants to assert security response codes and behavior — 401 unauthenticated, 403 forbidden, 429 rate-limited, and CSRF-token rejection. Keywords: security, security-testing, authorization, authentication, injection, csrf, input, negative-tests, sast, dast, testing.
9 other projects use a version of this.
Adopted by
Most recently taken up by
- joe-qai/qa-skillstheir own version, first seen Nov 8, 2026
- petrkindlmann/qa-skillstheir own version, first seen Oct 25, 2026
- proffesor-for-testing/agentic-qetheir own version, first seen Oct 25, 2026
- mejbaurbahar/software-tester-skillstheir own version, first seen Oct 13, 2026
- d-padmanabhan/agent-engineering-handbooktheir own version, first seen Sep 18, 2026
- mejbaurbahar/faguntheir own version, first seen Jul 5, 2026
Used with
Projects with it also use mobile-testing, database-testing and 5 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
petrkindlmannSkillmobile-testing
Test native, React Native, hybrid, and Flutter mobile apps with Appium 3.x, Detox, Maestro, and Patrol. Covers device farm setup (BrowserStack, Sauce Labs), gesture simulation, deep link and cold-start testing, push notifications, biometric (Face ID) auth, offline/poor-network simulation, and iOS/Android permission dialog handling. Use when: "mobile test," "Appium," "Detox," "Maestro," "Patrol," "Flutter test," "iOS test," "Android test," "device farm," "deep link," "biometric," "Face ID," "permission dialog," "React Native test." Not for: device/browser matrix strategy in the abstract — use cross-browser-testing; app startup/memory/battery profiling depth — use performance-testing; mobile screenshot diffing — use visual-testing. Related: ci-cd-integration, cross-browser-testing, performance-testing, test-data-management, test-reliability.
Also in 5 projects that use this
petrkindlmannSkilldatabase-testing
Validate database integrity, test migrations forward and backward, verify schema constraints, manage seed data, detect migration drift, and identify query performance issues. Covers PostgreSQL, MySQL, MongoDB with Prisma, TypeORM, Drizzle, and SQLAlchemy, plus Testcontainers test databases. Use when: "database test," "migration test," "migration rollback," "rollback test," "data integrity," "SQL test," "schema validation," "seed data," "query performance," "Testcontainers." Not for: synthetic data generation/masking at scale — use test-data-management; Docker/IaC test-environment provisioning — use test-environments; SQL injection — use security-testing. Related: test-data-management, test-environments, security-testing, ci-cd-integration.
Also in 4 projects that use this
conorluddySkillaccessibility-testing
WCAG compliance testing and accessibility quality assurance workflows for iOS apps. Use when validating accessibility labels, testing VoiceOver compatibility, checking contrast ratios, or ensuring WCAG 2.1 compliance. Covers accessibility tree analysis, semantic validation, and automated accessibility testing patterns.
Also in 4 projects that use this
nek1987Skillapi-testing
Use when writing tests for backend APIs or frontend flows. Triggers for: unit tests, integration tests, E2E tests, pytest fixtures, TestClient setup, mock data factories, or test coverage analysis. NOT for: testing business logic that doesn't involve API endpoints.
Also in 3 projects that use this
- +3 more from petrkindlmann
Other versions9 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 9
- proffesor-for-testing/agentic-qe★ 524same name
- petrkindlmann/qa-skills★ 209same name
- mn-youssef/security-skills★ 47same name
- joe-qai/qa-skills★ 30same name
- d-padmanabhan/agent-engineering-handbook★ 17same name
- Marnie0415/pi-skills★ 1same name
- mejbaurbahar/fagun★ 1same name
- mejbaurbahar/software-tester-skills★ 1same name
- mmondora/claude-skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository119 other files it gives its agents.
- strategy-bitrix-d7-incrementalSkill
- strategy-explicit-over-magicSkill
- strategy-framework-conventionsSkill
- strategy-legacy-safe-editsSkill
- strategy-minimal-diffSkill
- strategy-no-untested-refactorSkill
- strategy-preserve-public-apiSkill
- strategy-readonly-immutabilitySkill
- strategy-security-firstSkill
- strategy-test-drivenSkill
- openapiSkill
- paginationSkill
- rest-designSkill
- versioningSkill
- cqrsSkill
- dependency-inversionSkill
- hexagonalSkill
- repository-patternSkill
- service-layerSkill
- bitrixSkill
- findings-reportSkill
- laravelSkill
- performanceSkill
- phpSkill
- project-analysisSkill
- refactoringSkill
- roi-prioritizationSkill
- securitySkill
- stack-detectionSkill
- cache-layersSkill
- component-engineSkill
- d7-eventsSkill
- d7-loaderSkill
- d7-orm-queriesSkill
- iblock-elementsSkill
- kernel-main-moduleSkill
- localizationSkill
- controllersSkill
- ormSkill
- validationSkill
- controllersSkill
- query-builderSkill
- routingSkill
- autoload-psr4Skill
- dependency-managementSkill
- scriptsSkill
- connection-poolingSkill
- mysql-indexingSkill
- redisSkill
- transactionsSkill
- ci-github-actionsSkill
- deployment-strategiesSkill
- docker-phpSkill
- env-configSkill
- associationsSkill
- entities-mappingSkill
- orm-basicsSkill
- entity-apiSkill
- module-developmentSkill
- routing-controllersSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. 0 are common, 10 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 7 edited versions we read keep these.
10
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 78
Do not treat automated security tests as a substitute for a scoped manual penetration test or professional audit before a high-risk launch.
- Distinctive: line 80
Do not frame ordinary business-logic or formatting tests as security tests.
- Distinctive: line 132
Verify: Both users and the target resource exist in the test database.
- Distinctive: line 135
Verify: All three status assertions pass against the current policy.
- Distinctive: line 138
Verify: Reintroducing the record into the 403 body fails the test in CI.
- Distinctive: line 153
Verify: The dataset is bound to the test with a Pest dataset or PHPUnit data provider.
- Distinctive: line 156
Verify: Each dataset row runs as its own case and asserts neutralised output.
- Very specific: line 157
Add a taint-aware SAST run (e.g.
- Distinctive: line 159
Verify: Introducing a raw concatenation into a query is caught by SAST in CI.
- Distinctive: line 163
Add tests that a state-changing request without a valid CSRF token or nonce is rejected, and that exceeding the rate limit returns 429 with …
- Distinctive: line 168
Run static analysis security tools (SAST such as Psalm/PHPStan taint analysis) on every push and schedule dynamic scans (DAST such as OWASP …
“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- generated: do not edit — source: knowledge/atoms/testing/security-testing/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->PHP Security Testing
When to use
- The user wants to write tests that assert authentication and authorization — who can reach an endpoint and who gets 401 or 403.
- The user wants to test that the app resists injection and malicious input — SQL injection, XSS payloads, path traversal, and other untrusted-input attacks.
- The user wants to assert security response codes and behavior — 401 unauthenticated, 403 forbidden, 429 rate-limited, and CSRF-token rejection.
When NOT to use
- Do not treat automated security tests as a substitute for a scoped manual penetration test or professional audit before a high-risk launch.
- Do not frame ordinary business-logic or formatting tests as security tests; keep them as plain unit or feature tests.
Core guidance
- Assert the exact status code and no data leak — Assert the precise status (401 vs 403 vs 404 vs 429) and that the response body leaks no protected data, rather than only checking the request "failed".
- Drive injection tests from a payload dataset — Feed a dataset of known-malicious inputs (SQLi, XSS, path traversal, null bytes) into one parameterised test and assert each is rejected or safely neutralised.
- Assert denial, not just success, for every control — For every protected action, write a negative test that the wrong actor is denied (401/403) in addition to the positive test that the right actor succeeds.
Decision Engine
Walk this section before choosing an implementation path.
What is the concern — access control, untrusted input reaching a sink, robustness of
a parser, or whole-app runtime posture?
├── The concern is who may perform an action: → write a feature test hitting the route as each role — assert 200 for the allowed
actor and 401/403 for everyone else, plus no data leak in the denied body.
├── Untrusted input can reach a query, view, or shell: → write a dataset-driven test feeding known SQLi/XSS/traversal payloads and assert
each is parameterised, escaped, or rejected, backed by SAST taint analysis in CI.
├── A parser, decoder, or upload handler must survive hostile input: → add fuzzing or property-based tests that throw random, oversized, and malformed
input and assert no crash, hang, or unintended path — catching DoS and encoding bugs.
└── You need to probe the deployed app's runtime posture: → run a DAST scanner (e.g. OWASP ZAP) against a staging build to catch headers,
misconfig, and reachable endpoints that unit and feature tests never exercise.
Full engine: references/decision-engine.md — Decision Tree, Priority Matrix, Decision Table.
Workflows
Workflow: Authz Suite
Progress:
- [ ] In a Pest/PHPUnit feature test, create the owner (or privileged role) and a second
unrelated user, plus the resource the endpoint protects
- [ ] Hit the route three ways — as the owner (expect 200), as the other user (expect
403), and with no auth (expect 401) — using the app's HTTP test client
- [ ] On the 403 case, additionally assert the response body does not contain the
protected record's fields, then wire the test into CI- In a Pest/PHPUnit feature test, create the owner (or privileged role) and a second
unrelated user, plus the resource the endpoint protects.
- Verify: Both users and the target resource exist in the test database.
- Hit the route three ways — as the owner (expect 200), as the other user (expect
403), and with no auth (expect 401) — using the app's HTTP test client.
- Verify: All three status assertions pass against the current policy.
- On the 403 case, additionally assert the response body does not contain the
protected record's fields, then wire the test into CI.
- Verify: Reintroducing the record into the 403 body fails the test in CI.
Workflow: Injection Suite
Progress:
- [ ] Define a dataset of attack strings — SQLi (`' OR 1=1 --`), XSS
(`<script>alert(1)</script>`), path traversal (`../../etc/passwd`), and a null byte
- [ ] For each payload, submit it through the real endpoint and assert the safe effect —
stored/echoed escaped, no extra query rows, no schema-revealing error
- [ ] Add a taint-aware SAST run (e.g- Define a dataset of attack strings — SQLi (
' OR 1=1 --), XSS (<script>alert(1)</script>), path traversal (../../etc/passwd), and a null byte.- Verify: The dataset is bound to the test with a Pest dataset or PHPUnit data provider.
- For each payload, submit it through the real endpoint and assert the safe effect —
stored/echoed escaped, no extra query rows, no schema-revealing error.
- Verify: Each dataset row runs as its own case and asserts neutralised output.
- Add a taint-aware SAST run (e.g. Psalm
--taint-analysisor PHPStan taint rules) to CI so any new untrusted-to-sink flow fails even without an explicit payload.- Verify: Introducing a raw concatenation into a query is caught by SAST in CI.
Best practices
- Add tests that a state-changing request without a valid CSRF token or nonce is rejected, and that exceeding the rate limit returns 429 with a Retry-After
- For parsers, decoders, and upload handlers, add basic fuzzing or property-based tests that throw random, oversized, and malformed input and assert the code never crashes, hangs, or executes unintended paths
- Run static analysis security tools (SAST such as Psalm/PHPStan taint analysis) on every push and schedule dynamic scans (DAST such as OWASP ZAP) against a staging build, treating both as gates beside your Pest/PHPUnit security tests
Anti-patterns
| Anti-pattern | Why it fails | Do instead |
| Testing your code but ignoring vulnerable dependencies | A large share of real breaches come through vulnerable third-party packages, which<br>your own assertion tests will never surface. | Run a dependency audit (e.g. composer audit) in CI and fail on known-vulnerable<br>packages alongside your security test suite. |
| Using real credentials or PII in security tests | Test code is widely readable and often logged; real secrets in fixtures leak into<br>repos, CI logs, and screenshots, creating the very exposure you are testing against. | Generate disposable fixtures and fake credentials, and load any needed test secrets<br>from an isolated, non-production secret store. |
| Treating a scanner as the whole strategy | Generic scanners miss application-specific authorization and business-logic flaws<br>because they do not know your roles, ownership, or intended behavior. | Pair scanners with hand-written authz, injection, and abuse tests that encode your<br>domain's specific security rules. |
See references/anti-patterns.md.
Debugging
- Protections disabled globally in the test env — Disabling a protection to make ordinary feature tests simpler means a regression in that protection produces no failing test anywhere. Fix: Keep protections enabled and, where they get in the way, bypass them per-test via an explicit helper while retaining dedicated tests that exercise them.
- Only the authorized path is tested — The deny branch is the security-relevant one; without it, removing a policy check or a middleware goes unnoticed until it is exploited in production. Fix: For every positive access test add a negative one that asserts 401/403 for an actor who must not have access.
- Injection test asserts status, not effect — For most injection classes a 200 is expected either way; the security property is whether the payload was neutralised, not whether the request completed. Fix: Assert the safe effect — the value is stored/rendered escaped, the query returns no extra rows, and no error discloses the schema.
Production checklist
- A tokenless write is asserted rejected and exceeding the limit returns 429 with Retry-After.
- Each protected action has a negative test proving the wrong actor gets 401 or 403.
- A shared malicious-input dataset (SQLi, XSS, traversal) drives a parameterised test asserting safe handling.
- Security tests use disposable fixtures and fake credentials, never real production secrets or live PII.
- Static security analysis (taint-aware SAST) runs on every push and fails the build on new findings.
- Denied responses assert the exact status code and that no protected data appears in the body.
Version notes
- composer audit ships with Composer 2.4+ (PHP >=8.1) —
composer auditfor scanning installed packages against the advisory database is built in from Composer 2.4; on older Composer use theroave/security-advisoriespackage or thelocal-php-security-checkerbinary instead. - Pest arch presets help enforce security invariants (PHP >=8.1) — Pest 2+ arch tests (
arch()->expect(...)) and Pest 3's expanded presets let you assert security invariants such as "no debug functions" or "controllers depend on a policy", complementing per-request security tests.
Security
- Keep attack payloads and secrets out of production paths — Run security tests only against an isolated test database and disposable fixtures, never against production or a shared staging store, and keep attack payloads and any test secrets out of source that ships to production.
Testing
- Activation and decision behavior are verified in
eval/scenarios/testing/security-testing.yaml. - Assert the precise status (401 vs 403 vs 404 vs 429) and that the response body leaks no protected data, rather than only checking the request "failed".
- Add tests that a state-changing request without a valid CSRF token or nonce is rejected, and that exceeding the rate limit returns 429 with a Retry-After.
- Feed a dataset of known-malicious inputs (SQLi, XSS, path traversal, null bytes) into one parameterised test and assert each is rejected or safely neutralised.
- For parsers, decoders, and upload handlers, add basic fuzzing or property-based tests that throw random, oversized, and malformed input and assert the code never crashes, hangs, or executes unintended paths.
- Run static analysis security tools (SAST such as Psalm/PHPStan taint analysis) on every push and schedule dynamic scans (DAST such as OWASP ZAP) against a staging build, treating both as gates beside your Pest/PHPUnit security tests.
- For every protected action, write a negative test that the wrong actor is denied (401/403) in addition to the positive test that the right actor succeeds.
Additional resources
- references/anti-patterns.md
- references/core.md
- references/decision-engine.md
- references/examples.md
- references/pitfalls.md
- references/recipes.md
- references/version-differences.md
Knowledge graph
Related: security/sql-injection-prevention, testing/pest-basics
<!-- graph-fragment: graph/fragments/testing/security-testing.yaml -->Skill contract
Produces: test.security-suite
Requires: security.owasp-reviewed
Risk: medium · Confidence: 0.85
<!-- contract-fragment: contracts/fragments/testing/security-testing.yaml -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

